SDK generation
The SDK plugin generates a typed package from the database's stored definitions. While the database is open, it updates that package in the configured output directory.
The generated code calls the language binding and provides typed access to stored definitions.
Enable sdk in the plugin selection at open, with the output settings below.
Calls without it report the unavailable status.
Query results recursively omit fields containing empty objects or arrays. Generated row maps leave absent keys out. Null, empty strings, false, zero and array positions stay intact in the returned document.
Native time values
Generated native time fields use
java.time.Instant for timestamps and java.time.Duration for durations.
Use sd/instant-from-ticks, instant-to-ticks, duration-from-ticks and duration-to-ticks for native tick conversion.
The explicit tick conversions refuse precision loss and values outside the target range. These conversions perform no native operation.
A native time schema requires one string member, #utc or #dur, and sets additionalProperties to false.
For example, this schema describes a native timestamp:
{
"type": "object",
"properties": {
"#utc": {
"type": "string"
}
},
"required": [
"#utc"
],
"additionalProperties": false
}
Use #dur in both places for a duration schema.
Schema fields support lists and stored-schema references.
Scalar time fields also type query filters and rows.
Native time expression results use the same binding types.
An ordinary string schema stays text, including strings with a date-time format.
Native ticks are signed 64-bit counts of 100 ns.
Timestamp ticks count from the Unix epoch in UTC. Duration ticks can be negative.
Settings
Set clojure.dir to a dedicated directory for generated source.
Add this directory to your Clojure classpath and depend on the stardust binding.
The plugin controls all contents of the directory.
Keep your source files and database elsewhere.
(require '[stardust.core :as sd])
(with-open [database
(sd/open "people.db"
{:plugins {:sdk {:clojure {:dir "gen/people"}
:debounce {:#dur "PT0.25S"}
:max_wait {:#dur "PT2S"}}}})]
(with-open [sync-options (sd/parse "{maxWait {#dur PT10S}}" :dust)]
(sd/sdk-sync database sync-options)))The Clojure namespaces
The plugin writes sdk/schemas.clj, sdk/queries.clj, sdk/mutations.clj and sdk/expressions.clj when their definition types are present.
Each namespace declares model-fingerprint.
Definition paths use stable names: people/by_name becomes people-by-name.
Names collide only within one definition type.
Member, derived-name and reserved-name collisions report Model_Errors before publication.
Use (sd/sdk-status database) to inspect the diagnostics and correct the definition names.
Schema functions construct ordinary maps with exact wire keys.
Their -fields descriptors identify inferred types, list depth, schema references and required fields.
Pass nested schema maps through their named constructor functions.
For example, (schemas/person {:name "Ada" :address (schemas/parts-address {:city "Oslo"})}) uses the generated nested map adapter.
The existing typed binding encodes maps and records and decodes persistent host values.
Integer and floating values retain the binding's i64 and f64 semantics.
Entity positions use the binding's native link value.
Query functions return reusable reducibles with inferred row maps.
The -row-fields descriptors identify statically inferred columns.
Dynamic rows retain their original host shape, including positional vectors.
Mutation functions return the binding's commit map.
Expression functions build stored definitions with current database macros and return decoded host results.
Parameter functions accept generated keyword or string keys and authored wire keys.
Duplicate spellings of one field report an error.
An absent optional key retains its stored default or leaves its filter unbound.
A supplied nil remains explicit null.
Declared null parameters report missing_parameter.
Required predicate inputs must be present.
Supplied false, zero, empty text and empty collections remain supplied.
Aggregate and window result variables remain outputs.
For stored definitions named people/add, people/adults and double, use:
(require '[stardust.core :as sd]
'[sdk.queries :as queries]
'[sdk.mutations :as mutations]
'[sdk.expressions :as expressions])
(mutations/people-add database {:name "Ada" :age 36})
(into [] (queries/people-adults database)) ; => [{:name "Ada" :age 36}]
(expressions/double database {:n 21}) ; => 42
(reduce (fn [_ row] (reduced row)) nil (queries/people-adults database))Each reduction acquires its query and rows inside with-open.
Normal completion, reduced early termination and exceptions close both owners.
Reduction returns persistent host values that remain valid after cleanup.
Generated expressions also close their owned result document and program.
Runs
The plugin generates once at open, and again after commits that change definitions. Data commits do not start a run. A run reads all definitions from one committed snapshot.
Each successful render replaces the output directory's contents, including the startup run. See file ownership before choosing an output directory.
Call status to inspect these fields:
| Field | Contents |
|---|---|
enabled | Whether the plugin is enabled |
pending | Whether generation remains |
runs | Run count |
fingerprint | Generation model fingerprint |
outputs | Outputs, each with language, directory and file counts written and removed |
diagnostics | Diagnostics with severity, code, definition type and path, pointer, member, language and message |
failure | Last run failure, with code and message; absent after a successful run |
When to call sync
Generation runs automatically at open and after definition commits, according to the debounce settings. Opening the database or committing definitions can finish before the generated files are ready. Call sync before compiling or reading files that must include those definitions. Applications that can use the files after automatic generation finishes do not need an explicit sync.
The call requests a render immediately, bypassing debounce. It also rebuilds files when definitions have not changed.
Its options accept only the common maxWait option. A timeout leaves the requested run active.
Repeated waits after a timeout join that run. Inspect status when generation reports failed.
Without an output language, sync validates the model inline and writes no files.
File ownership
The plugin owns the entire configured output directory. Every successful render removes its previous contents, including edited files, unrelated files and subdirectories.
Keep application source, database files and other data outside this directory.
Do not edit generated files: the next run replaces your changes.
The plugin retains only its internal .stardust-sdk.lock file between runs.
The plugin renders and validates the package before it removes any files. Rendering errors leave the previous directory contents unchanged. A filesystem error during cleanup or writing can leave the directory empty or partly written. The next successful run clears that partial output and writes a fresh package. Use sync before a build and check its result.
Each file is written through an atomic rename. Rebuilding the whole directory is not atomic.
A destination lock prevents concurrent publication and reports Destination_Busy when another publisher holds it.
Use a separate output directory for each database, with no directory nested inside another output directory.
Cleanup removes symlinks inside the output directory without following them.
The output directory itself and the lock file must not be symlinks.
Directory inspection is limited to 65,536 entries, 64 levels and 16 MiB of stored paths.
An inspection failure leaves the previous contents unchanged.
Operations
| Operation | Returns | Summary |
|---|---|---|
| sdk-status | document | sdk.status() returns the SDK generator's owned status document. |
| sdk-sync | none | sdk.sync(options) waits until the SDK generator published the definitions committed before the call. |
sdk-status
[db]Parameters
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
db | Sdk | Borrowed for the call | Required | The sdk owner for this operation. Keep it alive during the call. |
Errors
| Status | When |
|---|---|
:unavailable | the database does not enable the sdk plugin |
:closed | the database is closed |
:out-of-memory | native memory is exhausted |
Notes
The document describes generation outputs, diagnostics and the last run: see runs.
Examples
Describe the SDK generator
(with-open [sync-options (sd/parse "{maxWait {#dur PT5S}}" :dust)]
(sd/sdk-sync db sync-options))
(sd/sdk-status db){
"enabled": true,
"pending": false,
"runs": 1,
"fingerprint": "sha256:f0e170ac54b67b0f9a8e4794922a586c21da2910b0766dcd3feb410b416b61e8"
}C exports: stardust_db_plugin_call, stardust_result_take_document, stardust_result_error, stardust_result_release
sdk-sync
[db][db options]Parameters
| Parameter | Type | Ownership | Default | Meaning |
|---|---|---|---|---|
db | Sdk | Borrowed for the call | Required | The sdk owner for this operation. Keep it alive during the call. |
options | Document | Borrowed for the call | Absent selects operation defaults | The borrowed call options, or none. Optional maxWait is a nonnegative native duration, such as {maxWait {#dur PT5S}}. Without it, or with zero, the call checks once. |
Errors
| Status | When |
|---|---|
:invalid-argument | options is not an object, or an option is invalid, duplicated or unsupported |
:failed | the plugin's work failed; status describes the failure |
:timeout | maxWait passed before the work finished |
:unavailable | the database does not enable the sdk plugin |
:closed | the database is closed |
Notes
Database close interrupts an active wait. See when to call sync.
Examples
Run the SDK generator and wait for it
(with-open [sync-options (sd/parse "{maxWait {#dur PT5S}}" :dust)]
(sd/sdk-sync db sync-options))
(sd/sdk-status db){
"enabled": true,
"pending": false,
"runs": 1,
"fingerprint": "sha256:f0e170ac54b67b0f9a8e4794922a586c21da2910b0766dcd3feb410b416b61e8"
}C exports: stardust_db_plugin_call, stardust_result_take_document, stardust_result_error, stardust_result_release