create-restforge-skills 0.1.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.
@@ -0,0 +1,238 @@
1
+ # Reference: dbschema-kit Catalog
2
+
3
+ > **Offline mirror.** This file mirrors `codegen_get_dbschema_catalog` from the
4
+ > installed RESTForge platform. The live tool is authoritative — when this file
5
+ > and the tool disagree, trust the tool, then update this file. Always re-ground
6
+ > with the tool before defining SDF; do not rely on this mirror alone.
7
+
8
+ Source: `codegen_get_dbschema_catalog` — installed platform version.
9
+ Use as grounding before defining SDF.
10
+ Schema version: 1.1.
11
+
12
+ ---
13
+
14
+ ## Table of Contents
15
+
16
+ 1. [Field Types](#field-types)
17
+ 2. [Shorthand Syntax](#shorthand-syntax)
18
+ 3. [Constraints](#constraints)
19
+ 4. [Relation Types](#relation-types)
20
+ 5. [Referential Actions](#referential-actions)
21
+ 6. [Check Operations](#check-operations)
22
+ 7. [Audit Columns](#audit-columns)
23
+ 8. [Soft-Delete Contract](#soft-delete-contract)
24
+ 9. [Naming Rules](#naming-rules)
25
+ 10. [Dialect Support](#dialect-support)
26
+
27
+ ---
28
+
29
+ ## Field Types
30
+
31
+ 10 types available. `string` and `decimal` require a modifier.
32
+
33
+ | Type | Modifier | Shorthand example | Notes |
34
+ |---|---|---|---|
35
+ | `string` | required: `:<length>` | `string:255` | VARCHAR, explicit length required |
36
+ | `text` | none | `text` | TEXT/CLOB, no length limit |
37
+ | `integer` | none | `integer` | INT 32-bit |
38
+ | `bigint` | none | `bigint` | BIGINT 64-bit |
39
+ | `decimal` | required: `:<precision>,<scale>` | `decimal:15,2` | Fixed-point |
40
+ | `boolean` | none | `boolean` | Native BOOLEAN (PG), VARCHAR on others |
41
+ | `date` | none | `date` | Date only |
42
+ | `timestamp` | none | `timestamp` | Date + time |
43
+ | `uuid` | none | `uuid` | Native UUID (PG), VARCHAR(36) on others |
44
+ | `json` | none | `json` | JSONB (PG), JSON (MySQL), CLOB (Oracle) |
45
+
46
+ ---
47
+
48
+ ## Shorthand Syntax
49
+
50
+ Format: `<type>[:<modifier>] [<constraint>[:<value>]]...`
51
+
52
+ ```
53
+ string:36 pk
54
+ string:255 notnull
55
+ decimal:15,2 notnull default:0
56
+ boolean default:true
57
+ string:100 default:'pending'
58
+ timestamp default:now()
59
+ string:36 fk:category.category_id
60
+ string:64 index
61
+ ```
62
+
63
+ Rules:
64
+ - Type must come first and must be from the field types list above.
65
+ - Modifier is required for `string` (length) and `decimal` (precision,scale).
66
+ - Standalone constraints have no value: `pk`, `notnull`, `unique`, `index`.
67
+ - Value constraints require `constraint:value` format: `default`, `fk`.
68
+ - String default: single-quoted `default:'value'`; numeric/boolean: raw `default:0`;
69
+ SQL constant: bare identifier `default:current_date`; native function: `default:now()`.
70
+ - FK uses dot notation: `fk:<table>.<column>`. `<column>` is the **actual
71
+ column name** of the referenced field in the target table — normally that
72
+ table's primary key column (e.g. `category.category_id`), NOT a literal `id`.
73
+ RESTForge does not auto-resolve `.id` to the primary key; a reference to a
74
+ column that does not exist is rejected. Bracket syntax is rejected by the parser.
75
+ - `autoUpdate` is deprecated — no functional effect, parsed for backward compat only.
76
+
77
+ ---
78
+
79
+ ## Constraints
80
+
81
+ 7 constraints available (excludes deprecated `autoUpdate`).
82
+
83
+ | Constraint | Kind | Example | Notes |
84
+ |---|---|---|---|
85
+ | `pk` | standalone | `string:36 pk` | Primary key |
86
+ | `notnull` | standalone | `string:255 notnull` | NOT NULL |
87
+ | `unique` | standalone | `string:32 unique` | Single-column UNIQUE |
88
+ | `index` | standalone | `string:64 index` | Single-column non-unique index |
89
+ | `default` | value | `boolean default:true` | Default value |
90
+ | `fk` | value | `string:36 fk:category.category_id` | FK + auto belongsTo relation; target is the actual PK column name |
91
+
92
+ ---
93
+
94
+ ## Relation Types
95
+
96
+ 3 relation types. All use `type`, `localKey`, `references` (required),
97
+ and `target`, `onDelete`, `onUpdate` (optional).
98
+
99
+ | Type | Direction | DDL |
100
+ |---|---|---|
101
+ | `belongsTo` | Many-to-one, this table holds the FK | FK constraint generated |
102
+ | `hasOne` | One-to-one inverse of belongsTo | No additional DDL |
103
+ | `hasMany` | One-to-many inverse of belongsTo | No additional DDL |
104
+
105
+ Example:
106
+ ```js
107
+ relations: {
108
+ category: {
109
+ type: "belongsTo",
110
+ localKey: "category_id",
111
+ references: "category_id",
112
+ onDelete: "restrict"
113
+ }
114
+ }
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Referential Actions
120
+
121
+ 4 actions for `onDelete` and `onUpdate`:
122
+
123
+ | Action | Behavior |
124
+ |---|---|
125
+ | `cascade` | Delete/update child rows |
126
+ | `restrict` | Reject delete/update if child exists |
127
+ | `setNull` | Set child FK to NULL (field must be nullable) |
128
+ | `noAction` | Defer check (semantics similar to restrict in most dialects) |
129
+
130
+ ---
131
+
132
+ ## Check Operations
133
+
134
+ 7 operators for the `checks` array. Format: `{ name?, field, <operator>: <value> }`.
135
+
136
+ | Operator | Value type | Example |
137
+ |---|---|---|
138
+ | `in` | array | `{ field: "status", in: ["active", "inactive"] }` |
139
+ | `eq` | scalar | `{ field: "type", eq: "user" }` |
140
+ | `neq` | scalar | `{ field: "type", neq: "system" }` |
141
+ | `gt` | numeric | `{ field: "qty", gt: 0 }` |
142
+ | `gte` | numeric | `{ field: "qty", gte: 0 }` |
143
+ | `lt` | numeric | `{ field: "discount", lt: 100 }` |
144
+ | `lte` | numeric | `{ field: "discount", lte: 100 }` |
145
+
146
+ > Case enforcement at the DB level (e.g. require `customer_name` to be stored
147
+ > upper case) belongs here as a check, not in RDF `fieldValidation`. RDF
148
+ > `uppercase` only normalizes the value at the API layer.
149
+
150
+ ---
151
+
152
+ ## Audit Columns
153
+
154
+ 4 standard columns for tables managed by RESTForge. Emitted automatically by
155
+ `codegen_dbschema_init`. Lookup/system tables may remove them manually.
156
+
157
+ | Column | SDF shorthand | Notes |
158
+ |---|---|---|
159
+ | `created_at` | `timestamp default:now()` | Set via DEFAULT now() on INSERT |
160
+ | `created_by` | `string:100` | Set by application layer on INSERT, nullable |
161
+ | `updated_at` | `timestamp` | Auto-updated via RDF runtime (not an SDF marker) |
162
+ | `updated_by` | `string:100` | Set by application layer on UPDATE, nullable |
163
+
164
+ All 4 columns are nullable. Drift between SDF (audit columns absent) and RDF
165
+ (assumes audit columns exist) causes runtime errors.
166
+
167
+ ---
168
+
169
+ ## Soft-Delete Contract
170
+
171
+ Declare with `softDelete: { enabled: true }` in `defineModel`. The three
172
+ contract columns must be present in `fields` with the correct types.
173
+
174
+ | Column | Required shorthand | Nullable |
175
+ |---|---|---|
176
+ | `is_deleted` | `boolean notnull default:false` | no |
177
+ | `deleted_at` | `timestamp` | yes |
178
+ | `deleted_by` | `string:70` | yes |
179
+
180
+ ### Biconditional rules
181
+
182
+ - `enabled: true` + all three columns present with correct types → valid.
183
+ - `enabled: true` + missing columns → ERROR (missing columns listed).
184
+ - Contract columns present but `enabled` not true → ERROR.
185
+ - Wrong column type → ERROR.
186
+ - `is_deleted`, `deleted_at`, `deleted_by` are reserved names — cannot be used
187
+ as regular columns in a RESTForge table.
188
+
189
+ ### Reusable (UNIQUE column values freed after soft-delete)
190
+
191
+ Fields whose unique values should be freed after soft-delete must be declared
192
+ in `softDelete.reusable: [{ field, length }]`. Requirements:
193
+ - Field must exist in `fields`.
194
+ - Field type must be `string` or `text`.
195
+ - Field must have a single-column UNIQUE constraint.
196
+ - `length` = maximum input length. Physical length = `length + 38`
197
+ (38 = "##" + UUID v7).
198
+
199
+ ### Generated DDL
200
+
201
+ - CHECK constraint: `chk_<table>_soft_delete_consistency` — enforces consistency
202
+ across the three contract columns.
203
+ - Non-unique indexes become PostgreSQL partial indexes:
204
+ `WHERE is_deleted = FALSE`.
205
+ - UNIQUE constraints are NOT made partial; column values are freed via
206
+ suffix mutation (not a partial unique index).
207
+
208
+ ### Unique eligibility gate
209
+
210
+ When `enabled: true`, all UNIQUE constraints on the table are checked:
211
+ - Composite UNIQUE is rejected — suffix mutation cannot free composite columns.
212
+ - Single-column UNIQUE on a non-string type is rejected — suffix mutation only
213
+ works for `string`/`text`.
214
+
215
+ ### Dialect support
216
+
217
+ Phase 1: PostgreSQL only. Other dialects produce an explicit error.
218
+
219
+ ---
220
+
221
+ ## Naming Rules
222
+
223
+ - Table names: `snake_case`, lowercase, digits, underscores.
224
+ - Field/column names: `snake_case`.
225
+ - Constraint names: auto-generated with prefixes `pk_`, `fk_`, `idx_`, `uq_`,
226
+ `ck_`. When exceeding the dialect's maximum length, falls back to an 8-character
227
+ MD5 suffix.
228
+
229
+ ---
230
+
231
+ ## Dialect Support
232
+
233
+ | Dialect | Driver | Boolean storage |
234
+ |---|---|---|
235
+ | `postgres` | pg | Native BOOLEAN |
236
+ | `mysql` | mysql2 | VARCHAR ("true"/"false") |
237
+ | `oracle` | oracledb | VARCHAR2 + CHECK constraint |
238
+ | `sqlite` | better-sqlite3 | TEXT |