runlify 0.0.793 → 0.0.796
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/build/cli.js +8 -2
- package/build/projectsGeneration/builders/generationPaths.js +44 -1
- package/build/projectsGeneration/generateProject/back/src/generateBackSrc.js +11 -2
- package/build/projectsGeneration/generateProject/fileHandlers.js +6 -2
- package/build/projectsGeneration/generateProject/front/generateFrontSrc.js +10 -1
- package/build/projectsGeneration/generateProject/front/translations/generateFrontSrcTranslations.js +33 -1
- package/build/projectsGeneration/generateProject/generateBackClickHouseBootstrap.js +1 -4
- package/build/projectsGeneration/generateProject/utils.js +2 -2
- package/build/projectsGeneration/generators/fileTemplates/back/clickhouse/jobs.js +41 -4
- package/build/projectsGeneration/generators/fileTemplates/back/roles/customPermissions.js +12 -0
- package/build/projectsGeneration/generators/fileTemplates/back/roles/customUiPermissions.js +13 -0
- package/build/projectsGeneration/generators/fileTemplates/back/roles/initPermissions.js +31 -0
- package/build/projectsGeneration/generators/fileTemplates/back/roles/uiPermissions.js +24 -0
- package/build/projectsGeneration/generators/fileTemplates/ui/NotFoundPage.js +6 -0
- package/build/projectsGeneration/generators/fileTemplates/ui/PermissionPage.js +6 -0
- package/build/projectsGeneration/generators/fileTemplates/ui/environment/src/routes.js +5 -5
- package/build/projectsGeneration/generators/fileTemplates/ui/getDefaultMenu.js +5 -1
- package/build/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nIndexTmpl.js +35 -0
- package/build/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nTypesTmpl.js +33 -0
- package/build/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nValidationTmpl.js +38 -0
- package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityCreate/DefaultEntityCreate.js +16 -5
- package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityEdit/DefaultEntityEdit.js +27 -11
- package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityList/DefaultEntityFilter.js +13 -4
- package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityList/DefaultEntityList.js +14 -7
- package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityShow/DefaultMainTab.js +13 -4
- package/build/projectsGeneration/generators/fileTemplates/ui/pages/EntityShow/DependencyTab.js +12 -3
- package/build/projectsGeneration/generators/fileTemplates/ui/resources.js +21 -8
- package/build/projectsGeneration/generators/fileTemplates/ui/utils/permissions.js +89 -0
- package/build/projectsGeneration/generators/ui/getShowComponent.js +2 -2
- package/build/types/projectsGeneration/builders/generationPaths.d.ts +42 -0
- package/build/types/projectsGeneration/generateProject/fileHandlers.d.ts +1 -0
- package/build/types/projectsGeneration/generateProject/types.d.ts +1 -1
- package/build/types/projectsGeneration/generateProject/utils.d.ts +1 -1
- package/build/types/projectsGeneration/generators/fileTemplates/back/roles/customPermissions.d.ts +2 -0
- package/build/types/projectsGeneration/generators/fileTemplates/back/roles/customUiPermissions.d.ts +2 -0
- package/build/types/projectsGeneration/generators/fileTemplates/back/roles/initPermissions.d.ts +2 -0
- package/build/types/projectsGeneration/generators/fileTemplates/back/roles/uiPermissions.d.ts +3 -0
- package/build/types/projectsGeneration/generators/fileTemplates/ui/NotFoundPage.d.ts +2 -0
- package/build/types/projectsGeneration/generators/fileTemplates/ui/PermissionPage.d.ts +2 -0
- package/build/types/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nIndexTmpl.d.ts +2 -0
- package/build/types/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nTypesTmpl.d.ts +3 -0
- package/build/types/projectsGeneration/generators/fileTemplates/ui/i18n/skeleton/uiI18nValidationTmpl.d.ts +2 -0
- package/build/types/projectsGeneration/generators/fileTemplates/ui/pages/EntityEdit/DefaultEntityEdit.d.ts +1 -0
- package/build/types/projectsGeneration/generators/fileTemplates/ui/utils/permissions.d.ts +2 -0
- package/docs/01-overview.md +172 -0
- package/docs/02-system-meta-builder.md +405 -0
- package/docs/03-entity-types.md +471 -0
- package/docs/04-fields.md +357 -0
- package/docs/05-custom-methods.md +249 -0
- package/docs/06-storage.md +129 -0
- package/docs/07-backend-file-graph.md +231 -0
- package/docs/08-frontend-file-graph.md +260 -0
- package/docs/09-options.md +213 -0
- package/docs/10-modules.md +164 -0
- package/docs/11-permissions.md +231 -0
- package/docs/INDEX.md +70 -0
- 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.
|