@dboio/cli 0.11.4 → 0.13.2
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 +126 -3
- package/bin/dbo.js +4 -0
- package/package.json +1 -1
- package/plugins/claude/dbo/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/dbo/commands/dbo.md +65 -244
- package/plugins/claude/dbo/docs/_audit_required/API/all.md +40 -0
- package/plugins/claude/dbo/docs/_audit_required/API/app.md +38 -0
- package/plugins/claude/dbo/docs/_audit_required/API/athenticate.md +26 -0
- package/plugins/claude/dbo/docs/_audit_required/API/cache.md +29 -0
- package/plugins/claude/dbo/docs/_audit_required/API/content.md +14 -0
- package/plugins/claude/dbo/docs/_audit_required/API/data_source.md +28 -0
- package/plugins/claude/dbo/docs/_audit_required/API/email.md +18 -0
- package/plugins/claude/dbo/docs/_audit_required/API/input.md +25 -0
- package/plugins/claude/dbo/docs/_audit_required/API/instance.md +28 -0
- package/plugins/claude/dbo/docs/_audit_required/API/log.md +8 -0
- package/plugins/claude/dbo/docs/_audit_required/API/media.md +12 -0
- package/plugins/claude/dbo/docs/_audit_required/API/output_by_entity.md +12 -0
- package/plugins/claude/dbo/docs/_audit_required/API/upload.md +7 -0
- package/plugins/claude/dbo/docs/_audit_required/dbo-api-syntax.md +1487 -0
- package/plugins/claude/dbo/docs/_audit_required/dbo-problems-code.md +111 -0
- package/plugins/claude/dbo/docs/_audit_required/dbo-problems-performance.md +109 -0
- package/plugins/claude/dbo/docs/_audit_required/dbo-problems-syntax.md +97 -0
- package/plugins/claude/dbo/docs/_audit_required/dbo-product-market.md +119 -0
- package/plugins/claude/dbo/docs/_audit_required/dbo-white-paper.md +125 -0
- package/plugins/claude/dbo/docs/dbo-cheat-sheet.md +323 -0
- package/plugins/claude/dbo/docs/dbo-cli-readme.md +2222 -0
- package/plugins/claude/dbo/docs/dbo-core-entities.md +878 -0
- package/plugins/claude/dbo/docs/dbo-output-customsql.md +677 -0
- package/plugins/claude/dbo/docs/dbo-output-query.md +967 -0
- package/plugins/claude/dbo/skills/cli/SKILL.md +62 -246
- package/src/commands/add.js +366 -62
- package/src/commands/build.js +102 -0
- package/src/commands/clone.js +602 -139
- package/src/commands/diff.js +4 -0
- package/src/commands/init.js +16 -2
- package/src/commands/input.js +3 -1
- package/src/commands/mv.js +12 -4
- package/src/commands/push.js +265 -70
- package/src/commands/rm.js +16 -3
- package/src/commands/run.js +81 -0
- package/src/lib/config.js +39 -0
- package/src/lib/delta.js +7 -1
- package/src/lib/diff.js +24 -2
- package/src/lib/filenames.js +120 -41
- package/src/lib/ignore.js +6 -0
- package/src/lib/input-parser.js +13 -4
- package/src/lib/scripts.js +232 -0
- package/src/migrations/006-remove-uid-companion-filenames.js +181 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# DBO.io: Your Schema Is Your Application
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
Most software asks you to accept someone else's idea of how your data should be organized. A CRM gives you their definition of a "contact." A project management tool gives you their definition of a "task." A SaaS platform gives you their schema, and you reshape your business to fit it.
|
|
6
|
+
|
|
7
|
+
The alternative — custom development — solves the data model problem but introduces an engineering problem. A custom application requires a full technology stack: an object-relational mapper to translate between the database and the programming language, a business logic layer to enforce rules, controllers to handle requests, views to render output, and migration scripts to evolve the schema over time. This middle tier — the code that sits between the database and the user — is where most of the complexity, cost, and ongoing maintenance lives. It is the reason custom software is expensive and slow to change.
|
|
8
|
+
|
|
9
|
+
The irony is that the relational database already knows the structure of the data. The tables, columns, types, constraints, and relationships are all defined in the schema. But conventional application development ignores this knowledge and restates it — painstakingly, redundantly — in application code. Every column becomes a property in a model class. Every table becomes a set of controller actions. Every relationship becomes a join written by hand. The database knows what the data looks like, but the application pretends it doesn't.
|
|
10
|
+
|
|
11
|
+
## The Core Insight
|
|
12
|
+
|
|
13
|
+
DBO.io begins with a simple premise: if the database already describes the structure of the data, the platform should be able to derive the application from that description. Define your tables and columns, and the platform provides the API, the rendering, the security, and the messaging — automatically. The schema is not an implementation detail hidden behind code. It is the application definition itself.
|
|
14
|
+
|
|
15
|
+
This eliminates the middle tier entirely. There is no object-relational mapper because there are no model classes. There is no business logic layer because the rules are expressed as metadata on the schema. There is no controller code because the API is generated from the entity definitions. The path from database to user-facing output is direct: a query executes, a template renders the result, and tokens resolve dynamic values — all without a line of application code.
|
|
16
|
+
|
|
17
|
+
The result is a platform where the people who understand the data — the domain experts, the analysts, the business owners — can define and modify applications by working with the schema and templates, not by writing or commissioning software.
|
|
18
|
+
|
|
19
|
+
## Five Pillars of the Architecture
|
|
20
|
+
|
|
21
|
+
### Pillar 1: The Entity System — Schema as Configuration
|
|
22
|
+
|
|
23
|
+
At the center of DBO.io is the entity, a metadata wrapper around a database table or view. An entity is not a class definition or a code artifact. It is a database record that describes a table: its name, its data source, its columns, and the behaviors associated with it.
|
|
24
|
+
|
|
25
|
+
Each column in an entity carries rich metadata beyond what the database schema alone provides. A column definition includes its data type and constraints, but also its display title, default value, validation rules, encryption behavior, whether it is read-only or computed, and its relationships to other entities. This metadata is the configuration that would traditionally be scattered across model classes, validation logic, form definitions, and migration scripts. In DBO.io, it lives in one place: the column record.
|
|
26
|
+
|
|
27
|
+
Because entities and columns are themselves data — rows in tables — adding a new entity or modifying a column is a data operation, not a code change. There is no deployment, no recompilation, no migration script. The schema evolves through the same mechanisms used to manage any other data in the system.
|
|
28
|
+
|
|
29
|
+
The entity system is database-agnostic. A data source abstraction layer handles the differences between database engines — identifier quoting, date formatting, type conversion, identity retrieval — so that entities can be backed by different databases without any change to the entity definition or the application behavior. A single application can query across multiple databases transparently.
|
|
30
|
+
|
|
31
|
+
### Pillar 2: The Eliminated Middle Tier — Database to API
|
|
32
|
+
|
|
33
|
+
In a conventional application, a request from the user passes through a controller, which calls a service, which calls a repository, which calls the database, and then the result travels back through the same layers in reverse. Each layer exists to translate between the one above it and the one below it. Each layer must be written, tested, and maintained.
|
|
34
|
+
|
|
35
|
+
DBO.io collapses this stack. REST endpoints map directly to data operations. An input endpoint handles creates, updates, and deletes. An output endpoint executes a query and returns results. A content endpoint renders a template. A message endpoint sends a communication. The platform provides these endpoints automatically for every entity. There is no controller to write, no service layer to maintain, no repository pattern to implement.
|
|
36
|
+
|
|
37
|
+
Validation, transactions, and error handling are enforced by the platform based on the entity and column metadata. A column marked as required will reject null values. A column marked as encrypted will encrypt on write and decrypt on read. A column with a maximum length will enforce it. These are not rules written in application code — they are properties of the column definition.
|
|
38
|
+
|
|
39
|
+
The API supports the full spectrum of data operations through a uniform syntax. A single request can create, update, or delete records across multiple entities, all within a transaction. Filtering, sorting, pagination, and search are URL parameters, not code. The format of the response — HTML, JSON, XML, CSV — is a parameter, not a separate endpoint or serialization layer.
|
|
40
|
+
|
|
41
|
+
### Pillar 3: Template Composition — Rendering Without Code
|
|
42
|
+
|
|
43
|
+
Query results, by themselves, are just data. Turning data into something a user can see and interact with is the job of templates. In DBO.io, a template defines how a set of query results becomes a rendered output — an HTML page, a JSON response, an email, a PDF.
|
|
44
|
+
|
|
45
|
+
A template is organized into structural sections: a header rendered once at the top, a row section rendered for each record, a footer rendered at the end, and an empty section rendered when there are no results. Within these sections, tokens resolve dynamic values. A value token pulls a column from the current row. A session token pulls a value from the current user's session. A request token pulls a URL parameter. A site token pulls a property of the current domain. Tokens can carry modifiers — to decrypt a value, escape it for HTML, truncate it, or format a date.
|
|
46
|
+
|
|
47
|
+
The composition model is what elevates templates from simple formatting to application assembly. An embed token nests one piece of rendered content inside another. An output can embed another output, a content record, an input form, or a message — and each embedded element resolves its own tokens from its own data context. A page is not a monolithic view; it is a composition of independently defined, independently queryable components. Each component can be reused across multiple pages, and changes to a component propagate everywhere it appears.
|
|
48
|
+
|
|
49
|
+
User-defined template tags extend the system without code changes. A template author can define custom named sections and reference them throughout the template. The platform distinguishes between system tags, which have fixed semantic meaning, and user-defined tags, which are arbitrary extensions. This allows template authors to create reusable patterns and conditional structures within the template language itself.
|
|
50
|
+
|
|
51
|
+
### Pillar 4: Cell-Level Security — Granular by Design
|
|
52
|
+
|
|
53
|
+
Security in DBO.io is not an afterthought bolted onto the application layer. It is intrinsic to the entity and column model, enforced at the data level before results ever reach a template or an API response.
|
|
54
|
+
|
|
55
|
+
Access control operates at three levels of granularity. At the entity level, a security rule grants or denies a user or group the ability to view, add, edit, delete, or execute operations on an entire entity. At the column level, a separate security rule can restrict access to individual columns — hiding sensitive fields from users who should not see them, or making certain columns read-only for certain roles. At the row level, a security rule can restrict access to specific records, identified by their primary key values.
|
|
56
|
+
|
|
57
|
+
These security rules are data. They are rows in security tables, not code in middleware or annotations on classes. Adding a security rule is a data operation. Changing who can see what is a data operation. The security model is as dynamic and configurable as the schema itself.
|
|
58
|
+
|
|
59
|
+
When a query executes, the platform automatically generates additional constraints based on the requesting user's security profile. If a user can only see certain rows, the query is filtered before execution. If a user cannot see certain columns, those columns are excluded from the result set. The template never has an opportunity to render data the user is not authorized to see, because that data is never retrieved in the first place.
|
|
60
|
+
|
|
61
|
+
This approach means that security is consistent regardless of how data is accessed. Whether a user requests data through the API, through a template, through an embed, or through a message, the same rules apply. There is no surface area where an application developer can accidentally expose data by forgetting to check permissions — the platform enforces it universally.
|
|
62
|
+
|
|
63
|
+
### Pillar 5: Multi-Tenancy and Instance Architecture
|
|
64
|
+
|
|
65
|
+
DBO.io is designed from the ground up to serve many organizations from a single platform, with each organization owning its own data model.
|
|
66
|
+
|
|
67
|
+
The tenancy model has two levels. An account represents an organization — a company, a department, a client. An instance represents a discrete application environment within that account — production, staging, development, or entirely separate applications. Each instance gets its own database with its own schema. There is no shared-schema multi-tenancy where tenants' data is commingled in the same tables. Each tenant's data is physically isolated.
|
|
68
|
+
|
|
69
|
+
A shared control plane manages cross-cutting concerns: account records, user authentication, instance metadata, and domain routing. When a request arrives, the platform identifies the account and instance from the domain or request parameters, establishes a connection to the appropriate instance database, and all subsequent operations — queries, security checks, template rendering, caching — execute within that tenant's context.
|
|
70
|
+
|
|
71
|
+
Applications are portable. Because entities, columns, templates, security rules, and configuration are all data records, an entire application can be exported from one instance and imported into another. This enables a workflow where applications are developed in a staging instance, tested, and then deployed to production — or packaged and deployed across entirely separate organizations.
|
|
72
|
+
|
|
73
|
+
The caching architecture respects tenant boundaries. Cache keys are prefixed with account and instance identifiers, preventing any possibility of data leaking across tenants. Each level of the cache hierarchy — system-wide, account-scoped, session-scoped, and request-scoped — maintains strict isolation.
|
|
74
|
+
|
|
75
|
+
## How the Pieces Compose
|
|
76
|
+
|
|
77
|
+
Consider a practical example. An organization needs to track projects and the people assigned to them.
|
|
78
|
+
|
|
79
|
+
An administrator defines two entities — one for projects and one for assignments — by creating records in the entity table. For each entity, they define columns: project name, status, start date, assigned person, role. Each column record specifies its data type, display title, validation rules, and any default values. The moment these records exist, the platform exposes REST API endpoints for creating, reading, updating, and deleting records in both entities. No code has been written.
|
|
80
|
+
|
|
81
|
+
Next, the administrator creates an output — a saved query definition — that joins projects with their assignments. They create a template for this output with a header showing column titles, a row section displaying each project with its assigned personnel, and a footer showing the total count. Tokens in the template resolve column values, and the output is immediately available as an API endpoint that returns rendered HTML or raw JSON, depending on the requested format.
|
|
82
|
+
|
|
83
|
+
To build a full page, the administrator creates a content record that embeds the project output alongside a separate output showing summary statistics and an input form for adding new assignments. Each embedded element resolves independently — the statistics query runs, the project list query runs, the input form renders — and the results compose into a single page. If the summary statistics are needed on other pages, that output is simply embedded again elsewhere.
|
|
84
|
+
|
|
85
|
+
Security rules ensure that each user sees only the projects they are authorized to view. A project manager sees all projects; a team member sees only their assignments. These rules are data records, and the platform enforces them transparently — the template and the API never need to check permissions, because the query results are already filtered.
|
|
86
|
+
|
|
87
|
+
Finally, the administrator creates a message template that sends an email notification when a new assignment is created. The email template uses the same token system as the page templates, pulling the project name, assignee, and role from the data context. The message is queued and delivered by a background process.
|
|
88
|
+
|
|
89
|
+
The entire application — data model, API, rendered pages, security, and notifications — was created by defining data records. No application code was written. No deployment was performed. The schema became the application.
|
|
90
|
+
|
|
91
|
+
## The Content Execution Layer
|
|
92
|
+
|
|
93
|
+
Configuration covers the vast majority of application behavior, but there are cases where custom logic is genuinely required — a complex calculation, a data transformation, an integration with an external service. For these cases, DBO.io provides a content execution layer.
|
|
94
|
+
|
|
95
|
+
Dynamic code can be authored as a content record and executed at runtime. The platform compiles the code, caches the compiled result for performance, and executes it within a controlled environment that provides access to data sources, the current user context, and structured input and output objects. The compiled code is cached by its content hash, so identical code is never recompiled.
|
|
96
|
+
|
|
97
|
+
This layer sits alongside templates, not in place of them. It is an escape hatch for the minority of cases where declarative configuration is insufficient — not a general-purpose programming model that replaces the template and token system. The design philosophy is that most application behavior should be expressible through schema, templates, and metadata, with dynamic code reserved for genuine exceptions.
|
|
98
|
+
|
|
99
|
+
## The Messaging Subsystem
|
|
100
|
+
|
|
101
|
+
Communication is a first-class capability, not an external integration. The platform supports email, SMS, and AI-powered chatbot conversations through a unified messaging abstraction.
|
|
102
|
+
|
|
103
|
+
Message templates use the same token and template system as content rendering. An email template defines its recipients, subject, and body using the same tokens that resolve data values, session information, and request parameters in any other template. This means that any data accessible through the platform can be included in a message without writing integration code.
|
|
104
|
+
|
|
105
|
+
Messages are queued for background delivery with scheduling support. A message can be sent immediately or deferred to a future time. The background processing system handles retries and batch delivery. Chatbot conversations support multi-turn threading, where the platform tracks conversation history and manages function calling — allowing an AI assistant to query data and perform operations through the same API that serves human users.
|
|
106
|
+
|
|
107
|
+
## The Caching Architecture
|
|
108
|
+
|
|
109
|
+
Performance at scale requires caching, and DBO.io provides a multi-level cache designed for multi-tenant isolation. The cache operates at five tiers: system-wide for data shared across all tenants, account-scoped for data shared across an organization's instances, instance-scoped for data within a single application, session-scoped for data tied to a user's session, and request-scoped for data that lives only for the duration of a single request.
|
|
110
|
+
|
|
111
|
+
Entity metadata, query results, rendered content, and compiled code are each cached independently and at the appropriate tier. The cache supports pluggable storage backends — an in-process cache for single-server deployments and a distributed cache for scaled environments. Selective invalidation allows refreshing specific cached items without flushing the entire cache.
|
|
112
|
+
|
|
113
|
+
## What This Makes Possible
|
|
114
|
+
|
|
115
|
+
DBO.io inverts the traditional relationship between database and application. Instead of the database serving the application, the database defines the application. This inversion has practical consequences.
|
|
116
|
+
|
|
117
|
+
Application development is measured in hours, not months. Defining entities, creating templates, and configuring security rules are all data operations that take effect immediately. There is no build step, no deployment pipeline, no waiting for code review. The people closest to the business problem — who understand the data and the workflows — can build and modify applications directly.
|
|
118
|
+
|
|
119
|
+
Every customer gets a data model that fits their actual business. There is no compromise between "our schema" and "your needs." The schema is yours. It reflects your entities, your relationships, your terminology. When the business changes, the schema changes, and the application changes with it — instantly, without a development cycle.
|
|
120
|
+
|
|
121
|
+
The eliminated middle tier means there is dramatically less code to write, test, debug, and maintain. The platform handles the concerns that traditionally consume the majority of development effort: API routing, data validation, security enforcement, output formatting, and cache management. What remains is the schema, the templates, and the metadata that configures them — all of which are data, all of which are versioned and portable, and none of which require a compiler.
|
|
122
|
+
|
|
123
|
+
The platform scales across organizations through physical database isolation, tenant-aware caching, and a shared control plane. Each organization operates as if they have their own platform, because at the data level, they do.
|
|
124
|
+
|
|
125
|
+
DBO.io is the thesis that for the vast majority of data-driven applications, the relational database already contains everything the application needs to know. The platform's job is to stop ignoring that knowledge and start deriving the application from it.
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# DBO Framework — Developer Cheat Sheet
|
|
2
|
+
|
|
3
|
+
DBO is a multi-tenant platform where apps are built from entities, outputs, content, and media — no backend code. Data access, CRUD, security, and composition all happen through a template language and HTTP API.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Core Primitives
|
|
8
|
+
|
|
9
|
+
| Primitive | What it is |
|
|
10
|
+
|-----------|-----------|
|
|
11
|
+
| **App** | Top-level workspace. Groups entities, outputs, content, media, config. |
|
|
12
|
+
| **Entity** | Maps to a DB table/view. Unit of data access, security, and input. |
|
|
13
|
+
| **Output** | Named query config → fetches entity rows → renders via template. |
|
|
14
|
+
| **Content** | Template/page record. Stores markup, CSS, JS, or executable C#. Served via URL. |
|
|
15
|
+
| **Media** | Binary file record. Metadata + reference to physical file (disk or external). |
|
|
16
|
+
| **Bin** | Hierarchical directory container for physical media files. |
|
|
17
|
+
| **Site** | Web portal grouping content under a master template and domain. |
|
|
18
|
+
| **Data Source** | DB connection config. One app can use multiple data sources. |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Token Syntax
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
#{type@reference$target!default:modifier;comment}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Order: `type` → `@ref` → `$target` → `!default` → `:modifier` → `;comment`. All parts except `type` are optional.
|
|
29
|
+
|
|
30
|
+
### Token Types
|
|
31
|
+
|
|
32
|
+
| Token | Reads from |
|
|
33
|
+
|-------|-----------|
|
|
34
|
+
| `#{value@Field}` | Current row data in the render context |
|
|
35
|
+
| `#{request@Param}` | URL / request parameters |
|
|
36
|
+
| `#{session@Field}` | Authenticated session (e.g. `#{session@UserID}`) |
|
|
37
|
+
| `#{input@add1.id}` | ID of a record created in the same input batch |
|
|
38
|
+
| `#{payload$Target}` | Rendered output of a named embed |
|
|
39
|
+
| `#{unique}` | Generated unique ID |
|
|
40
|
+
|
|
41
|
+
### Defaults
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
#{request@Param!fallback}
|
|
45
|
+
#{session@CustomerID!#{request@CustomerID}} ← token as default (nested)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Key Modifiers
|
|
49
|
+
|
|
50
|
+
| Modifier | Effect |
|
|
51
|
+
|----------|--------|
|
|
52
|
+
| `:cached$Target` | Deferred read from named embed — resolves after all embeds execute |
|
|
53
|
+
| `:no_escape` | Bypasses all format-based escaping (HTML, JSON, XML, CSV) — raw value output |
|
|
54
|
+
| `:raw` | Deferred injection via placeholder (final render pass) — does not re-parse tokens in field values |
|
|
55
|
+
| `:escape_json` | Forces JSON-safe escaping regardless of output format |
|
|
56
|
+
| `:url_encode` | URL percent-encodes the value |
|
|
57
|
+
| `:url_decode` | URL-decodes the value |
|
|
58
|
+
| `:truncate` | Truncates to 100 characters, appending "..." |
|
|
59
|
+
| `:{format}` | .NET format string — e.g. `:d` (short date), `:f2` (2 decimal places) |
|
|
60
|
+
|
|
61
|
+
**Rule**: Always pair `:cached` with an explicit `$Target`. Without it, resolution is ambiguous.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Tag Syntax
|
|
66
|
+
|
|
67
|
+
Two systems — do not conflate with tokens (`#{...}`):
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<#_tagname attr="val"/> system tags (structural, underscore prefix)
|
|
71
|
+
<#CustomSection>...</#Custom> custom tags (user-defined named sections)
|
|
72
|
+
<@slotName>...</@slotName> slot tags (master template slots)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### System Tag Reference
|
|
76
|
+
|
|
77
|
+
| Tag | Purpose |
|
|
78
|
+
|-----|---------|
|
|
79
|
+
| `<#_embed url="..." .../>` | Inline another output, content, or input operation |
|
|
80
|
+
| `<#_row>...</#_row>` | Repeating section — renders once per result row |
|
|
81
|
+
| `<#_header>` / `<#_footer>` | Before / after all rows |
|
|
82
|
+
| `<#_noresult>` | Renders when query returns zero rows |
|
|
83
|
+
| `<#_empty>` | Also renders on zero rows (after noresult, sequential) |
|
|
84
|
+
| `<#_successful>` | Inside an input embed — block runs on success |
|
|
85
|
+
| `<#_failed>` | Inside an input embed — block runs on failure |
|
|
86
|
+
| `<#_value.Field value="_null">` | Conditional block: renders when Field is null |
|
|
87
|
+
| `<#_value.Field modifier="exclude" value="_null">` | Renders when Field is NOT null |
|
|
88
|
+
| `<#_include target="name">val</#_include>` | Set named variable for downstream use |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Embed System
|
|
93
|
+
|
|
94
|
+
Embeds are the primary composition mechanism. They make an internal API call and inline the result.
|
|
95
|
+
|
|
96
|
+
```html
|
|
97
|
+
<!-- Self-closing -->
|
|
98
|
+
<#_embed url="/api/output/{uid}"
|
|
99
|
+
name="label.name"
|
|
100
|
+
secure="false"
|
|
101
|
+
execute="true"
|
|
102
|
+
target="MyTarget"/>
|
|
103
|
+
|
|
104
|
+
<!-- Block form — override template sections inline -->
|
|
105
|
+
<#_embed.myid url="/api/output/{uid}" name="label.name">
|
|
106
|
+
<#_row><li>#{value@Name}</li></#_row>
|
|
107
|
+
<#_noresult><p>None.</p></#_noresult>
|
|
108
|
+
</#_embed.myid>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Attribute order**: `url` first, `name` second, then the rest.
|
|
112
|
+
|
|
113
|
+
**Serialization id** (`.myid` suffix) is required when nesting block embeds — it lets the parser match open/close tags in nested structures.
|
|
114
|
+
|
|
115
|
+
### Embed Attributes
|
|
116
|
+
|
|
117
|
+
| Attribute | Default | Notes |
|
|
118
|
+
|-----------|---------|-------|
|
|
119
|
+
| `url` | required | Endpoint to embed |
|
|
120
|
+
| `name` | — | Label for debugging and payload ID |
|
|
121
|
+
| `target` | — | Named context for `:cached` tokens and `#{payload$...}`; comma-separated for multiple |
|
|
122
|
+
| `secure` | `true` | `false` bypasses access control for this request |
|
|
123
|
+
| `execute` | `true` | `false` skips the call entirely |
|
|
124
|
+
| `hide` | `false` | `true` executes but suppresses output (side-effect embeds) |
|
|
125
|
+
| `payload` | `true` | `false` skips caching rendered output for `#{payload$...}`. When `hide=true`, defaults to `false` — set explicitly to cache a hidden embed's output |
|
|
126
|
+
| `catch_exception` | `"401,406"` | HTTP codes caught silently; `"true"` catches all |
|
|
127
|
+
|
|
128
|
+
**URL prefixes**: `/api/output/{uid}` (query), `/api/output/entity/{uid}/{rowId}` (single row), `/api/content/{uid}` (content), `/api/input/submit` (CRUD), `/api/message/content/{uid}` (message). Short aliases: `/api/o/`, `/api/c/`, `/api/i/s`
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Output Templates
|
|
133
|
+
|
|
134
|
+
An output renders rows through template sections:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
[_header] → [_row × N] → [_footer]
|
|
138
|
+
↘ [_noresult] + [_empty] if N = 0
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Custom sections (`<#SectionName>...</#SectionName>`) are named blocks that calling templates can target by name. They make outputs composable — a caller picks which section to render.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## HTTP API Reference
|
|
146
|
+
|
|
147
|
+
### Read
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
GET /api/output/{uid}
|
|
151
|
+
GET /api/output/entity/{entityUid}
|
|
152
|
+
GET /api/output/entity/{entityUid}/{rowId}
|
|
153
|
+
GET /api/o/{uid} ← shorthand
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`{entityUid}` is the entity's own UID — not an entity_column UID. For system entities, the UID is the physical table name (e.g., `content`, `user`, `output`). See `core-entities.md` for the full list. Example:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
GET /api/output/entity/content?_template=json_indented&_limit=10
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Filter/control params:**
|
|
163
|
+
|
|
164
|
+
| Param | Meaning |
|
|
165
|
+
|-------|---------|
|
|
166
|
+
| `_filter@Field=value` | Filter rows |
|
|
167
|
+
| `_filter@Field:restrictive=value` | Filter cannot be overridden by any outer frame in the request stack |
|
|
168
|
+
| `_limit=25` | Max rows |
|
|
169
|
+
| `_template=json_indented` | Override output format |
|
|
170
|
+
| `voidcache=true` | Flush all caches globally — accepted on any endpoint |
|
|
171
|
+
|
|
172
|
+
### Write
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
POST /api/input/submit
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Row parameter syntax (URL-encoded, multiple in one request):
|
|
179
|
+
```
|
|
180
|
+
RowID:{ref};column:{entity_column_uid}={value}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Column UIDs: core system entities use `{entity}.{ColumnName}` (e.g., `content.Content`); custom app entity columns use opaque UIDs — retrieve via `GET /api/output/entity/{entityUid}?_template=json_indented&_limit=1`.
|
|
184
|
+
|
|
185
|
+
`{ref}` values:
|
|
186
|
+
- `add1`, `add2`, … → insert new record (labeled for cross-reference)
|
|
187
|
+
- `{id}` → update existing record by ID
|
|
188
|
+
- `del{id}` → delete record
|
|
189
|
+
|
|
190
|
+
Cross-referencing within a batch — use the pairing key directly as the column value:
|
|
191
|
+
```
|
|
192
|
+
RowID:add2;column:output_value.OutputID=add1
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`#{input@add1.id}` is the template token form — only valid inside rendered content, not in direct API calls.
|
|
196
|
+
|
|
197
|
+
**Special values**: `_now` (current datetime), `_null` (null/empty)
|
|
198
|
+
|
|
199
|
+
**Required**: `_confirm=true` to execute any write. Optional: `_debug=true`.
|
|
200
|
+
|
|
201
|
+
### Content / Auth
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
GET /api/content/{uid}
|
|
205
|
+
GET /api/c/{uid}
|
|
206
|
+
GET /api/authenticate?action=login
|
|
207
|
+
GET /api/authenticate?action=logout
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Input Forms
|
|
213
|
+
|
|
214
|
+
Use `data-os-form` instead of manual JS:
|
|
215
|
+
|
|
216
|
+
```html
|
|
217
|
+
<form id="my-form" data-os-form="{validate: true, done: function() {...}}">
|
|
218
|
+
<input name="RowID:{id};column:table.Field" value="#{value@Field}" />
|
|
219
|
+
</form>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Submit: `os.form.submit('#my-form')`
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Security
|
|
227
|
+
|
|
228
|
+
- Security always evaluates against `LoggedInUser` — never `CurrentUser`.
|
|
229
|
+
- Impersonation changes the render context (`CurrentUser`) but not the security context.
|
|
230
|
+
- `Administrator` flag bypasses all security checks.
|
|
231
|
+
- `secure="false"` on an embed bypasses access control for that embed's request only.
|
|
232
|
+
- Default: 401 (access denied) and 406 (validation failed) from embeds are caught silently.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Schema Discovery
|
|
237
|
+
|
|
238
|
+
To find column names and UIDs for any DBO system entity (output, content, message, user, security, etc.):
|
|
239
|
+
|
|
240
|
+
**Schema catalog** (primary): `dbo-documentation-project/docs/schema-catalog/core-entities.md`
|
|
241
|
+
- 38 core entities, structured markdown tables
|
|
242
|
+
- Load into LLM context for API construction tasks
|
|
243
|
+
|
|
244
|
+
**Live API** (for custom app entities):
|
|
245
|
+
```
|
|
246
|
+
GET /api/output/entity/{entityUid}?_template=json_indented&_limit=1
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Input submit column syntax** uses physical names — not UIDs:
|
|
250
|
+
```
|
|
251
|
+
column:{physical_table}.{PhysicalColumnName}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Identifiers
|
|
257
|
+
|
|
258
|
+
- **Use UIDs** in templates, tokens, and application code — stable across environments.
|
|
259
|
+
- **Numeric IDs** are environment-specific. Do not hard-code in templates.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Common Build Patterns
|
|
264
|
+
|
|
265
|
+
**Data read with inline template:**
|
|
266
|
+
```html
|
|
267
|
+
<#_embed.list url="/api/output/{uid}" name="my.list">
|
|
268
|
+
<#_row><div>#{value@Name}</div></#_row>
|
|
269
|
+
<#_noresult><p>No results.</p></#_noresult>
|
|
270
|
+
</#_embed.list>
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**Two-phase write (insert + cross-reference):**
|
|
274
|
+
```html
|
|
275
|
+
<#_embed.first url="/api/input/submit?_confirm=true
|
|
276
|
+
&RowID:add1;column:kj_job.TypeID=24">
|
|
277
|
+
<#_successful>
|
|
278
|
+
<#_embed url="/api/input/submit?_confirm=true
|
|
279
|
+
&RowID:add2;column:kj_Transactions.JobID=#{input@add1.id}"/>
|
|
280
|
+
</#_successful>
|
|
281
|
+
<#_failed>Write failed.</#_failed>
|
|
282
|
+
</#_embed.first>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**Read from a named embed's payload:**
|
|
286
|
+
```html
|
|
287
|
+
<#_embed url="/api/output/{uid}" target="MyOutput"/>
|
|
288
|
+
#{value@SomeField:cached$MyOutput}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Flow file pattern** (backend action handler — no UI output):
|
|
292
|
+
```html
|
|
293
|
+
<!-- 1. Fetch context (hidden) -->
|
|
294
|
+
<#_embed url="/api/output/{ctx-uid}" target="Ctx" hide="true" secure="false"/>
|
|
295
|
+
<!-- 2. Execute write -->
|
|
296
|
+
<#_embed.action url="/api/input/submit?_confirm=true&RowID:add1;...">
|
|
297
|
+
<#_successful>{"ok": true, "id": "#{input@add1.id}"}</#_successful>
|
|
298
|
+
<#_failed>{"ok": false}</#_failed>
|
|
299
|
+
</#_embed.action>
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Full Docs
|
|
305
|
+
|
|
306
|
+
| Document | Path |
|
|
307
|
+
|----------|------|
|
|
308
|
+
| Schema catalog — 38 core entities | `docs/core-entities.md` |
|
|
309
|
+
| Output — Query | `docs/output-query.md` |
|
|
310
|
+
| App (Pending) | `docs/API/app.md` |
|
|
311
|
+
| Authenticate (Pending) | `docs/API/athenticate.md` |
|
|
312
|
+
| Cache (Pending) | `docs/API/cache.md` |
|
|
313
|
+
| Content (Pending) | `docs/API/content.md` |
|
|
314
|
+
| Data Source (Pending) | `docs/API/data_source.md` |
|
|
315
|
+
| Message (Pending) | `docs/API/message` |
|
|
316
|
+
| Input / Submit (Pending) | `docs/API/input.md` |
|
|
317
|
+
| Instance (Pending) | `docs/API/instance.md` |
|
|
318
|
+
| Log (Pending) | `docs/API/log.md` |
|
|
319
|
+
| Media (Pending) | `docs/API/media.md` |
|
|
320
|
+
| Output by Entity (Pending) | `docs/API/output_by_entity.md` |
|
|
321
|
+
| Upload (Pending) | `docs/API/upload.md` |
|
|
322
|
+
|
|
323
|
+
All paths relative to the repository root.
|