sirius-framework-mcp 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.
- package/LICENSE +191 -0
- package/README.md +160 -0
- package/dist/grammars/tree-sitter-java.wasm +0 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +247 -0
- package/dist/index.js.map +1 -0
- package/dist/java-parser.d.ts +25 -0
- package/dist/java-parser.js +281 -0
- package/dist/java-parser.js.map +1 -0
- package/dist/prompts/index.d.ts +9 -0
- package/dist/prompts/index.js +15 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/workflows.d.ts +27 -0
- package/dist/prompts/workflows.js +317 -0
- package/dist/prompts/workflows.js.map +1 -0
- package/dist/resources/biz/analytics.md +157 -0
- package/dist/resources/biz/biz-controller.md +151 -0
- package/dist/resources/biz/codelists.md +154 -0
- package/dist/resources/biz/entity-triple.md +142 -0
- package/dist/resources/biz/importer.md +153 -0
- package/dist/resources/biz/isenguard.md +156 -0
- package/dist/resources/biz/jobs.md +145 -0
- package/dist/resources/biz/processes.md +155 -0
- package/dist/resources/biz/storage.md +149 -0
- package/dist/resources/biz/tenants.md +159 -0
- package/dist/resources/biz/testing.md +127 -0
- package/dist/resources/db/composites.md +145 -0
- package/dist/resources/db/entities.md +156 -0
- package/dist/resources/db/mixing.md +176 -0
- package/dist/resources/db/queries.md +178 -0
- package/dist/resources/db/refs.md +135 -0
- package/dist/resources/index.d.ts +27 -0
- package/dist/resources/index.js +68 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/kernel/async.md +189 -0
- package/dist/resources/kernel/commons.md +203 -0
- package/dist/resources/kernel/config.md +155 -0
- package/dist/resources/kernel/di.md +138 -0
- package/dist/resources/kernel/lifecycle.md +146 -0
- package/dist/resources/loader.d.ts +9 -0
- package/dist/resources/loader.js +17 -0
- package/dist/resources/loader.js.map +1 -0
- package/dist/resources/web/controllers.md +151 -0
- package/dist/resources/web/services.md +136 -0
- package/dist/resources/web/templates.md +162 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/introspection.d.ts +55 -0
- package/dist/tools/introspection.js +233 -0
- package/dist/tools/introspection.js.map +1 -0
- package/dist/tools/scaffold.d.ts +64 -0
- package/dist/tools/scaffold.js +505 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/workspace.d.ts +37 -0
- package/dist/workspace.js +185 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Controllers
|
|
2
|
+
|
|
3
|
+
Controllers in sirius-web handle HTTP requests by mapping URI patterns to methods.
|
|
4
|
+
They live in `sirius.web.controller` (base framework) and `sirius.biz.web` (business layer).
|
|
5
|
+
|
|
6
|
+
## BasicController — The Base Class
|
|
7
|
+
|
|
8
|
+
All controllers extend `BasicController`, which provides:
|
|
9
|
+
|
|
10
|
+
- `getUser()` — returns the current `UserInfo`
|
|
11
|
+
- `hasPermission(String)` — checks if the current user holds a permission
|
|
12
|
+
- `assertPermission(String)` — throws if the permission is missing
|
|
13
|
+
- `assertNotNull(Object)` — throws a 404-style error if the object is null
|
|
14
|
+
- `showSavedMessage()` — flashes a "Changes have been saved" message
|
|
15
|
+
- `showDeletedMessage()` — flashes a "Object was deleted" message
|
|
16
|
+
- `fail(WebContext, HandledException)` — renders an error template
|
|
17
|
+
|
|
18
|
+
In sirius-biz, controllers typically extend `BizController` which adds tenant-aware
|
|
19
|
+
helpers like `findForTenant()` and `assertTenant()`.
|
|
20
|
+
|
|
21
|
+
## @Routed — Mapping URIs to Methods
|
|
22
|
+
|
|
23
|
+
`@Routed` attaches a URI pattern to a controller method:
|
|
24
|
+
|
|
25
|
+
```java
|
|
26
|
+
@Routed("/products/:1/edit")
|
|
27
|
+
public void editProduct(WebContext webContext, String productId) {
|
|
28
|
+
// :1 binds the path segment to the first String parameter after WebContext
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Pattern elements:**
|
|
33
|
+
- String literal (`/products`) — must match exactly
|
|
34
|
+
- `:1`, `:2`, ... — captures the path segment into the n-th method parameter (after WebContext)
|
|
35
|
+
- `*` — matches any single path segment (value is discarded)
|
|
36
|
+
- `**` — variadic, must be last; matched segments go into a `List<String>` parameter
|
|
37
|
+
- `#{name}` — captures the segment into a request attribute
|
|
38
|
+
- `${i18n.key}` — matches the NLS-translated value of the key
|
|
39
|
+
|
|
40
|
+
**Priority:** When routes conflict (e.g., `/foo/:1` vs `/foo/special`), set
|
|
41
|
+
`priority` on the more specific route to a value below `PriorityCollector.DEFAULT_PRIORITY`:
|
|
42
|
+
|
|
43
|
+
```java
|
|
44
|
+
@Routed(value = "/foo/special", priority = 90)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**HTTP methods:** By default all methods are accepted. Restrict with:
|
|
48
|
+
|
|
49
|
+
```java
|
|
50
|
+
@Routed(value = "/api/items", methods = HttpMethod.POST)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## @LoginRequired and @Permission
|
|
54
|
+
|
|
55
|
+
Place these on routed methods to enforce access control:
|
|
56
|
+
|
|
57
|
+
```java
|
|
58
|
+
@Routed("/admin/users")
|
|
59
|
+
@LoginRequired
|
|
60
|
+
@Permission("permission-manage-users")
|
|
61
|
+
public void users(WebContext webContext) { ... }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`@LoginRequired` requires any authenticated user. `@Permission("name")` requires
|
|
65
|
+
the named permission. Both can be combined; the login check runs first.
|
|
66
|
+
|
|
67
|
+
## @DefaultRoute — Fallback on Error
|
|
68
|
+
|
|
69
|
+
Mark one routed method per controller with `@DefaultRoute`. If any other route in
|
|
70
|
+
the same controller throws an error, the framework re-dispatches to the default
|
|
71
|
+
route and displays the error message there, rather than showing a generic error page:
|
|
72
|
+
|
|
73
|
+
```java
|
|
74
|
+
@Routed("/products")
|
|
75
|
+
@DefaultRoute
|
|
76
|
+
public void products(WebContext webContext) {
|
|
77
|
+
// This serves as the fallback — e.g., list view
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## WebContext — The Request Object
|
|
82
|
+
|
|
83
|
+
Every routed method receives a `WebContext` as its first parameter. Key methods:
|
|
84
|
+
|
|
85
|
+
- `webContext.get("paramName")` — returns a `Value` for a query/form parameter
|
|
86
|
+
- `webContext.isSafePOST()` — true if POST with a valid CSRF token
|
|
87
|
+
- `webContext.ensureSafePOST()` — like `isSafePOST()` but throws on invalid token
|
|
88
|
+
- `webContext.respondWith().template("/templates/path.html.pasta", args...)` — render a Pasta template
|
|
89
|
+
- `webContext.respondWith().redirectToGet(url)` — HTTP redirect after POST
|
|
90
|
+
|
|
91
|
+
## Concrete Example
|
|
92
|
+
|
|
93
|
+
```java
|
|
94
|
+
@Register
|
|
95
|
+
public class ProductController extends BizController {
|
|
96
|
+
|
|
97
|
+
@Routed("/products")
|
|
98
|
+
@DefaultRoute
|
|
99
|
+
@LoginRequired
|
|
100
|
+
@Permission("permission-manage-products")
|
|
101
|
+
public void products(WebContext webContext) {
|
|
102
|
+
SQLQuery<Product> query = oma.select(Product.class)
|
|
103
|
+
.orderAsc(Product.NAME);
|
|
104
|
+
webContext.respondWith()
|
|
105
|
+
.template("/templates/products/list.html.pasta", query);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Routed("/product/:1/edit")
|
|
109
|
+
@LoginRequired
|
|
110
|
+
@Permission("permission-manage-products")
|
|
111
|
+
public void editProduct(WebContext webContext, String productId) {
|
|
112
|
+
Product product = findForTenant(Product.class, productId);
|
|
113
|
+
|
|
114
|
+
if (webContext.ensureSafePOST()) {
|
|
115
|
+
load(webContext, product);
|
|
116
|
+
oma.update(product);
|
|
117
|
+
showSavedMessage();
|
|
118
|
+
webContext.respondWith().redirectToGet("/products");
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
webContext.respondWith()
|
|
123
|
+
.template("/templates/products/edit.html.pasta", product);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@Routed("/product/:1/delete")
|
|
127
|
+
@LoginRequired
|
|
128
|
+
@Permission("permission-manage-products")
|
|
129
|
+
public void deleteProduct(WebContext webContext, String productId) {
|
|
130
|
+
Product product = findForTenant(Product.class, productId);
|
|
131
|
+
oma.delete(product);
|
|
132
|
+
showDeletedMessage();
|
|
133
|
+
webContext.respondWith().redirectToGet("/products");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Common Mistakes
|
|
139
|
+
|
|
140
|
+
1. **Forgetting `@Register`** — Controllers must be annotated with `@Register`
|
|
141
|
+
or they will not be discovered by the framework.
|
|
142
|
+
|
|
143
|
+
2. **Missing CSRF check on mutations** — Always use `ensureSafePOST()` or
|
|
144
|
+
`isSafePOST()` before modifying data. Skipping this opens CSRF vulnerabilities.
|
|
145
|
+
|
|
146
|
+
3. **Route priority conflicts** — If `/items/:1` and `/items/new` both exist,
|
|
147
|
+
the generic route may match first. Set a lower `priority` value on `/items/new`.
|
|
148
|
+
|
|
149
|
+
4. **Returning after redirect** — After calling `redirectToGet()`, always `return`
|
|
150
|
+
from the method. Otherwise the code continues and may try to render a template,
|
|
151
|
+
causing a "response already committed" error.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Web Services (API Endpoints)
|
|
2
|
+
|
|
3
|
+
Sirius-web provides annotations to mark controller methods as structured API
|
|
4
|
+
endpoints that automatically handle envelope wrapping and error formatting.
|
|
5
|
+
These live in `sirius.web.services`.
|
|
6
|
+
|
|
7
|
+
## @PublicService — External API
|
|
8
|
+
|
|
9
|
+
`@PublicService` marks a routed method as part of the public API. These services
|
|
10
|
+
are listed in the built-in API explorer (`/system/api`):
|
|
11
|
+
|
|
12
|
+
```java
|
|
13
|
+
@Routed("/api/v1/products")
|
|
14
|
+
@PublicService(apiName = "products", format = Format.JSON)
|
|
15
|
+
@LoginRequired
|
|
16
|
+
public void listProducts(WebContext webContext, JSONStructuredOutput out) {
|
|
17
|
+
out.beginArray("products");
|
|
18
|
+
oma.select(Product.class).iterateAll(product -> {
|
|
19
|
+
out.beginObject("product");
|
|
20
|
+
out.property("id", product.getIdAsString());
|
|
21
|
+
out.property("name", product.getName());
|
|
22
|
+
out.endObject();
|
|
23
|
+
});
|
|
24
|
+
out.endArray();
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Parameters:**
|
|
29
|
+
- `apiName` — Groups the service in the API explorer. Each API name needs a
|
|
30
|
+
matching config block under `http.api`.
|
|
31
|
+
- `format` — One of `Format.JSON`, `Format.XML`, or `Format.RAW`.
|
|
32
|
+
- `priority` — Sort order in the API explorer (default: 100).
|
|
33
|
+
- `path` — Custom documentation path, useful when the `@Routed` pattern contains
|
|
34
|
+
parameter placeholders (e.g., turning `/ps/:1/api` into `/ps/{process}/api`).
|
|
35
|
+
- `documentationUri` — Optional link to external documentation.
|
|
36
|
+
- `enforceMaintenanceMode` — If `true`, blocks calls when the scope is locked.
|
|
37
|
+
|
|
38
|
+
When `format` is `JSON`, the method must accept `JSONStructuredOutput` as its
|
|
39
|
+
second parameter. When `XML`, it must accept `XMLStructuredOutput`.
|
|
40
|
+
|
|
41
|
+
## @InternalService — Internal API
|
|
42
|
+
|
|
43
|
+
`@InternalService` works identically to `@PublicService` but is not listed in the
|
|
44
|
+
public API explorer. Use it for endpoints consumed only by internal systems:
|
|
45
|
+
|
|
46
|
+
```java
|
|
47
|
+
@Routed("/api/internal/sync")
|
|
48
|
+
@InternalService(format = Format.JSON)
|
|
49
|
+
public void sync(WebContext webContext, JSONStructuredOutput out) {
|
|
50
|
+
out.property("status", "ok");
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The only parameter is `format` (defaults to `Format.JSON`).
|
|
55
|
+
|
|
56
|
+
## Automatic Envelope Wrapping
|
|
57
|
+
|
|
58
|
+
For both annotations, the framework automatically:
|
|
59
|
+
|
|
60
|
+
1. Calls `beginResult()` before your method
|
|
61
|
+
2. Calls `endResult()` after your method
|
|
62
|
+
3. Sets `success: true` on normal completion
|
|
63
|
+
|
|
64
|
+
**Successful JSON response:**
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"success": true,
|
|
68
|
+
"error": false,
|
|
69
|
+
"products": [ ... ]
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Error JSON response (on exception):**
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"success": false,
|
|
77
|
+
"error": true,
|
|
78
|
+
"message": "The product was not found.",
|
|
79
|
+
"code": "PRODUCT_NOT_FOUND"
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The error code and HTTP status can be set via exception hints:
|
|
84
|
+
|
|
85
|
+
```java
|
|
86
|
+
throw Exceptions.createHandled()
|
|
87
|
+
.withDirectMessage("The product was not found.")
|
|
88
|
+
.hint(Controller.ERROR_CODE, "PRODUCT_NOT_FOUND")
|
|
89
|
+
.hint(Controller.HTTP_STATUS, 404)
|
|
90
|
+
.handle();
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
For `Format.RAW`, error responses simply return the appropriate HTTP status code
|
|
94
|
+
without a structured body.
|
|
95
|
+
|
|
96
|
+
## Format.RAW
|
|
97
|
+
|
|
98
|
+
Use `Format.RAW` when the method produces a non-structured response (e.g., a file
|
|
99
|
+
download or plain text). The method does not receive a structured output parameter
|
|
100
|
+
and handles the response directly via `WebContext`:
|
|
101
|
+
|
|
102
|
+
```java
|
|
103
|
+
@Routed("/api/v1/export")
|
|
104
|
+
@PublicService(apiName = "export", format = Format.RAW)
|
|
105
|
+
public void export(WebContext webContext) {
|
|
106
|
+
webContext.respondWith().direct(HttpResponseStatus.OK, "text/csv", csvData);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Swagger / OpenAPI Parameter Documentation
|
|
111
|
+
|
|
112
|
+
Service parameters should be documented with `@io.swagger.v3.oas.annotations.Parameter`
|
|
113
|
+
on each accepted query or form parameter. The API explorer picks these up:
|
|
114
|
+
|
|
115
|
+
```java
|
|
116
|
+
@Routed("/api/v1/products")
|
|
117
|
+
@PublicService(apiName = "products", format = Format.JSON)
|
|
118
|
+
@io.swagger.v3.oas.annotations.Parameter(name = "query", description = "Search filter")
|
|
119
|
+
@io.swagger.v3.oas.annotations.Parameter(name = "limit", description = "Max results")
|
|
120
|
+
public void listProducts(WebContext webContext, JSONStructuredOutput out) { ... }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Common Mistakes
|
|
124
|
+
|
|
125
|
+
1. **Wrong second parameter type** — `Format.JSON` requires `JSONStructuredOutput`;
|
|
126
|
+
`Format.XML` requires `XMLStructuredOutput`. Mismatching causes a startup error.
|
|
127
|
+
|
|
128
|
+
2. **Calling beginResult/endResult manually** — The framework handles this
|
|
129
|
+
automatically. Calling it again produces malformed output.
|
|
130
|
+
|
|
131
|
+
3. **Forgetting the apiName config** — Every `apiName` used in `@PublicService`
|
|
132
|
+
needs a corresponding `http.api.<apiName>` block in the config, or the API
|
|
133
|
+
explorer will not display the service correctly.
|
|
134
|
+
|
|
135
|
+
4. **Using @Routed(jsonCall = true)** — This is deprecated since 2021. Use
|
|
136
|
+
`@InternalService(format = Format.JSON)` instead.
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Templates (Pasta / Tagliatelle)
|
|
2
|
+
|
|
3
|
+
Sirius uses the Pasta/Tagliatelle template engine for server-side HTML rendering.
|
|
4
|
+
Template files use the `.html.pasta` extension and live under
|
|
5
|
+
`src/main/resources/default/templates/`.
|
|
6
|
+
|
|
7
|
+
## File Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
src/main/resources/default/
|
|
11
|
+
templates/biz/ # Page templates
|
|
12
|
+
taglib/ # Custom tag definitions (w:, t:, k:)
|
|
13
|
+
extensions/ # Extension point templates
|
|
14
|
+
mail/ # Email templates
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Templates are invoked from controllers via:
|
|
18
|
+
|
|
19
|
+
```java
|
|
20
|
+
webContext.respondWith().template("/templates/products/list.html.pasta", query);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Typed Arguments — `<i:arg>`
|
|
24
|
+
|
|
25
|
+
Every template declares its parameters at the top with `<i:arg>`:
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<i:arg type="sirius.db.jdbc.SmartQuery" name="query"/>
|
|
29
|
+
<i:arg type="String" name="title"/>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The types must be fully qualified Java class names. The arguments are passed
|
|
33
|
+
positionally from the controller's `template()` call.
|
|
34
|
+
|
|
35
|
+
## Control Flow
|
|
36
|
+
|
|
37
|
+
**Conditionals:**
|
|
38
|
+
```html
|
|
39
|
+
<i:if test="product.isNew()">
|
|
40
|
+
<h1>Create Product</h1>
|
|
41
|
+
</i:if>
|
|
42
|
+
<i:else>
|
|
43
|
+
<h1>Edit @product.getName()</h1>
|
|
44
|
+
</i:else>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Loops:**
|
|
48
|
+
```html
|
|
49
|
+
<i:for type="sirius.biz.model.Product" var="product" items="query.queryList()">
|
|
50
|
+
<tr>
|
|
51
|
+
<td>@product.getName()</td>
|
|
52
|
+
<td>@product.getPrice()</td>
|
|
53
|
+
</tr>
|
|
54
|
+
</i:for>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Local variables:**
|
|
58
|
+
```html
|
|
59
|
+
<i:local name="count" value="query.count()"/>
|
|
60
|
+
<p>Total: @count</p>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Inline expressions:**
|
|
64
|
+
Use `@` to output Java expressions directly: `@product.getName()`. For more
|
|
65
|
+
complex expressions, use `@(expression)`.
|
|
66
|
+
|
|
67
|
+
## Taglib Prefixes
|
|
68
|
+
|
|
69
|
+
Custom tags are organized by prefix:
|
|
70
|
+
|
|
71
|
+
- **`w:`** — Web widgets from sirius-web (e.g., `<w:page>`, `<w:table>`)
|
|
72
|
+
- **`t:`** — Tycho UI components from sirius-biz (e.g., `<t:page>`, `<t:sidebar>`,
|
|
73
|
+
`<t:searchHeader>`, `<t:datacards>`)
|
|
74
|
+
- **`e:`** — Extension points that can be filled by other modules
|
|
75
|
+
|
|
76
|
+
Tycho (`t:`) is the standard modern UI framework for sirius-biz applications.
|
|
77
|
+
Most pages use `<t:page>` as their root element.
|
|
78
|
+
|
|
79
|
+
## Internationalization — `@i18n`
|
|
80
|
+
|
|
81
|
+
Use `@i18n("key")` to output a translated string from the NLS system:
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<h1>@i18n("Product.plural")</h1>
|
|
85
|
+
<button>@i18n("NLS.save")</button>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The key is resolved via `NLS.get()` using the current request's language.
|
|
89
|
+
|
|
90
|
+
## Pragmas
|
|
91
|
+
|
|
92
|
+
Pragmas provide metadata about the template. They are declared at the top:
|
|
93
|
+
|
|
94
|
+
```html
|
|
95
|
+
<i:pragma name="title" value="Products"/>
|
|
96
|
+
<i:pragma name="description" value="Lists all products"/>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Pragmas can be read by parent templates or the framework to set page titles,
|
|
100
|
+
breadcrumbs, or other metadata.
|
|
101
|
+
|
|
102
|
+
## Concrete Template Example
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<i:arg type="sirius.biz.model.Product" name="product"/>
|
|
106
|
+
|
|
107
|
+
<i:pragma name="title" value="@apply('Edit: %s', product.getName())"/>
|
|
108
|
+
|
|
109
|
+
<t:page>
|
|
110
|
+
<i:block name="breadcrumbs">
|
|
111
|
+
<li><a href="/products">@i18n("Product.plural")</a></li>
|
|
112
|
+
<li>@product.getName()</li>
|
|
113
|
+
</i:block>
|
|
114
|
+
|
|
115
|
+
<i:block name="page-header">
|
|
116
|
+
<t:pageHeader title="@product.getName()"/>
|
|
117
|
+
</i:block>
|
|
118
|
+
|
|
119
|
+
<t:editForm url="@apply('/product/%s/edit', product.getIdAsString())">
|
|
120
|
+
<div class="row">
|
|
121
|
+
<t:textfield name="name" value="@product.getName()"
|
|
122
|
+
label="@i18n('Product.name')"
|
|
123
|
+
class="col-md-6"/>
|
|
124
|
+
<t:textfield name="price" value="@toUserString(product.getPrice())"
|
|
125
|
+
label="@i18n('Product.price')"
|
|
126
|
+
class="col-md-6"/>
|
|
127
|
+
</div>
|
|
128
|
+
</t:editForm>
|
|
129
|
+
</t:page>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Extension Points
|
|
133
|
+
|
|
134
|
+
Extensions allow modules to inject content into templates without modifying them:
|
|
135
|
+
|
|
136
|
+
```html
|
|
137
|
+
<!-- In the base template -->
|
|
138
|
+
<e:extensions target="product-details" product="@product"/>
|
|
139
|
+
|
|
140
|
+
<!-- In an extension template under extensions/product-details/ -->
|
|
141
|
+
<i:arg type="sirius.biz.model.Product" name="product"/>
|
|
142
|
+
<t:textfield name="sku" value="@product.getSku()" label="SKU"/>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
All templates found under `extensions/<target-name>/` are rendered at the
|
|
146
|
+
extension point, in alphabetical filename order.
|
|
147
|
+
|
|
148
|
+
## Common Mistakes
|
|
149
|
+
|
|
150
|
+
1. **Non-qualified type in `<i:arg>`** — Always use the fully qualified class name.
|
|
151
|
+
Writing `SmartQuery` instead of `sirius.db.jdbc.SmartQuery` causes a compile error.
|
|
152
|
+
|
|
153
|
+
2. **Forgetting to pass all arguments** — The `template()` call must pass arguments
|
|
154
|
+
in the same order as the `<i:arg>` declarations. Missing arguments cause
|
|
155
|
+
runtime errors.
|
|
156
|
+
|
|
157
|
+
3. **Using `@` in HTML attributes without quotes** — Expressions in attributes
|
|
158
|
+
must be quoted: `href="@url"`, not `href=@url`.
|
|
159
|
+
|
|
160
|
+
4. **Modifying taglib templates directly** — Tags under `taglib/` are framework-
|
|
161
|
+
provided. Override behavior through extensions or by creating custom tags rather
|
|
162
|
+
than editing built-in ones.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { listEntities, listFrameworkFlags, listRoutes, listJobs, listComposites, listControllers, } from "./introspection.js";
|
|
2
|
+
export type { EntityInfo, FrameworkFlag, FullRouteInfo, ControllerInfo, } from "./introspection.js";
|
|
3
|
+
export { scaffoldEntity, scaffoldJob, scaffoldTest, scaffoldComposite, scaffoldController, toUpperSnake, } from "./scaffold.js";
|
|
4
|
+
export type { FieldDefinition, ScaffoldFile, ScaffoldResult, ScaffoldEntityOptions, ScaffoldJobOptions, ScaffoldTestOptions, ScaffoldCompositeOptions, ScaffoldControllerOptions, } from "./scaffold.js";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { listEntities, listFrameworkFlags, listRoutes, listJobs, listComposites, listControllers, } from "./introspection.js";
|
|
2
|
+
export { scaffoldEntity, scaffoldJob, scaffoldTest, scaffoldComposite, scaffoldController, toUpperSnake, } from "./scaffold.js";
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,cAAc,EACd,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAS5B,OAAO,EACL,cAAc,EACd,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,GACb,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { JavaClassInfo, RouteInfo } from "../java-parser.js";
|
|
2
|
+
export interface EntityInfo {
|
|
3
|
+
name: string;
|
|
4
|
+
packageName: string;
|
|
5
|
+
superClass: string;
|
|
6
|
+
type: "sql" | "mongo" | "elastic" | "unknown";
|
|
7
|
+
annotations: JavaClassInfo["annotations"];
|
|
8
|
+
mappings: string[];
|
|
9
|
+
filePath: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FrameworkFlag {
|
|
12
|
+
name: string;
|
|
13
|
+
defaultValue: boolean;
|
|
14
|
+
description: string;
|
|
15
|
+
filePath: string;
|
|
16
|
+
}
|
|
17
|
+
export interface FullRouteInfo extends RouteInfo {
|
|
18
|
+
controller: string;
|
|
19
|
+
filePath: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ControllerInfo {
|
|
22
|
+
name: string;
|
|
23
|
+
packageName: string;
|
|
24
|
+
superClass: string;
|
|
25
|
+
routes: RouteInfo[];
|
|
26
|
+
filePath: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Scan for entity classes whose superClass matches known entity superclasses.
|
|
30
|
+
*/
|
|
31
|
+
export declare function listEntities(basePath: string): Promise<EntityInfo[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Parse HOCON component-*.conf files and extract sirius.frameworks flags.
|
|
34
|
+
*/
|
|
35
|
+
export declare function listFrameworkFlags(basePath: string): Promise<FrameworkFlag[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Extract routes from all Java files. Optionally filter by URI prefix.
|
|
38
|
+
*/
|
|
39
|
+
export declare function listRoutes(basePath: string, prefix?: string): Promise<FullRouteInfo[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Find JobFactory implementations by matching known job superclasses.
|
|
42
|
+
*/
|
|
43
|
+
export declare function listJobs(basePath: string): Promise<(JavaClassInfo & {
|
|
44
|
+
filePath: string;
|
|
45
|
+
})[]>;
|
|
46
|
+
/**
|
|
47
|
+
* Find Composite classes (superClass === "Composite").
|
|
48
|
+
*/
|
|
49
|
+
export declare function listComposites(basePath: string): Promise<(JavaClassInfo & {
|
|
50
|
+
filePath: string;
|
|
51
|
+
})[]>;
|
|
52
|
+
/**
|
|
53
|
+
* Find controller classes by matching known controller superclasses.
|
|
54
|
+
*/
|
|
55
|
+
export declare function listControllers(basePath: string): Promise<ControllerInfo[]>;
|