First commit
This commit is contained in:
163
Tables.md
Normal file
163
Tables.md
Normal file
@@ -0,0 +1,163 @@
|
||||
Here is a fully rewritten version of the entire **Tables + Columns + Floating Mapping** section — accurate, simplified, and without over-emphasizing the “floating” term, while still explaining why it matters.
|
||||
|
||||
---
|
||||
|
||||
## Tables & Columns
|
||||
|
||||
### Automatic SQL Mapping from UI Components
|
||||
|
||||
In Unify, **your UI defines your data model**.
|
||||
|
||||
Every data entity in an application is a **table object**:
|
||||
|
||||
```js
|
||||
import table from '/unify/table.js';
|
||||
|
||||
export default class user extends table {
|
||||
|
||||
username = new username(); // column
|
||||
email = new email(); // column
|
||||
groups = new groups(); // relation
|
||||
}
|
||||
```
|
||||
|
||||
Any child object that extends `column` is automatically treated as a **database column** belonging to its nearest table ancestor.
|
||||
|
||||
There is no need to write schemas, migrations, or model config files.
|
||||
Unify inspects the structure at runtime and understands:
|
||||
|
||||
* Table name → class name (`user`)
|
||||
* Column names → field names (`username`, `email`, …)
|
||||
* Relationships → nested collections
|
||||
* Permissions → defined on the table
|
||||
|
||||
No duplication. No ORM setup.
|
||||
Your UI code **is** your data model.
|
||||
|
||||
---
|
||||
|
||||
### Columns Can Live Anywhere in the UI Tree
|
||||
|
||||
Columns do not need to be direct children of the table.
|
||||
|
||||
You can design your UI freely:
|
||||
|
||||
```js
|
||||
export default class userEditPanel extends panel {
|
||||
accountPanel = new accountPanel();
|
||||
contactPanel = new contactPanel();
|
||||
}
|
||||
|
||||
class accountPanel extends panel {
|
||||
username = new username(); // column
|
||||
}
|
||||
|
||||
class contactPanel extends panel {
|
||||
email = new email(); // column
|
||||
}
|
||||
```
|
||||
|
||||
Unify automatically discovers these fields because they appear **under a table instance** in the object tree.
|
||||
|
||||
So you are free to:
|
||||
|
||||
* Split a screen into panels
|
||||
* Reuse complex component hierarchies
|
||||
* Move UI structure without refactoring SQL code
|
||||
|
||||
This enables **UI-first design** without breaking the data layer.
|
||||
|
||||
---
|
||||
|
||||
### CRUD Without CRUD Code
|
||||
|
||||
Unify provides two primary data operations:
|
||||
|
||||
| Action | Developer code | Result |
|
||||
| ------ | ------------------- | ----------------------------------- |
|
||||
| Save | `await user.save()` | INSERT or UPDATE depending on `id` |
|
||||
| Load | `await user.sync()` | SELECT + populate all child columns |
|
||||
|
||||
Example: Editing a profile
|
||||
|
||||
```js
|
||||
async click() {
|
||||
const form = this.parents('userEdit');
|
||||
await form.save(); // automatically writes username & email
|
||||
form.hide();
|
||||
}
|
||||
```
|
||||
|
||||
And for loading:
|
||||
|
||||
```js
|
||||
user.id = 42;
|
||||
await user.sync(); // loads username/email into the UI automatically
|
||||
```
|
||||
|
||||
No setters.
|
||||
No binding boilerplate.
|
||||
No DTOs.
|
||||
No form libraries.
|
||||
|
||||
The table object is both:
|
||||
|
||||
* Data source
|
||||
* UI container
|
||||
* Binding layer
|
||||
|
||||
---
|
||||
|
||||
### Why This Matters
|
||||
|
||||
| Traditional Full-Stack | With Unify |
|
||||
| --------------------------- | -------------------------- |
|
||||
| Write database schema | Skip — inferred |
|
||||
| Write backend model | Skip — inferred |
|
||||
| Write API controllers | Skip — RPC auto-generation |
|
||||
| Write validation logic | Built into column objects |
|
||||
| Build UI → manually connect | UI *is* the data model |
|
||||
| Keep everything in sync | `.sync()` + `.save()` |
|
||||
|
||||
This eliminates the friction between backend + frontend and replaces it with one unified codebase.
|
||||
|
||||
---
|
||||
|
||||
### Minimal Mental Model
|
||||
|
||||
> A **table** object represents a database row.
|
||||
> Any **column** object inside that table’s UI subtree automatically becomes a database column.
|
||||
> `sync()` loads data into the UI.
|
||||
> `save()` writes UI data back to SQL.
|
||||
|
||||
Nothing more is needed to build and ship real applications.
|
||||
|
||||
---
|
||||
|
||||
### Example Recap
|
||||
|
||||
```js
|
||||
user.id = 7;
|
||||
await user.sync(); // load existing row → UI updates
|
||||
|
||||
user.username.value = "kaj";
|
||||
await user.save(); // update DB row with new values
|
||||
```
|
||||
|
||||
One line to fetch, one line to commit.
|
||||
|
||||
---
|
||||
|
||||
If you'd like, the next chapter can flow directly into **Render Collections & Lists**, since they demonstrate the same philosophy at scale:
|
||||
|
||||
* UI defines queries (pagination, filtering)
|
||||
* Changes propagate automatically across the app
|
||||
|
||||
Should I continue with:
|
||||
|
||||
A) Render Collections + Filtering/Searching
|
||||
B) Permissions (groups, scopes, READ/WRITE/DELETE)
|
||||
C) Routing + Animated Page State
|
||||
D) Server RPC Communication Model (socket commands)
|
||||
|
||||
Just tell me which one comes next.
|
||||
Reference in New Issue
Block a user