letopis 0.20.3 → 1.0.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.
Files changed (89) hide show
  1. package/AGENT-CHEATSHEET.en.md +368 -0
  2. package/AGENT-CHEATSHEET.md +354 -0
  3. package/CHANGELOG.md +348 -0
  4. package/MIGRATION.md +190 -0
  5. package/README.en.md +1937 -0
  6. package/README.md +1493 -3466
  7. package/dist/acl.d.ts +26 -50
  8. package/dist/acl.js +22 -267
  9. package/dist/admin.d.ts +138 -0
  10. package/dist/admin.js +170 -0
  11. package/dist/auth.d.ts +120 -73
  12. package/dist/auth.js +121 -306
  13. package/dist/cache.d.ts +73 -0
  14. package/dist/cache.js +148 -0
  15. package/dist/chain.d.ts +124 -191
  16. package/dist/chain.js +369 -551
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +164 -0
  19. package/dist/demo/booking.d.ts +289 -0
  20. package/dist/demo/booking.js +159 -0
  21. package/dist/errors.d.ts +29 -0
  22. package/dist/errors.js +70 -0
  23. package/dist/import.d.ts +179 -0
  24. package/dist/import.js +792 -0
  25. package/dist/index.d.ts +172 -26
  26. package/dist/index.js +304 -178
  27. package/dist/jsonschema.d.ts +22 -0
  28. package/dist/jsonschema.js +167 -0
  29. package/dist/load.d.ts +76 -0
  30. package/dist/load.js +884 -0
  31. package/dist/model.d.ts +166 -0
  32. package/dist/model.js +224 -0
  33. package/dist/ops.d.ts +7 -6
  34. package/dist/ops.js +7 -51
  35. package/dist/pglite.d.ts +22 -0
  36. package/dist/pglite.js +45 -0
  37. package/dist/registry.d.ts +57 -0
  38. package/dist/registry.js +82 -0
  39. package/dist/sql.d.ts +59 -142
  40. package/dist/sql.js +568 -654
  41. package/dist/sync.d.ts +31 -0
  42. package/dist/sync.js +108 -0
  43. package/dist/tx.d.ts +129 -8
  44. package/dist/tx.js +300 -73
  45. package/dist/typed.d.ts +97 -0
  46. package/dist/typed.js +1 -0
  47. package/dist/types.d.ts +71 -250
  48. package/dist/types.js +27 -108
  49. package/dist/up.d.ts +140 -47
  50. package/dist/up.js +339 -267
  51. package/dist/uuid.d.ts +21 -6
  52. package/dist/uuid.js +48 -64
  53. package/dist/validate.d.ts +24 -0
  54. package/dist/validate.js +251 -0
  55. package/dist/watch.d.ts +62 -0
  56. package/dist/watch.js +168 -0
  57. package/dist/write.d.ts +117 -74
  58. package/dist/write.js +658 -720
  59. package/llms.txt +26 -0
  60. package/package.json +49 -19
  61. package/sql/10-core.sql +136 -0
  62. package/sql/15-errors.sql +60 -0
  63. package/sql/20-context.sql +153 -0
  64. package/sql/30-validate.sql +423 -0
  65. package/sql/40-class.sql +259 -0
  66. package/sql/50-acl.sql +539 -0
  67. package/sql/60-write.sql +1369 -0
  68. package/sql/70-read.sql +245 -0
  69. package/sql/80-auth.sql +827 -0
  70. package/sql/90-time.sql +957 -0
  71. package/sql/95-seed.system.sql +178 -0
  72. package/sql/99-revision.sql +3 -0
  73. package/sql/README.md +56 -0
  74. package/sql/seed.booking.sql +39 -112
  75. package/dist/schema.d.ts +0 -15
  76. package/dist/schema.js +0 -351
  77. package/dist/sessions.d.ts +0 -32
  78. package/dist/sessions.js +0 -114
  79. package/dist/tables.d.ts +0 -105
  80. package/dist/tables.js +0 -248
  81. package/docker/Dockerfile +0 -40
  82. package/docker/start.sh +0 -18
  83. package/scripts/check-docs.mjs +0 -375
  84. package/scripts/gen-api-contract.mjs +0 -226
  85. package/scripts/gen-types.mjs +0 -350
  86. package/scripts/release-notes.mjs +0 -76
  87. package/scripts/schema-sync.mjs +0 -185
  88. package/sql/ddl.sql +0 -600
  89. package/sql/seed.auth.sql +0 -73
package/dist/index.d.ts CHANGED
@@ -1,29 +1,175 @@
1
1
  /**
2
- * letopis: dot-цепочки над append-only Entity-хранилищем (TimescaleDB).
2
+ * letopis 1.0 — основная точка входа пакета. Руководство — README.md пакета, машинный каталог API —
3
+ * docs/api-contract.json репозитория; решения и их причины — reports/PLAN-LETOPIS-1.0.md (этапы ниже).
3
4
  *
4
- * schema — ПОЛНОЕ имя PG-схемы С версией движка ("v1.booking"); префикс либа НЕ достраивает
5
- * (создаёт up({ schema: 'booking', version: 1 }) либо db/apply.mjs). Шаг цепочки — id ИЛИ
6
- * alias класса из таблицы Schema (db.Staff ≡ db.Мастер).
7
- *
8
- * const db = await connect({ dsn, schema: 'v1.booking' }) // безличный пул
9
- * const t = await db.as(accountId) // арендатор ВЫЗОВА
10
- * await t.Мастер({ name: 'Вася' }).навык().Услуга().run()
5
+ * Этап 2: connect() — подключение под сессией, реестр классов, отложенный сигнал, db.sql.
6
+ * Этап 3: цепочки чтения t.Класс(…).Связь().rows(); этап 4 — запись цепочками и загрузчик.
7
+ * Этап 5: db.auth (креды, вход, сессии), db.acl, db.as(аккаунт, { tenant }) — имперсонация.
8
+ * Этап 6: история (restore, purge, rekey, trimHistory), verify, maintain, reset, watch, кэш результатов.
11
9
  */
12
- import { type EntityDb } from './chain.js';
13
- import type { ConnectOpts } from './types.js';
14
- export declare function connect(opts: ConnectOpts): Promise<EntityDb>;
15
- /** Курсор keyset-пагинации из последней строки страницы (field как в .sort(), вложенные пути поддержаны). */
16
- export declare function cursorOf(row: import('./types.js').Row, field?: string): import('./types.js').Cursor;
17
- export { up } from './up.js';
18
- export type { UpOpts } from './up.js';
19
- export { uuidv5, uuidv7, LETOPIS_NS } from './uuid.js';
20
- export { ne, gt, gte, lt, lte, between, inList, like, ilike, starts, ends, has, hasAny, hasAll, exists, isNull, not, or, } from './ops.js';
21
- export type { Row, Path, Filter, ChainMods, Cursor, ConnectOpts, QueryEvent, Account, Credential, Resource, Rule, AclOp, AclDecision, } from './types.js';
22
- export type { EntityDb, EntityTx, Chain, Batch, WatchEvent, WatchOpts } from './chain.js';
23
- export type { Tables, AccountsApi, CredentialsApi, ResourcesApi, RulesApi, SchemaApi } from './tables.js';
24
- export { totpCode } from './auth.js';
25
- export type { AuthApi, AuthResult } from './auth.js';
26
- export type { AclApi } from './acl.js';
27
- export type { SessionStore, Sessions, Session } from './sessions.js';
28
- export { ValidationError } from './write.js';
29
- export { Registry } from './schema.js';
10
+ import postgres from 'postgres';
11
+ import { Registry } from './registry.js';
12
+ import { type Tx } from './tx.js';
13
+ import { type AuthApi } from './auth.js';
14
+ import { type AclApi } from './acl.js';
15
+ import { type LoadInput, type LoadOptions, type LoadReport } from './load.js';
16
+ import { type Batch, type Chain, type StepFn } from './chain.js';
17
+ import type { QueryEvent, Row } from './types.js';
18
+ import { type CacheOptions, type CacheStats } from './cache.js';
19
+ import { Subscription, type WatchOptions } from './watch.js';
20
+ import { type MaintainOptions, type MaintainReport, type ModelDescription, type ResetOptions, type ResetResult, type VerifyResult } from './admin.js';
21
+ import type { AnyModelLike, StepsOf } from './typed.js';
22
+ export { DDL_REVISION } from './types.js';
23
+ export { uuidv5, v5Name, v5Id, idOf, type KeyedClass } from './uuid.js';
24
+ export { LetopisError, ValidationError, fromDbError, type Issue } from './errors.js';
25
+ export { Registry, type ClassInfo, type EndInfo, type LeafType } from './registry.js';
26
+ export { compileValidator, applyDefaults, type Validator } from './validate.js';
27
+ export { syncModels, generateTypes, schemaToTs, type SyncResult } from './sync.js';
28
+ export { ne, gt, gte, lt, lte, between, inList, like, ilike, starts, ends, has, hasAny, hasAll, exists, isNull, not, or, isOp } from './ops.js';
29
+ export { cursorOf } from './sql.js';
30
+ export { inc, isInc, type IncMarker, type WriteRow } from './write.js';
31
+ export { totpCode, hashPassword, verifyHash, type AuthApi, type LoginResult, type Credential } from './auth.js';
32
+ export type { AclApi, AclDecision, AclDataDecision, AclOp } from './acl.js';
33
+ export type { LoadOptions, LoadReport, LoadIssue, LoadInput } from './load.js';
34
+ export type { Chain, ChainCore, StepFn, BatchEntry } from './chain.js';
35
+ export type { ModelLike, AnyModelLike, RowOf, FilterOf, FieldFilterOf, TypedChain, StepsOf, PatchOf } from './typed.js';
36
+ export type { Row, Path, Filter, FieldFilter, Cursor, ChainMods, QueryEvent, Op, Scalar } from './types.js';
37
+ export type { CacheOptions, CacheStats } from './cache.js';
38
+ export type { WatchOptions, WatchEvent, Subscription } from './watch.js';
39
+ export type { VerifyResult, VerifyIssue, MaintainOptions, MaintainReport, ResetOptions, ResetResult, ModelDescription } from './admin.js';
40
+ export { describeText } from './admin.js';
41
+ export { up, createTenant, type UpOptions, type UpResult, type HistoryPolicy, type TenantOptions, type TenantResult } from './up.js';
42
+ export { RESERVED_CLASS_NAMES, CHAIN_METHODS, DB_METHODS } from './types.js';
43
+ /** Снесено в 1.0.0: id v7 больше не выдаются (§2.3). */
44
+ export declare function uuidv7(): never;
45
+ /** Снесено в 1.0.0: пространство имён v5 — id арендатора. Любое использование значения — ошибка. */
46
+ export declare const LETOPIS_NS: string;
47
+ export interface ConnectOptions {
48
+ /** Строка подключения; либо готовый пул postgres.js в `sql`. */
49
+ dsn?: string;
50
+ sql?: postgres.Sql;
51
+ /** Схема установки, например `v2.salon`. */
52
+ schema: string;
53
+ /** Токен сессии; либо ключ APIKEY в `apiKey` (он же `service` — ключ сервиса) — его обменяют на сессию. */
54
+ token?: string;
55
+ apiKey?: string;
56
+ service?: string;
57
+ /** Продлевать сессию раз в минуту работы (по умолчанию да, §2.9). */
58
+ refreshSession?: boolean;
59
+ /** Разрешить роль, которая обходит RLS (суперпользователь, BYPASSRLS, член роли-владельца), — администраторское подключение (§2.9). */
60
+ allowBypassRls?: boolean;
61
+ /** Имя роли-владельца (по умолчанию letopis_owner). */
62
+ owner?: string;
63
+ /** Интервал отправки отложенного сигнала, мс (по умолчанию 100; решение 9 точки А). */
64
+ notifyIntervalMs?: number;
65
+ /** Размер пула, если подключение создаёт сам connect(). */
66
+ max?: number;
67
+ /** Хук на каждый запрос цепочки (метрики, лог). */
68
+ onQuery?: (e: QueryEvent) => void;
69
+ /** Порог медленного запроса, мс: событие получает slow; без onQuery — console.warn. */
70
+ slowMs?: number;
71
+ /** Модели letopis/model — только для типов цепочек (TypedDb); описания классов берутся из базы. */
72
+ models?: readonly AnyModelLike[];
73
+ /**
74
+ * Слушать сигналы базы (LISTEN, по умолчанию да). false — пул в режиме транзакций (PgBouncer):
75
+ * реестр перечитывается через db.refresh(), подписка опрашивает журнал, кэш результатов выключен
76
+ * (с cache: { ttlOnly: true } — работает только по сроку).
77
+ */
78
+ listen?: boolean;
79
+ /** Кэш результатов (§2.12): срок по умолчанию, размер, ttlOnly; false — выключен. */
80
+ cache?: CacheOptions | false;
81
+ /** Запускать maintain() по расписанию ('1h', '15m', мс) под advisory-блокировкой: работает один процесс. */
82
+ maintain?: string | number;
83
+ }
84
+ export interface DbCore {
85
+ readonly schema: string;
86
+ readonly token: string | null;
87
+ /** Арендатор сессии. */
88
+ readonly tenant: string | null;
89
+ readonly registry: Registry;
90
+ /** Креды, вход и сессии (этап 5). */
91
+ readonly auth: AuthApi;
92
+ /** Решения прав: check(endpoint), checkData(class, op) (этап 5). */
93
+ readonly acl: AclApi;
94
+ /** Сырой SQL под сессией и RLS, одной транзакцией (в db.begin() — в ней): db.sql`select …`. */
95
+ sql(strings: TemplateStringsArray, ...values: unknown[]): Promise<postgres.Row[]>;
96
+ /** Транзакция под сессией: fn получает соединение postgres.js (в db.begin() — ту же транзакцию). */
97
+ transaction<T>(fn: (tx: Tx) => Promise<T>): Promise<T>;
98
+ /** id объекта класса с ключом в арендаторе сессии. */
99
+ idOf(cls: string, key: Readonly<Record<string, unknown>>): string;
100
+ /** Перечитать описания классов. */
101
+ refresh(): Promise<void>;
102
+ /** Отправить накопленные сигналы сейчас. */
103
+ flushSignals(): Promise<void>;
104
+ /**
105
+ * Проверка цепочек хэшей и якорь (хэш всех голов); { data: true } — ещё данные, концы, арендаторы,
106
+ * владельцы и id всех строк. Только системный администратор или администраторское подключение.
107
+ */
108
+ verify(opts?: {
109
+ data?: boolean;
110
+ }): Promise<VerifyResult>;
111
+ /** Обслуживание: истёкшие сессии и коды, прореживание журнала по политике хранения, очередь сигналов. */
112
+ maintain(opts?: MaintainOptions): Promise<MaintainReport>;
113
+ /** Сброс sessions | tenant | all (allowReset установки, право letopis.reset, confirm — имя схемы). */
114
+ reset(opts: ResetOptions): Promise<ResetResult>;
115
+ /** Обрезка истории до момента: класса (с потомками), id, списка id или строк; версия 1 → запись trim. */
116
+ trimHistory(target: string | string[] | Row | Row[], before: string | Date): Promise<number>;
117
+ /** Новый ключ класса: строки семейства переносятся на новые id, ссылки переводятся. */
118
+ rekeyClass(cls: string, key: string[]): Promise<number>;
119
+ /** Машинное описание модели с метаданными классов (describeText — то же текстом, llms.txt). */
120
+ describe(): ModelDescription;
121
+ /** Подписка по курсору: for await (const ev of db.watch({ from })) …; ev.cursor — откуда продолжить. */
122
+ watch(opts?: WatchOptions): Subscription;
123
+ /** Кэш результатов подключения. */
124
+ readonly cache: {
125
+ clear(): void;
126
+ stats(): CacheStats;
127
+ };
128
+ /** Начать путь с готового узла: db.entity(row | цепочка). */
129
+ entity(x: Chain | Row): Chain;
130
+ /**
131
+ * Тот же пул от имени аккаунта (letopis.account: имперсонацию проверяет база — право сервиса
132
+ * auth.impersonate), в арендаторе tenant (собственный аккаунта или по членству) и с явным владельцем
133
+ * новых строк: await db.as(account, { tenant, owner }). account = null — тот же актор.
134
+ */
135
+ as(account: string | {
136
+ id: string;
137
+ } | null, opts?: {
138
+ owner?: string;
139
+ tenant?: string;
140
+ }): Promise<Db>;
141
+ /** Явная транзакция read committed: те же цепочки, commit(), rollback(), lock(), forUpdate(). */
142
+ begin(): Promise<DbTx>;
143
+ /**
144
+ * Загрузчик (§2.6): строки любых классов — проверки в коде, COPY от роли владельца, один запрос по
145
+ * целям вне загрузки. Только на администраторском подключении (иначе admin_required).
146
+ */
147
+ load(input: LoadInput, opts?: LoadOptions): Promise<LoadReport>;
148
+ /**
149
+ * Именованная очередь планов фасада: batch.Класс(…).create(…); batch.run() — одной транзакцией. У корня,
150
+ * у каждого db.as() и у каждой db.begin() очереди свои: план исполняется от имени фасада, который его поставил.
151
+ */
152
+ batch(name: string): Batch;
153
+ /** Advisory-блокировка до конца транзакции — только в db.begin() (иначе tx_required). */
154
+ lock(...keys: (string | number)[]): Promise<void>;
155
+ /** Зафиксировать транзакцию tr (то же, что tr.commit()). */
156
+ commit(tr?: DbTx): Promise<void>;
157
+ /** Откатить транзакцию tr (то же, что tr.rollback()). */
158
+ rollback(tr?: DbTx): Promise<void>;
159
+ close(): Promise<void>;
160
+ }
161
+ /** Подключение: служебные методы и классы как стартовые шаги цепочек — db.Класс(фильтр). */
162
+ export type Db = DbCore & {
163
+ [className: string]: StepFn;
164
+ };
165
+ /** Явная транзакция db.begin(): тот же API; ошибка любого запроса её ломает (§2.5). */
166
+ export type DbTx = Db;
167
+ /** Подключение с типами шагов, строк и фильтров по моделям: connect({ models }). */
168
+ export type TypedDb<M extends readonly AnyModelLike[]> = DbCore & StepsOf<M> & {
169
+ [className: string]: StepFn;
170
+ };
171
+ export type { Batch };
172
+ export declare function connect<const M extends readonly AnyModelLike[]>(opts: ConnectOptions & {
173
+ models: M;
174
+ }): Promise<TypedDb<M>>;
175
+ export declare function connect(opts: ConnectOptions): Promise<Db>;