@coopenomics/docs-factory 1.0.0 → 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 +80 -106
- package/dist/index.cjs +496 -484
- package/dist/index.d.cts +187 -186
- package/dist/index.d.mts +187 -186
- package/dist/index.d.ts +187 -186
- package/dist/index.mjs +497 -485
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,117 +1,97 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
Фабрика документов
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
1
|
+
# @coopenomics/docs-factory
|
|
2
|
+
|
|
3
|
+
Фабрика документов цифрового кооператива. Собирает юридически значимые документы
|
|
4
|
+
по шаблонам из цепи и данным пайщиков: модель документа → HTML (Nunjucks) → PDF
|
|
5
|
+
(WeasyPrint 67). Хэш документа — SHA-256 PDF; повторная сборка по метаданным даёт
|
|
6
|
+
тот же документ байт в байт.
|
|
7
|
+
|
|
8
|
+
Пакет вынесен из монорепозитория `C9S/mono` 29.10.2026 (шаг 6а фабрики v2).
|
|
9
|
+
Прежнее имя `@coopenomics/factory` устарело.
|
|
10
|
+
|
|
11
|
+
## Что внутри
|
|
12
|
+
|
|
13
|
+
- **Сборщики всех видов документов** цифрового кооператива — 92 вида (`src/Actions`).
|
|
14
|
+
Сборщик — объявление: какие данные прочитать на блок документа и как собрать
|
|
15
|
+
из них модель (`defineBuilder`, `src/Builder`).
|
|
16
|
+
- **Версии сборщиков** `major.minor`. Версия пишется в `meta.builder` нового
|
|
17
|
+
документа; пересборка идёт ровно той версией, что записана в мете. Все версии
|
|
18
|
+
вида документа — в одном файле: `Factory` (1.0) и дописанные в конец
|
|
19
|
+
`Factory_1_1`, `Factory_2_0`. Выпущенная версия заморожена: исправление —
|
|
20
|
+
новый `minor` в конце файла.
|
|
21
|
+
- **Шаблоны документов** — второй пакет репозитория `@coopenomics/docs-templates`
|
|
22
|
+
(`packages/docs-templates`): тексты, схемы, переводы, типы `Action` и `Model`
|
|
23
|
+
каждого вида документа. Выходит одной версией с фабрикой. Фабрика собирает из
|
|
24
|
+
них реестр шаблонов (`src/Templates`) с номерами редакций; ключ `x-builder` в
|
|
25
|
+
схеме редакции объявляет, под какой `major` сборщика она написана.
|
|
26
|
+
- **Порт хранилища** `IFactoryStorage` и реализации: PostgreSQL
|
|
27
|
+
(`PostgresFactoryStorage`, Kysely) и память (`MemoryFactoryStorage`).
|
|
28
|
+
- **Порт данных цепи** `IChainDataSource`: шаблоны, таблицы и действия на блок.
|
|
14
29
|
|
|
15
30
|
## Установка
|
|
16
31
|
|
|
17
|
-
Компонент является частью монорепозитория. Установка зависимостей из корня проекта:
|
|
18
|
-
|
|
19
32
|
```bash
|
|
20
|
-
pnpm
|
|
33
|
+
pnpm add @coopenomics/docs-factory @coopenomics/docs-templates cooptypes
|
|
21
34
|
```
|
|
22
35
|
|
|
23
|
-
|
|
36
|
+
Версии `docs-factory` и `docs-templates` в приложении ставятся одинаковыми.
|
|
24
37
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
```
|
|
38
|
+
`cooptypes` — зависимость приложения (`peerDependencies`): фабрика берёт тот
|
|
39
|
+
выпуск, что стоит у приложения.
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
Для PDF нужен WeasyPrint 67 в `/venv/bin/python3` и системный шрифт Arial —
|
|
42
|
+
как в образе контроллера (`components/controller/Dockerfile` в `C9S/mono`).
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
## Использование
|
|
32
45
|
|
|
33
|
-
|
|
46
|
+
```ts
|
|
47
|
+
import { Generator, PostgresFactoryStorage } from '@coopenomics/docs-factory'
|
|
34
48
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
| `build` | `pnpm run build` | Сборка библиотеки (unbuild) |
|
|
38
|
-
| `dev` | `pnpm run dev` | Режим разработки с автопересборкой (nodemon) |
|
|
39
|
-
| `test` | `pnpm run test` | Запуск тестов (Vitest) |
|
|
40
|
-
| `lint` | `pnpm run lint` | Проверка кода (ESLint) |
|
|
41
|
-
| `typecheck` | `pnpm run typecheck` | Проверка типов TypeScript |
|
|
42
|
-
| `setup-indexes` | `pnpm run setup-indexes` | Настройка индексов MongoDB |
|
|
49
|
+
const generator = new Generator(chainDataSource) // реализация IChainDataSource
|
|
50
|
+
await generator.connect(new PostgresFactoryStorage({ host, port, user, password, database }))
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
// Новая сборка: версия сборщика — по объявлению действующей редакции шаблона
|
|
53
|
+
const document = await generator.generate({ registry_id: 1, coopname: 'voskhod', username: 'ant', lang: 'ru' })
|
|
45
54
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
pnpm run dev:lib # Режим разработки factory + cooptypes
|
|
49
|
-
pnpm run test:component # Компонентные тесты factory
|
|
55
|
+
// Пересборка по метаданным подписанного документа — тем же сборщиком
|
|
56
|
+
const same = await generator.generate({ ...document.meta }, { skip_save: true })
|
|
50
57
|
```
|
|
51
58
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Хранилище фабрики — порт `IFactoryStorage`; реализации — PostgreSQL (`PostgresFactoryStorage`) и память. Для набора тестов нужен PostgreSQL. Переменные окружения:
|
|
59
|
+
Таблицы хранилища на узле создаёт миграция контроллера; отдельному приложению —
|
|
60
|
+
`await storage.ensureSchema()`.
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
- `SOURCE` — источник данных (`local` для тестов)
|
|
62
|
+
## Разработка
|
|
58
63
|
|
|
59
|
-
|
|
64
|
+
Тесты и эталоны запускаются только в CI (workflow `Factory`, `.github/workflows/factory.yml`)
|
|
65
|
+
на каждый пуш. Локально — сборка и проверки сборщиков:
|
|
60
66
|
|
|
61
|
-
|
|
67
|
+
| Команда | Что делает |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `pnpm build` | сборка (unbuild) с проверкой типов |
|
|
70
|
+
| `pnpm lint` | ESLint |
|
|
71
|
+
| `pnpm check` | полнота экспорта сборщиков, чтения на блок, заморозка версий |
|
|
72
|
+
| `node scripts/x-builder-check.mjs` | `x-builder` не меняется внутри редакции (после `pnpm build`) |
|
|
73
|
+
| `node scripts/golden-coverage.mjs` | у каждого вида документа есть эталон |
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Тестовый набор покрывает генерацию документов различных типов. Тесты требуют запущенный MongoDB и используют таймаут 240 секунд.
|
|
75
|
+
Эталоны — `test/golden/<номер>/<случай>.{html,meta.json,pdf.sha256}`. Пересоздать —
|
|
76
|
+
пуш в ветку `ci/update`, забрать артефакт `factory-golden`, закоммитить; только
|
|
77
|
+
при осознанной смене вывода. Правила для сборщиков — `CLAUDE.md`.
|
|
68
78
|
|
|
69
|
-
|
|
79
|
+
Совместная правка с монорепозиторием: в `C9S/mono` — `pnpm factory:link`
|
|
80
|
+
(подключает этот чекаут, ожидается в `~/docs-factory`) и `pnpm factory:unlink`.
|
|
70
81
|
|
|
71
|
-
|
|
72
|
-
|------|----------|
|
|
73
|
-
| `test/index.test.ts` | Основные тесты генерации документов |
|
|
74
|
-
| `test/wallet.test.ts` | Тесты документов кошелька |
|
|
75
|
-
| `test/meet.test.ts` | Тесты документов собраний |
|
|
76
|
-
| `test/blagorost.test.ts` | Тесты документов программы «Благорост» |
|
|
77
|
-
| `test/market.test.ts` | Тесты документов маркетплейса |
|
|
78
|
-
| `test/search.test.ts` | Тесты поиска документов |
|
|
79
|
-
| `test/udata.test.ts` | Тесты пользовательских данных |
|
|
80
|
-
| `test/documents-1000-plus.test.ts` | Тесты документов с registry_id > 1000 |
|
|
82
|
+
## Выпуск
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
1. Поднять `version` в `package.json` и в `packages/docs-templates/package.json`
|
|
85
|
+
(одна семантическая версия), коммит в `main`.
|
|
86
|
+
2. Тег `vX.Y.Z` (предварительный — `vX.Y.Z-dev.N`) в `C9S/docs-factory`.
|
|
87
|
+
3. Workflow `Release`: проверки Factory → сверка тега с версиями обоих пакетов →
|
|
88
|
+
публикация в npm шаблонов, затем фабрики (предварительная — с меткой `next`) →
|
|
89
|
+
робот открывает PR в `C9S/mono` → `dev` с новой точной версией обоих пакетов во
|
|
90
|
+
всех `package.json` и `pnpm-lock.yaml`.
|
|
83
91
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
├── config.ts # Конфигурация подключений
|
|
88
|
-
├── Actions/ # Генераторы документов (по registry_id)
|
|
89
|
-
│ ├── 1.WalletAgreement.ts
|
|
90
|
-
│ ├── 100.ParticipantApplication.ts
|
|
91
|
-
│ ├── 300.AnnualGeneralMeetingAgenda.ts
|
|
92
|
-
│ ├── 600.FreeDecision.ts
|
|
93
|
-
│ ├── 1001.GenerationContract.ts
|
|
94
|
-
│ └── ... # Более 60 шаблонов
|
|
95
|
-
├── Factory/ # Ядро фабрики документов
|
|
96
|
-
├── Models/ # Модели данных MongoDB
|
|
97
|
-
│ ├── Cooperative.ts
|
|
98
|
-
│ ├── Individual.ts
|
|
99
|
-
│ ├── Organization.ts
|
|
100
|
-
│ ├── Document.ts
|
|
101
|
-
│ └── ...
|
|
102
|
-
└── templates/ # HTML-шаблоны (Nunjucks/Handlebars)
|
|
103
|
-
test/ # Тесты (Vitest)
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Процесс генерации документа
|
|
107
|
-
|
|
108
|
-
1. Загрузка шаблона и JSON Schema из блокчейна
|
|
109
|
-
2. Получение приватных данных из хранилища (MongoDB)
|
|
110
|
-
3. Валидация данных по JSON Schema (Ajv)
|
|
111
|
-
4. Конструирование контекста для шаблона
|
|
112
|
-
5. Рендеринг HTML из Nunjucks/Handlebars-шаблона
|
|
113
|
-
6. Подпись хеша документа EOSIO-ключом
|
|
114
|
-
7. Генерация PDF через WeasyPrint
|
|
92
|
+
Монорепозиторий поднимает версию только этим PR: гейт `pnpm check` держит
|
|
93
|
+
точную и одну версию, контроллер при старте сверяет установленную фабрику с
|
|
94
|
+
объявленной.
|
|
115
95
|
|
|
116
96
|
## Приватные данные документа: `doc_data`
|
|
117
97
|
|
|
@@ -121,7 +101,7 @@ test/ # Тесты (Vitest)
|
|
|
121
101
|
|
|
122
102
|
1. Контроллер собирает приватный payload и вызывает `generator.saveDocData(payload, registry_id)` — возвращается `{ hash }` (sha256, идемпотентный).
|
|
123
103
|
2. `hash` передаётся on-chain в Action под зарезервированным именем `doc_data_hash`.
|
|
124
|
-
3. При
|
|
104
|
+
3. При сборке и пересборке фабрика подгружает payload из хранилища (`getDocData(hash)`) и подставляет в модель документа как `doc_data`.
|
|
125
105
|
4. Шаблон документа использует приватные поля как `{{ doc_data.<field> }}`.
|
|
126
106
|
|
|
127
107
|
### Пример
|
|
@@ -146,14 +126,17 @@ await generator.generate({
|
|
|
146
126
|
})
|
|
147
127
|
```
|
|
148
128
|
|
|
149
|
-
|
|
129
|
+
Сборщик (`src/Actions/1103.MarketplaceTransportNote.ts`) объявляет чтение, каркас его выполняет:
|
|
150
130
|
|
|
151
131
|
```ts
|
|
152
|
-
|
|
153
|
-
|
|
132
|
+
reads: ({ data, f }) => ({
|
|
133
|
+
docData: () => f.loadDocData<TransportNoteDocData>(data),
|
|
134
|
+
// …
|
|
135
|
+
}),
|
|
136
|
+
assemble: ({ meta, reads: { docData } }) => ({ meta, doc_data: docData, /* … */ }),
|
|
154
137
|
```
|
|
155
138
|
|
|
156
|
-
Шаблон (`Templates/1103.MarketplaceTransportNote
|
|
139
|
+
Шаблон (`src/Templates/1103.MarketplaceTransportNote.ts`):
|
|
157
140
|
|
|
158
141
|
```html
|
|
159
142
|
<tr><th>Экспедитор</th><td>{{ doc_data.expeditor_full_name }}</td></tr>
|
|
@@ -174,22 +157,13 @@ const combinedData = { ...base, doc_data }
|
|
|
174
157
|
|
|
175
158
|
### Graceful degradation
|
|
176
159
|
|
|
177
|
-
Если
|
|
160
|
+
Если приватные данные удалены (например, по запросу пайщика), документ остаётся **верифицируемым по хэшу подписи** (хэш зафиксирован on-chain), но не регенерируется. Это явное архитектурное решение: ценность блокчейн-подписи сохраняется; восстановление PDF — обратимо deprecated.
|
|
178
161
|
|
|
179
162
|
### Когда применять
|
|
180
163
|
|
|
181
164
|
- **Новые документы** с персональными данными — сразу через `doc_data`.
|
|
182
165
|
- **Существующие документы** (700-1099, 300-304 и т.д.) — остаются без изменений. Паттерн прогрессивный, переводить старые документы при отсутствии необходимости не нужно.
|
|
183
166
|
|
|
184
|
-
## Ключевые зависимости
|
|
185
|
-
|
|
186
|
-
- **nunjucks / handlebars** — шаблонизаторы
|
|
187
|
-
- **ajv** — валидация JSON Schema
|
|
188
|
-
- **mongodb** — хранилище данных
|
|
189
|
-
- **eosjs-ecc** — криптографические операции EOSIO
|
|
190
|
-
- **pdf-lib** — работа с PDF
|
|
191
|
-
- **unbuild** — сборка библиотеки
|
|
192
|
-
|
|
193
167
|
## Лицензия
|
|
194
168
|
|
|
195
169
|
[BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.ru)
|