@metaobjectsdev/sdk 0.21.0 → 0.21.1
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/agent-context/skills/metaobjects-codegen/references/java.md +70 -2
- package/agent-context/skills/metaobjects-prompts/references/java.md +8 -0
- package/agent-context/skills/metaobjects-runtime-ui/references/java.md +16 -0
- package/agent-context/templates/always-on.md.mustache +1 -0
- package/package.json +2 -2
|
@@ -89,9 +89,10 @@ concrete imports and signatures so you don't have to guess them.
|
|
|
89
89
|
|
|
90
90
|
## `codegen-spring` generators
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
Most live in `metaobjects-codegen-spring` under
|
|
93
93
|
`com.metaobjects.generator.spring.*`; wire any subset, typically all three of the
|
|
94
|
-
first group together
|
|
94
|
+
first group together. (`JavaObjectCodeGenerator`, last row below, lives in the
|
|
95
|
+
separate `metaobjects-codegen-base` module instead.)
|
|
95
96
|
|
|
96
97
|
| Generator | Output |
|
|
97
98
|
|---|---|
|
|
@@ -105,6 +106,7 @@ first group together:
|
|
|
105
106
|
| `SpringRenderHelperGenerator` | the typed render helper for a `template.prompt` payload |
|
|
106
107
|
| `LlmTraceHelperGenerator` | `<Entity>TraceHelper.java` per concrete entity — the LLM-trace helper |
|
|
107
108
|
| `SpringFilterAllowlistGenerator` | per-entity filter allowlist |
|
|
109
|
+
| `JavaObjectCodeGenerator` | module `metaobjects-codegen-base` (`com.metaobjects.generator.direct.object.javacode`), a separate module from the Spring generators above. Flavor-selected via the `flavor` generator arg. `flavor=pojoAware` → `class <Name> extends PojoObject` (a concrete `MetaObjectAware` class with a `(MetaObject)` constructor) — its inherited `getMetaData()` back-reference is what breaks a default Jackson/Gson mapper, see "Serializing generated objects" below. `flavor=valueObject` → `class <Name> extends ValueObject` (map-backed; less hostile to a default mapper, but still not the sanctioned serialization path). Either concrete flavor also emits a `<Name>Extractor` plus a self-registering `ObjectClassBindingProvider`. For a plain default-Jackson-friendly type, use the `codegen-spring` record surface instead — never `pojoAware`. |
|
|
108
110
|
|
|
109
111
|
**Projections (read-only views).** An `object.projection` (read-only `source.rdb`
|
|
110
112
|
`@kind: view` child) is served read-only through OMDB at the ObjectManager layer
|
|
@@ -153,3 +155,69 @@ polymorphic + per-subtype-scoped repository seam the consumer implements against
|
|
|
153
155
|
Spring Data JPA / JDBC. Conformance-gated by `fixtures/api-contract-conformance/tph`
|
|
154
156
|
(HTTP wire shape) and `fixtures/persistence-conformance/tph-*` (single-table
|
|
155
157
|
runtime semantics).
|
|
158
|
+
|
|
159
|
+
## Serializing generated objects
|
|
160
|
+
|
|
161
|
+
Two paths hand you a `MetaObjectAware` instance: (a) `JavaObjectCodeGenerator`'s
|
|
162
|
+
flavored codegen above (a `pojoAware` or `valueObject` class), and (b) the om/omdb
|
|
163
|
+
runtime (`ObjectManager.getObjects(...)` / `MetaObject.newInstance()` — see the
|
|
164
|
+
runtime-ui reference). **A default Jackson/Gson mapper over a `PojoObject` subtype
|
|
165
|
+
fails on the `MetaObject` back-reference** — the inherited `getMetaData()` getter
|
|
166
|
+
leads a bean-style mapper into the metadata graph, and on a modular JVM into
|
|
167
|
+
`InaccessibleObjectException`. This is expected, not a bug to work around. If you
|
|
168
|
+
want a type that serializes cleanly with a bare default mapper, use the
|
|
169
|
+
`codegen-spring` record surface (`SpringDtoGenerator` / `SpringPayloadGenerator` /
|
|
170
|
+
`SpringValueObjectGenerator`) instead — never `pojoAware`.
|
|
171
|
+
|
|
172
|
+
Serialize any `MetaObjectAware` instance through the MetaObjects JSON layer's
|
|
173
|
+
`JsonObjectWriter`/`JsonObjectReader`, not a bare mapper — it applies the temporal
|
|
174
|
+
wire form below, and read/write round-trip through the same pair of calls:
|
|
175
|
+
|
|
176
|
+
```java
|
|
177
|
+
import com.metaobjects.io.object.json.JsonObjectWriter;
|
|
178
|
+
import com.metaobjects.io.object.json.JsonObjectReader;
|
|
179
|
+
import com.metaobjects.loader.MetaDataLoader;
|
|
180
|
+
import com.metaobjects.object.MetaObject;
|
|
181
|
+
|
|
182
|
+
import java.io.StringReader;
|
|
183
|
+
import java.io.StringWriter;
|
|
184
|
+
import java.nio.file.Path;
|
|
185
|
+
|
|
186
|
+
MetaDataLoader loader = MetaDataLoader.fromDirectory("app", Path.of("src/main/metaobjects"));
|
|
187
|
+
MetaObject mo = loader.getMetaObjectByName("acme::blog::Author");
|
|
188
|
+
|
|
189
|
+
// pojoAware-flavor generated class: public Author(MetaObject mo) { super(mo); }
|
|
190
|
+
Author author = new Author(mo);
|
|
191
|
+
author.setName("Ada");
|
|
192
|
+
author.setBirthDate(new java.util.Date()); // field.date
|
|
193
|
+
|
|
194
|
+
// Write
|
|
195
|
+
StringWriter out = new StringWriter();
|
|
196
|
+
JsonObjectWriter.writeObject(author, out);
|
|
197
|
+
String json = out.toString();
|
|
198
|
+
// {"@type":"acme::blog::Author","name":"Ada","birthDate":"2026-06-03"}
|
|
199
|
+
|
|
200
|
+
// Read
|
|
201
|
+
Author roundTripped = JsonObjectReader.readObject(Author.class, mo, new StringReader(json));
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Wire form** (`field.date` / `field.timestamp`):
|
|
205
|
+
|
|
206
|
+
| Field | Wire form | Example |
|
|
207
|
+
|---|---|---|
|
|
208
|
+
| `field.date` | calendar date of the instant at UTC — `YYYY-MM-DD` | `"2026-06-03"` |
|
|
209
|
+
| `field.timestamp` + `@localTime: true` | wall clock of the instant at UTC, no `Z` | `"2026-06-03T14:30:00.123"` |
|
|
210
|
+
| `field.timestamp` (default, tz-aware) | UTC instant, with `Z` | `"2026-06-03T14:30:00.123Z"` |
|
|
211
|
+
|
|
212
|
+
Fraction is millisecond resolution, trailing zeros stripped, and the `.` plus
|
|
213
|
+
fraction omitted entirely when zero (`.123`→`.123`, `.120`→`.12`, `.100`→`.1`,
|
|
214
|
+
`.000`→omitted). A `null` value writes JSON `null`. Readers are tolerant and
|
|
215
|
+
backward-compatible: a JSON **number** is still read as **legacy epoch
|
|
216
|
+
milliseconds**; a JSON **string** is tried in order as an ISO instant (the `Z`
|
|
217
|
+
form) → a local date-time (no `Z`) → a date-only form, failing with a message
|
|
218
|
+
naming all three accepted forms.
|
|
219
|
+
|
|
220
|
+
**Known bounded caveat:** a hand-constructed `field.date` value carrying a
|
|
221
|
+
sub-day time component writes as the calendar date only (truncated on first
|
|
222
|
+
write, stable thereafter) — this matches the shipped OMDB DATE codec, which
|
|
223
|
+
anchors DATE columns at midnight UTC.
|
|
@@ -53,6 +53,14 @@ rather than a throw. The payload record itself comes from `SpringPayloadGenerato
|
|
|
53
53
|
— the parser is a companion to it, so the parser and payload VO can't silently
|
|
54
54
|
drift.
|
|
55
55
|
|
|
56
|
+
Both `parse()` and `extractLenient(...)` here return **plain Java 21 records** —
|
|
57
|
+
safe with any mapper, nothing special needed. That's specific to this
|
|
58
|
+
`codegen-spring` extract tier: the codegen-base flavored `<Name>Extractor` and the
|
|
59
|
+
raw `MetaObjectExtractor` (the alternative extraction path, see the codegen
|
|
60
|
+
reference) return `MetaObjectAware` instances instead, and those need
|
|
61
|
+
`JsonObjectWriter`/`MetaObjectSerializer` — not a bare mapper — to serialize
|
|
62
|
+
correctly (see the codegen reference's "Serializing generated objects" section).
|
|
63
|
+
|
|
56
64
|
## The output-format prompt fragment (FR-010)
|
|
57
65
|
|
|
58
66
|
For every json/xml-format `template.output`, `codegen-spring`'s
|
|
@@ -65,6 +65,22 @@ try {
|
|
|
65
65
|
taking a `QueryOptions` (built from an `Expression`). `ValueObject` is the
|
|
66
66
|
map-backed runtime carrier.
|
|
67
67
|
|
|
68
|
+
## Serializing a row
|
|
69
|
+
|
|
70
|
+
A `ValueObject` **is** a `Map<String, Object>`, so a default Jackson
|
|
71
|
+
`ObjectMapper` map-serializes it without special configuration — you may not
|
|
72
|
+
hit a hard failure at all. The hard failure other shapes hit is the
|
|
73
|
+
**`pojoAware`** codegen flavor's bean shape (a public `getMetaData()`
|
|
74
|
+
back-reference a bean-style mapper walks into) and any direct Gson field walk
|
|
75
|
+
over a `MetaObjectAware` instance — an OMDB `ValueObject` row sidesteps both.
|
|
76
|
+
|
|
77
|
+
Even so, the MetaObjects JSON layer (`JsonObjectWriter`/`JsonObjectReader`,
|
|
78
|
+
`com.metaobjects.io.object.json`) is the sanctioned path for an OMDB row
|
|
79
|
+
regardless of mapper friendliness — it's what applies the temporal wire form
|
|
80
|
+
(`field.date`/`field.timestamp` render per the cross-port contract; a default
|
|
81
|
+
mapper has no idea what shape those should take). See the codegen reference's
|
|
82
|
+
"Serializing generated objects" section for the write+read snippet.
|
|
83
|
+
|
|
68
84
|
## Spring wiring
|
|
69
85
|
|
|
70
86
|
`metaobjects-core-spring` (or the Spring Boot starter) declares an
|
|
@@ -15,6 +15,7 @@ spine; generated code is the disposable artifact. Regenerate with `{{codegenComm
|
|
|
15
15
|
- Never hand-edit generated files — change the metadata and regenerate (three-way merge preserves hand-written regions).
|
|
16
16
|
- Use the generated constants for any string that names metadata.
|
|
17
17
|
- The loaded metadata model is READ-ONLY — never inject nodes or mutate the tree at load time (no "enrich the model on load" hooks). Need an extra field/column? Author it in the metadata, or derive it during codegen (read the metadata, emit output). Mutating the loaded model makes it diverge from what's declared — a bad practice reserved for very rare cases.
|
|
18
|
+
- **JVM:** serialize a MetaObject-backed instance (a `pojoAware`-flavor generated class, a runtime `ValueObject`, or any `MetaObjectAware` type) through the MetaObjects JSON layer — never hand-configure a Jackson/Gson mapper around the framework fields to make a default mapper cope.
|
|
18
19
|
|
|
19
20
|
## Authoring rules you must not violate
|
|
20
21
|
- Nodes are fused-key maps: `{"<type>.<subType>": { ... }}` (e.g. `{"field.string": {"name": "email"}}`) — never split the type and subtype into separate keys.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/sdk",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"description": "Workspace helpers and agent-docs utilities for MetaObjects projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@metaobjectsdev/metadata": "0.21.
|
|
59
|
+
"@metaobjectsdev/metadata": "0.21.1",
|
|
60
60
|
"zod": "^3.23.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|