runlify 0.0.794 → 0.0.797

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 (58) hide show
  1. package/build/cli.js +8 -2
  2. package/build/projectsGeneration/builders/generationPaths.js +44 -1
  3. package/build/projectsGeneration/generateProject/back/src/generateBackSrc.js +11 -2
  4. package/build/projectsGeneration/generateProject/fileHandlers.js +6 -2
  5. package/build/projectsGeneration/generateProject/front/generateFrontSrc.js +10 -1
  6. package/build/projectsGeneration/generateProject/front/translations/generateFrontSrcTranslations.js +33 -1
  7. package/build/projectsGeneration/generateProject/generateBackClickHouseBootstrap.js +1 -4
  8. package/build/projectsGeneration/generateProject/utils.js +2 -2
  9. package/build/projectsGeneration/generators/fileTemplates/back/clickhouse/jobs.js +41 -4
  10. package/build/projectsGeneration/generators/fileTemplates/back/roles/customPermissions.js +12 -0
  11. package/build/projectsGeneration/generators/fileTemplates/back/roles/customUiPermissions.js +13 -0
  12. package/build/projectsGeneration/generators/fileTemplates/back/roles/initPermissions.js +31 -0
  13. package/build/projectsGeneration/generators/fileTemplates/back/roles/uiPermissions.js +24 -0
  14. package/build/projectsGeneration/generators/fileTemplates/ui/NotFoundPage.js +6 -0
  15. package/build/projectsGeneration/generators/fileTemplates/ui/PermissionPage.js +6 -0
  16. package/build/projectsGeneration/generators/fileTemplates/ui/environment/src/layout/Menu.js +1 -1
  17. package/build/projectsGeneration/generators/fileTemplates/ui/environment/src/routes.js +5 -5
  18. package/build/projectsGeneration/generators/fileTemplates/ui/getDefaultMenu.js +5 -1
  19. package/build/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nIndexTmpl.js +35 -0
  20. package/build/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nTypesTmpl.js +33 -0
  21. package/build/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nValidationTmpl.js +38 -0
  22. package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityCreate/DefaultEntityCreate.js +16 -5
  23. package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityEdit/DefaultEntityEdit.js +27 -11
  24. package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityList/DefaultEntityFilter.js +13 -4
  25. package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityList/DefaultEntityList.js +14 -7
  26. package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityShow/DefaultMainTab.js +13 -4
  27. package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityShow/DependencyTab.js +12 -3
  28. package/build/projectsGeneration/generators/fileTemplates/ui/resources.js +21 -8
  29. package/build/projectsGeneration/generators/fileTemplates/ui/utils/permissions.js +89 -0
  30. package/build/projectsGeneration/generators/ui/getShowComponent.js +2 -2
  31. package/build/types/projectsGeneration/builders/generationPaths.d.ts +42 -0
  32. package/build/types/projectsGeneration/generateProject/fileHandlers.d.ts +1 -0
  33. package/build/types/projectsGeneration/generateProject/types.d.ts +1 -1
  34. package/build/types/projectsGeneration/generateProject/utils.d.ts +1 -1
  35. package/build/types/projectsGeneration/generators/fileTemplates/back/roles/customPermissions.d.ts +2 -0
  36. package/build/types/projectsGeneration/generators/fileTemplates/back/roles/customUiPermissions.d.ts +2 -0
  37. package/build/types/projectsGeneration/generators/fileTemplates/back/roles/initPermissions.d.ts +2 -0
  38. package/build/types/projectsGeneration/generators/fileTemplates/back/roles/uiPermissions.d.ts +3 -0
  39. package/build/types/projectsGeneration/generators/fileTemplates/ui/NotFoundPage.d.ts +2 -0
  40. package/build/types/projectsGeneration/generators/fileTemplates/ui/PermissionPage.d.ts +2 -0
  41. package/build/types/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nIndexTmpl.d.ts +2 -0
  42. package/build/types/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nTypesTmpl.d.ts +3 -0
  43. package/build/types/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nValidationTmpl.d.ts +2 -0
  44. package/build/types/projectsGeneration/generators/fileTemplates/ui/pages/EntityEdit/DefaultEntityEdit.d.ts +1 -0
  45. package/build/types/projectsGeneration/generators/fileTemplates/ui/utils/permissions.d.ts +2 -0
  46. package/docs/01-overview.md +172 -0
  47. package/docs/02-system-meta-builder.md +405 -0
  48. package/docs/03-entity-types.md +471 -0
  49. package/docs/04-fields.md +357 -0
  50. package/docs/05-custom-methods.md +249 -0
  51. package/docs/06-storage.md +129 -0
  52. package/docs/07-backend-file-graph.md +231 -0
  53. package/docs/08-frontend-file-graph.md +260 -0
  54. package/docs/09-options.md +213 -0
  55. package/docs/10-modules.md +164 -0
  56. package/docs/11-permissions.md +231 -0
  57. package/docs/INDEX.md +70 -0
  58. package/package.json +1 -1
@@ -0,0 +1,172 @@
1
+ # Overview & Mental Model
2
+
3
+ > **Load this file when:** you need to understand how Runlify works end-to-end,
4
+ > or when you need to orient yourself in a Runlify-powered project for the first time.
5
+
6
+ ---
7
+
8
+ ## What Runlify is
9
+
10
+ Runlify is a **metadata-driven full-stack code generator**. A consumer describes their
11
+ system declaratively using a fluent builder API (`SystemMetaBuilder`). Runlify generates
12
+ two complete sibling projects from that description plus all deployment infrastructure.
13
+
14
+ ```
15
+ meta-project/ ← you own this
16
+ src/meta/metadata.ts ← SystemMetaBuilder DSL — the source of truth
17
+ src/meta/options.json ← BootstrapEntityOptions — generation switches
18
+
19
+ runlify regen
20
+ │
21
+ ┌────────┴────────┐
22
+ ▼ ▼
23
+ <prefix>-back/ <prefix>-ui/
24
+ NestJS/Prisma react-admin
25
+ GraphQL TypeScript/React
26
+ ```
27
+
28
+ The meta project is **not deployed**. It is a build tool. The two generated projects are
29
+ what actually runs in production.
30
+
31
+ ---
32
+
33
+ ## Data flow
34
+
35
+ ```
36
+ SystemMetaBuilder
37
+ .addCatalog(...)
38
+ .addDocument(...)
39
+ .addMethod(...)
40
+ .build() ← produces a System object
41
+
42
+ System ──serialize──▶ src/meta/metadata.json
43
+ BootstrapEntityOptions ──▶ src/meta/options.json
44
+
45
+ runlify regen
46
+ │
47
+ ├─ reads metadata.json + options.json
48
+ ├─ prepareProjectWideGenerationArgs() ← resolves links, normalises DBs
49
+ ├─ cleanFiles() ← wipes previous generated output
50
+ ├─ generateBack() [typesOnly pass] ← generates TS types first
51
+ ├─ genGraphSchemesByLocalGenerator() ← generates .graphql schema files
52
+ ├─ generateBack() [full pass] ← full backend generation
53
+ ├─ generateFront() ← frontend generation (if enabled)
54
+ └─ generateEnvironment() ← Dockerfile, CI, Helm charts
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Two classes of files
60
+
61
+ Every file in the generated projects is one of two classes.
62
+
63
+ ### Generated files — DO NOT EDIT
64
+
65
+ Written by Runlify on **every** `regen`. First line is always:
66
+
67
+ ```
68
+ // DO NOT EDIT! THIS IS GENERATED FILE
69
+ ```
70
+
71
+ Editing these files is pointless — changes are lost on the next regen.
72
+
73
+ Examples: `<Entity>Service.ts`, GraphQL resolvers, Prisma schema, `resources.tsx`,
74
+ `routes.tsx`, `<Entity>List/index.tsx`.
75
+
76
+ ### Your files — safe to edit
77
+
78
+ Created by Runlify **once** (on first regen) then never touched again.
79
+ These are your extension points.
80
+
81
+ **Backend:**
82
+ | File | Purpose |
83
+ |------|---------|
84
+ | `Additional<Entity>Service.ts` | Add methods, override behaviour |
85
+ | `hooks/beforeCreate.ts` | Run logic before DB insert |
86
+ | `hooks/afterCreate.ts` | Run logic after DB insert |
87
+ | `hooks/beforeUpdate.ts` | Run logic before DB update |
88
+ | `hooks/afterUpdate.ts` | Run logic after DB update |
89
+ | `hooks/beforeDelete.ts` | Run logic before DB delete |
90
+ | `hooks/afterDelete.ts` | Run logic after DB delete |
91
+ | `hooks/beforeUpsert.ts` | Run logic before upsert |
92
+ | `hooks/additionalOperationsOnCreate.ts` | Side-effects on create |
93
+ | `hooks/additionalOperationsOnUpdate.ts` | Side-effects on update |
94
+ | `hooks/additionalOperationsOnDelete.ts` | Side-effects on delete |
95
+ | `hooks/changeListFilter.ts` | Mutate list query filter at runtime |
96
+ | `hooks/tenantIdRequiredHooks.ts` | Tenant isolation enforcement |
97
+ | `rest/restRouter.ts` | Custom REST endpoints |
98
+ | `init/roles/customPermissions.ts` | Hand-written data-space permissions — see [11-permissions.md](./11-permissions.md) |
99
+ | `init/roles/customUiPermissions.ts` | Hand-written UI-space permissions — see [11-permissions.md](./11-permissions.md) |
100
+
101
+ **Frontend:**
102
+ | File | Purpose |
103
+ |------|---------|
104
+ | `Dashboard.tsx` | Home page content |
105
+ | `additionalRoutes.tsx` | Custom pages/routes |
106
+ | `getAdditionalMenu.ts` | Extra menu items |
107
+ | `PermissionPage.tsx` | Shown instead of a page the user lacks permission for |
108
+ | `NotFoundPage.tsx` | Shown for an action that doesn't exist on the entity (e.g. no edit form) |
109
+ | `i18n/types.ts`, `i18n/<lang>/<lang>Validation.ts`, `i18n/<lang>/index.ts` | Validation messages and the per-language translation root — see [08-frontend-file-graph.md](./08-frontend-file-graph.md#i18n) |
110
+
111
+ See [11-permissions.md](./11-permissions.md) for access control — a separate system from
112
+ these "yours" files, spanning both projects.
113
+
114
+ Full file trees: [07-backend-file-graph.md](./07-backend-file-graph.md) and
115
+ [08-frontend-file-graph.md](./08-frontend-file-graph.md).
116
+
117
+ ---
118
+
119
+ ## What gets generated
120
+
121
+ | Area | Technology | Docs |
122
+ |------|-----------|------|
123
+ | ORM / DB schema | Prisma (v6/v7) | [07-backend-file-graph.md](./07-backend-file-graph.md) |
124
+ | API layer | GraphQL (Apollo) | [07-backend-file-graph.md](./07-backend-file-graph.md) |
125
+ | Admin UI | react-admin | [08-frontend-file-graph.md](./08-frontend-file-graph.md) |
126
+ | Config | JSON env files | [09-options.md](./09-options.md) |
127
+ | CI/CD | GitLab CI `.yml` | [09-options.md](./09-options.md) |
128
+ | Containers | Dockerfile | [09-options.md](./09-options.md) |
129
+ | Kubernetes | Helm charts | [09-options.md](./09-options.md) |
130
+
131
+ ---
132
+
133
+ ## Output paths
134
+
135
+ By default `regen` resolves sibling directories relative to the meta project:
136
+
137
+ ```
138
+ ../ ← parent of the meta project
139
+ <prefix>-back/ ← detachedBackProject
140
+ <prefix>-ui/ ← detachedUiProject
141
+ <meta-project>/
142
+ ```
143
+
144
+ Both paths are overridable via `detachedBackProject` and `detachedUiProject` in
145
+ `options.json`. See [09-options.md](./09-options.md).
146
+
147
+ ---
148
+
149
+ ## Anti-patterns
150
+
151
+ ### Editing generated files
152
+
153
+ **Wrong:** opening `<Entity>Service.ts` and adding a method directly.
154
+
155
+ **Why:** the file is overwritten completely on every `runlify regen`. Your changes vanish
156
+ with no warning.
157
+
158
+ **Correct:** put all custom logic in `Additional<Entity>Service.ts` or the appropriate
159
+ `hooks/` file.
160
+
161
+ ---
162
+
163
+ ### Putting business logic in `metadata.ts`
164
+
165
+ **Wrong:** computing values, calling APIs, or reading environment variables inside the
166
+ `SystemMetaBuilder` chain.
167
+
168
+ **Why:** `metadata.ts` is a build-time description. It must be pure and deterministic.
169
+ Side effects here cause unpredictable generation output.
170
+
171
+ **Correct:** keep `metadata.ts` as a plain declarative description of the domain.
172
+ All runtime logic goes into the generated project.
@@ -0,0 +1,405 @@
1
+ # SystemMetaBuilder API
2
+
3
+ > **Load this file when:** you need to know what methods are available on the root
4
+ > `SystemMetaBuilder` instance — adding entities, config vars, roles, menus, pages,
5
+ > databases, deploy environments, or custom methods.
6
+ >
7
+ > Related: [03-entity-types.md](./03-entity-types.md) · [04-fields.md](./04-fields.md) ·
8
+ > [05-custom-methods.md](./05-custom-methods.md) · [09-options.md](./09-options.md)
9
+
10
+ ---
11
+
12
+ ## Constructor
13
+
14
+ ```ts
15
+ new SystemMetaBuilder(prefix: string, defOpts?: BootstrapEntityOptions, defaultLanguage?: string)
16
+ ```
17
+
18
+ | Parameter | Type | Default | Description |
19
+ |-----------|------|---------|-------------|
20
+ | `prefix` | `string` | required | Project prefix, used as the base name for all generated artifacts |
21
+ | `defOpts` | `BootstrapEntityOptions` | `defaultBootstrapEntityOptions` | Generation options passed to every entity added. See [09-options.md](./09-options.md) |
22
+ | `defaultLanguage` | `string` | `'ru'` | Default language code for all titles and labels |
23
+
24
+ The constructor automatically:
25
+ - Seeds ~80 default config vars (DB, S3, JWT, Kafka, ES, ClickHouse, OIDC, Keycloak, recaptcha, Sentry, Loki)
26
+ - Creates two deploy environments: `dev` and `prod`
27
+ - Registers languages `en` and `ru`
28
+ - Adds the built-in `files` catalog via `initDefaultCatalogs()`
29
+
30
+ ---
31
+
32
+ ## Identity
33
+
34
+ ### `setName(name: string): this`
35
+
36
+ Sets the system name (defaults to `prefix`). Used in generated docs and specs.
37
+
38
+ ### `setPrefix(prefix: string): this`
39
+
40
+ Sets the project prefix. Affects generated project names and k8s chart names.
41
+
42
+ ### `setNeedFor(needFor: string): this`
43
+
44
+ Human-readable description of what this system is for. Used in generated documentation.
45
+
46
+ ---
47
+
48
+ ## Entities
49
+
50
+ All `add*` entity methods throw if a name is already taken across **all** entity types.
51
+
52
+ ### `addCatalog(name, title?, options?): CatalogBuilder` {#addCatalog}
53
+
54
+ Adds a reference data entity (lookup table).
55
+
56
+ | Parameter | Type | Description |
57
+ |-----------|------|-------------|
58
+ | `name` | `string` | Unique entity name, `camelCase` |
59
+ | `title` | `{ singular?: string, plural?: string }` | Human-readable titles |
60
+ | `options` | `BootstrapEntityOptions` | Overrides default generation options for this entity |
61
+
62
+ Returns a `CatalogBuilder`. See [03-entity-types.md#catalog](./03-entity-types.md#catalog).
63
+
64
+ ### `addDocument(name, title?, options?): DocumentBuilder` {#addDocument}
65
+
66
+ Adds a transactional document entity (e.g. orders, invoices).
67
+
68
+ Same signature as `addCatalog`. Returns a `DocumentBuilder`.
69
+ See [03-entity-types.md#document](./03-entity-types.md#document).
70
+
71
+ ### `addInfoRegistry(name, registrarDepended, title?, options?): InfoRegistryBuilder` {#addInfoRegistry}
72
+
73
+ Adds an information register (accounting-style, stores state snapshots).
74
+
75
+ | Parameter | Type | Description |
76
+ |-----------|------|-------------|
77
+ | `registrarDepended` | `boolean` | If `true`, auto-adds `registrarTypeId`, `registrarId`, `row` fields + unique constraint |
78
+
79
+ See [03-entity-types.md#inforegistry](./03-entity-types.md#inforegistry).
80
+
81
+ ### `addSumRegistry(name, registrarDepended, title?, options?): SumRegistryBuilder` {#addSumRegistry}
82
+
83
+ Adds a totals register (accounting-style, stores aggregated sums).
84
+
85
+ | Parameter | Type | Description |
86
+ |-----------|------|-------------|
87
+ | `options` | `RegistryOptions` | `{ registrarIdType: 'int' \| 'string', sharded?: boolean }` |
88
+
89
+ See [03-entity-types.md#sumregistry](./03-entity-types.md#sumregistry).
90
+
91
+ ### `addManyToManyRelation(name, title?, options?): CatalogBuilder`
92
+
93
+ Creates a junction catalog for a many-to-many relationship. Identical to `addCatalog`
94
+ internally — the name is semantic only, to signal intent.
95
+
96
+ ### `addReport(name, title?, options?): ReportBuilder` {#addReport}
97
+
98
+ Adds a read-only report page. Automatically creates a page and a `read` permission.
99
+ See [03-entity-types.md#report](./03-entity-types.md#report).
100
+
101
+ ---
102
+
103
+ ## Lookups
104
+
105
+ ```ts
106
+ getCatalogByName(name: string): CatalogBuilder // throws if not found
107
+ getInfoRegistryByName(name: string): InfoRegistryBuilder
108
+ getSavableEntities(): EntityBuilderWithOptions[] // catalogs + documents + infoRegistries + sumRegistries
109
+ getCatalogs(): EntityBuilderWithOptions[]
110
+ getDocuments(): EntityBuilderWithOptions[]
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Config Variables
116
+
117
+ Config vars define the runtime configuration schema for the generated application.
118
+ All config vars seeded in the constructor can be modified after construction.
119
+
120
+ ### `addConfigVar(name, type, required, def, needFor, scopes?, hidden?, editable?): ConfigVarBuilder` {#addConfigVar}
121
+
122
+ | Parameter | Type | Default | Description |
123
+ |-----------|------|---------|-------------|
124
+ | `name` | `string` | required | Dot-notation key, e.g. `'database.main.write.uri'` |
125
+ | `type` | `FieldType` | required | `'string' \| 'int' \| 'bigint' \| 'float' \| 'bool' \| 'datetime' \| 'date'` |
126
+ | `required` | `boolean` | required | Whether the var must be set in every environment |
127
+ | `def` | `ConfigValue<T>` | required | Default value |
128
+ | `needFor` | `string` | required | Human description of what this var configures |
129
+ | `scopes` | `ConfigVarScope[]` | `['back','worker','telegramBot']` | Which services use this var |
130
+ | `hidden` | `boolean` | `false` | Hide from UI |
131
+ | `editable` | `boolean` | `true` | Allow editing in UI |
132
+
133
+ Returns a `ConfigVarBuilder` which supports further chaining:
134
+ - `.setRequired()` / `.setScopes(scopes)` / `.addScopes(scopes)` / `.delScopes(scopes)`
135
+ - `.setHidden()` / `.setEditable()` / `.setDefValue(value)`
136
+ - `.setSecure()` — shorthand for `.setHidden(true).setEditable(false)`. Use for secrets.
137
+
138
+ `ConfigVarScope` values: `'ci' | 'back' | 'admin-app' | 'cutomer-app' | 'worker' | 'telegramBot'`
139
+
140
+ ### `delConfigVar(name: string): this`
141
+
142
+ Removes a config var by name. Useful for removing default vars seeded in the constructor.
143
+
144
+ ### `getConfigVar(name: string): ConfigVarBuilder | undefined`
145
+
146
+ Returns the builder for an existing config var, or `undefined`.
147
+
148
+ ### `getConfigVarRequired(name: string): ConfigVarBuilder`
149
+
150
+ Returns the builder or throws if not found. Use to modify default vars:
151
+
152
+ ```ts
153
+ system.getConfigVarRequired('database.main.write.uri').setDefValue('postgresql://...')
154
+ ```
155
+
156
+ **Anti-pattern — legacy methods:**
157
+
158
+ `setConfigVarDefaultValue(name, def)` and `setDefaultValueForConfigVar(name, def)` are
159
+ deprecated. They log a warning and delegate to `getConfigVarRequired(name).setDefValue(def)`.
160
+
161
+ **Correct:** always use `system.getConfigVarRequired(name).setDefValue(value)`.
162
+
163
+ ---
164
+
165
+ ## Databases
166
+
167
+ `main` is always registered. Additional databases must be registered before entities
168
+ reference them.
169
+
170
+ ### `addDatabase(name: string): this` {#addDatabase}
171
+
172
+ Registers an additional named database. Automatically generates connection config vars
173
+ for the new database (`database.<name>.write.uri`, etc.).
174
+
175
+ **Anti-pattern — referencing an unregistered database:**
176
+
177
+ ```ts
178
+ // WRONG: throws at build() time
179
+ const orders = system.addCatalog('orders')
180
+ orders.setDatabase('archive') // 'archive' was never registered
181
+
182
+ // CORRECT
183
+ system.addDatabase('archive')
184
+ const orders = system.addCatalog('orders')
185
+ orders.setDatabase('archive')
186
+ ```
187
+
188
+ ### `getRegisteredDatabaseNames(): string[]`
189
+
190
+ Returns `['main', ...others]` sorted alphabetically.
191
+
192
+ ---
193
+
194
+ ## Roles
195
+
196
+ ### `addRole(name: string, title?: string): RoleBuilder` {#addRole}
197
+
198
+ Defines an access role. Roles are referenced by permissions on entities.
199
+ Name must be unique across all entity names. See
200
+ [11-permissions.md](./11-permissions.md) for how permission strings are named and enforced.
201
+
202
+ ---
203
+
204
+ ## Deploy Environments
205
+
206
+ Two default environments (`dev`, `prod`) are seeded in the constructor.
207
+
208
+ ### `addDeployEnvironment(env: DeployEnvironment): this`
209
+
210
+ Adds a new deploy environment. `DeployEnvironment` shape:
211
+
212
+ | Field | Type | Description |
213
+ |-------|------|-------------|
214
+ | `name` | `string` | Environment name (`'staging'`, `'prod'`, etc.) |
215
+ | `main` | `boolean` | Is this the primary/production environment |
216
+ | `manualDeploy` | `boolean` | Requires manual trigger in CI |
217
+ | `clusterName` | `string` | Kubernetes cluster name |
218
+ | `workerClusterName` | `string` | Kubernetes cluster for workers |
219
+ | `branchName` | `string` | Git branch that triggers this environment |
220
+ | `metricsEnabled` | `boolean` | Enable metrics collection |
221
+ | `host` | `string` | Base domain for this environment |
222
+ | `runnerTag` | `string` | GitLab CI runner tag |
223
+ | `gitlabEnvPrefix` | `string` | Prefix for GitLab environment variables |
224
+
225
+ ### `editDeployEnvironment(name: string, partial: Partial<DeployEnvironment>): this`
226
+
227
+ Modifies an existing environment. Use to override the defaults:
228
+
229
+ ```ts
230
+ system.editDeployEnvironment('dev', { host: 'mycompany.dev', branchName: 'develop' })
231
+ system.editDeployEnvironment('prod', { host: 'mycompany.com', clusterName: 'prod01' })
232
+ ```
233
+
234
+ ### `delDeployEnvironment(name: string): this`
235
+
236
+ Removes an environment.
237
+
238
+ ---
239
+
240
+ ## Pages & Menu
241
+
242
+ ### `addPage(name, link, label, title?): PageBuilder` {#addPage}
243
+
244
+ Adds a standalone UI page (not tied to an entity). Used as a target for menu items.
245
+
246
+ | Parameter | Description |
247
+ |-----------|-------------|
248
+ | `name` | Unique page identifier |
249
+ | `link` | URL path (e.g. `'/dashboard'`) |
250
+ | `label` | i18n key shown in breadcrumbs/menu |
251
+ | `title` | Optional human title |
252
+
253
+ ### `addGroupMenuItem(label: string): GroupMenuItemBuilder`
254
+
255
+ Adds a collapsible group in the sidebar menu. Returns a builder to add sub-items:
256
+ - `.addInternalMenuItem(pageName)` — link to a page defined in the system
257
+ - `.addExternalMenuItem(label, url)` — link to an absolute URL
258
+ - `.addExternalEnvMenuItem(label, env)` — link resolved from a config var at runtime
259
+
260
+ ### `addInternalMenuItem(pageName: string): InternalMenuItemBuilder`
261
+
262
+ Adds a top-level sidebar link to an existing page.
263
+
264
+ ### `addExternalMenuItem(label, url): ExternalMenuItemBuilder`
265
+
266
+ Adds a top-level link to a hardcoded external URL.
267
+
268
+ ### `addExternalEnvMenuItem(label, env): ExternalEnvMenuItemBuilder`
269
+
270
+ Adds a top-level link where the URL is read from the config var named `env` at runtime.
271
+ Useful for linking to environment-specific external services.
272
+
273
+ **Anti-pattern — menu items pointing to non-existent pages:**
274
+
275
+ `addInternalMenuItem` validates that the page exists at `build()` time.
276
+ Calling it with a name that hasn't been registered via `addPage` (or auto-created by an
277
+ entity) throws. Always call `addPage` (or add the entity that owns the page) before
278
+ adding menu items that reference it.
279
+
280
+ ---
281
+
282
+ ## Custom Methods & Models
283
+
284
+ These produce additional GraphQL operations outside of entity CRUD.
285
+
286
+ ### `addMethod(name, methodType, title?): MethodBuilder` {#addMethod}
287
+
288
+ Adds a custom GraphQL Query or Mutation at the system level.
289
+
290
+ | Parameter | Type | Values |
291
+ |-----------|------|--------|
292
+ | `methodType` | `MethodType` | `MethodType.Query` \| `MethodType.Mutation` |
293
+
294
+ Returns a `MethodBuilder`. See [05-custom-methods.md](./05-custom-methods.md).
295
+
296
+ ### `createGeneralModel(name, title?): BaseModelBuilder`
297
+
298
+ Creates a model usable as both input and output.
299
+
300
+ ### `createInputModel(name, title?): BaseModelBuilder`
301
+
302
+ Creates a model usable only as input (GraphQL `input` type).
303
+
304
+ ### `createOutputModel(name, title?): BaseModelBuilder`
305
+
306
+ Creates a model usable only as output (GraphQL `type`).
307
+
308
+ See [05-custom-methods.md](./05-custom-methods.md) for full `MethodBuilder` and model API.
309
+
310
+ ---
311
+
312
+ ## i18n
313
+
314
+ ```ts
315
+ addLanguage(id: string, title?: string) // adds a language (en/ru pre-seeded)
316
+ deleteLanguage(id: string) // removes a language
317
+ setDefailtLanguage(id: string) // sets default; must exist or throws
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Glossary & Commands
323
+
324
+ ```ts
325
+ addGlossaryTerm(term: string, definition: string)
326
+ // Adds a domain term to the generated documentation. Throws on duplicate.
327
+
328
+ addCommnad(projectCategory: ProjectCategory, name: string, command: string, needFor: string)
329
+ // Registers a CLI command in the generated docs.
330
+ // projectCategory: 'back' | 'ui' | 'app' | 'land'
331
+ ```
332
+
333
+ ---
334
+
335
+ ## Additional Service (standalone service without entity)
336
+
337
+ ### `addAdditionalService(name, title?): AdditionalServiceBuilder`
338
+
339
+ Adds a standalone backend service with its own methods and models — not tied to any
340
+ entity. Useful for orchestration logic, external integrations, or complex business
341
+ operations that span multiple entities.
342
+
343
+ ---
344
+
345
+ ## Backend deployment config
346
+
347
+ ### `getBack(): DeploymentBuilder`
348
+
349
+ Returns the `DeploymentBuilder` for the main backend service. Allows configuring
350
+ replicas, CPU/memory requests and limits:
351
+
352
+ ```ts
353
+ system.getBack().setReplicas(2).setRequests({ cpu: '100m', memory: '256Mi' })
354
+ ```
355
+
356
+ ---
357
+
358
+ ## Build
359
+
360
+ ### `build(): System`
361
+
362
+ Validates and serialises the entire meta description into a plain `System` object.
363
+ Throws on any validation error (duplicate names, unregistered databases, invalid
364
+ constraints, etc.).
365
+
366
+ ### `validate(): System`
367
+
368
+ Alias of `build()`. Can be used to check for errors without assigning the result.
369
+
370
+ ---
371
+
372
+ ## Anti-patterns
373
+
374
+ ### Using `setConfigVarDefaultValue` / `setDefaultValueForConfigVar`
375
+
376
+ Both are **deprecated**. They print a warning on every call.
377
+
378
+ **Wrong:**
379
+ ```ts
380
+ system.setConfigVarDefaultValue('database.main.write.uri', 'postgresql://...')
381
+ ```
382
+
383
+ **Correct:**
384
+ ```ts
385
+ system.getConfigVarRequired('database.main.write.uri').setDefValue('postgresql://...')
386
+ ```
387
+
388
+ ### Duplicate names across different entity types
389
+
390
+ All entity names share a single namespace. `addCatalog('users')` and then
391
+ `addDocument('users')` will throw. Names must be unique across catalogs, documents,
392
+ infoRegistries, sumRegistries, roles, and pages.
393
+
394
+ ### Calling `build()` multiple times expecting different results
395
+
396
+ `build()` is deterministic. Calling it twice produces two separate plain objects with
397
+ identical content. If you need to check validity without producing output, use
398
+ `validate()` — it is the same operation.
399
+
400
+ ---
401
+
402
+ > **Examples:** this file intentionally omits code examples. If you are working with
403
+ > this documentation as an AI agent or developer, add real usage examples from the
404
+ > consuming project here. A reference metadata file can typically be found at
405
+ > `src/meta/metadata.ts` in the meta project.