Documentation navigationNavigare documentație
ExamplesExemple · API 0.8.0
declarative-transform
Each example is a fixture directory validated at build time against the released contracts: a JSON contract, a declarative transform, a template, a curl sequence and the expected output. Guides embed these files verbatim so documentation cannot drift from validated fixtures.Fiecare exemplu este un director de fixture-uri validat la build față de contractele publicate: un contract JSON, o transformare declarativă, un șablon, o secvență curl și rezultatul așteptat. Ghidurile includ aceste fișiere textual, astfel încât documentația nu poate devia de fixture-urile validate.
Files in this fixtureFișierele acestui fixture
declarative-transform/contract.json · 505 bytes · sha256 78d18c0ad890c899…{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Person",
"type": "object",
"additionalProperties": false,
"required": ["first_name", "last_name", "email"],
"properties": {
"first_name": { "type": "string", "minLength": 1 },
"middle_name": { "type": "string", "minLength": 1 },
"last_name": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"phone": { "type": "string", "pattern": "^\\+[1-9][0-9]{6,14}$" }
}
}
declarative-transform/create-contract.request.json · 730 bytes · sha256 0a6751820334bfc2…{
"name": "Person",
"description": "Docs example: the person intake contract used by the declarative transform guide.",
"schema": "{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"title\": \"Person\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"first_name\", \"last_name\", \"email\"],\n \"properties\": {\n \"first_name\": { \"type\": \"string\", \"minLength\": 1 },\n \"middle_name\": { \"type\": \"string\", \"minLength\": 1 },\n \"last_name\": { \"type\": \"string\", \"minLength\": 1 },\n \"email\": { \"type\": \"string\", \"format\": \"email\" },\n \"phone\": { \"type\": \"string\", \"pattern\": \"^\\\\+[1-9][0-9]{6,14}$\" }\n }\n}\n"
}
declarative-transform/create-transform.request.json · 771 bytes · sha256 1ced46d12a123992…{
"name": "Person welcome projection",
"description": "Docs example: copies, concatenates and coalesces person fields.",
"source": "{\n \"language\": \"declarative-v1\",\n \"output\": {\n \"first_name\": { \"$copy\": \"/first_name\" },\n \"middle_name\": { \"$copy_optional\": \"/middle_name\" },\n \"display_name\": {\n \"$concat\": [\n { \"$copy\": \"/first_name\" },\n { \"$literal\": \" \" },\n { \"$copy\": \"/last_name\" }\n ]\n },\n \"preferred_contact\": {\n \"$coalesce\": [\n { \"$copy_optional\": \"/phone\" },\n { \"$copy_optional\": \"/email\" },\n { \"$literal\": \"none\" }\n ]\n },\n \"source\": { \"$literal\": \"docs-example\" }\n }\n}\n",
"format": "json"
}
declarative-transform/create-version.request.json · 29 bytes · sha256 c33d261b7a5878fd…{
"expected_revision": 1
}
declarative-transform/curl.sh · 3419 bytes · sha256 a5fd68d7d9ae80bb…#!/bin/sh
# Docula example: declarative transform.
# login -> create contract -> create version -> publish -> create transform -> create version -> publish.
# Requires curl and jq. Environment: DOCULA_API (API origin, e.g. https://docula.ro),
# DOCULA_ORIGIN (browser origin accepted by the API; defaults to DOCULA_API),
# DOCULA_USERNAME and DOCULA_PASSWORD (read from the environment, never stored here).
set -eu
API=${DOCULA_API:?set DOCULA_API to the API origin, for example http://127.0.0.1:18081}
ORIGIN=${DOCULA_ORIGIN:-$API}
HERE=$(cd "$(dirname "$0")" && pwd)
JAR=$(mktemp)
trap 'rm -f "$JAR"' EXIT
# 1. Login. The session cookie goes to the cookie jar; the CSRF token comes back in the JSON body.
CSRF=$(jq -n --arg u "${DOCULA_USERNAME:?}" --arg p "${DOCULA_PASSWORD:?}" '{username: $u, password: $p}' |
curl --fail --silent --show-error -c "$JAR" -H "Origin: $ORIGIN" -H 'Content-Type: application/json' \
--data-binary @- "$API/api/v1/auth/login" | jq -r '.csrf_token')
# api METHOD PATH [JSON-FILE]: every mutation needs the exact Origin, the session cookie and X-CSRF-Token.
api() {
if [ "$#" -ge 3 ]; then
curl --fail --silent --show-error -b "$JAR" -X "$1" -H "Origin: $ORIGIN" -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' --data-binary @"$3" "$API$2"
else
curl --fail --silent --show-error -b "$JAR" -X "$1" -H "Origin: $ORIGIN" -H "X-CSRF-Token: $CSRF" "$API$2"
fi
}
# 2. Create the contract draft (createContract). The schema travels as a JSON string.
CONTRACT=$(api POST /api/v1/contracts "$HERE/create-contract.request.json")
CONTRACT_ID=$(printf '%s' "$CONTRACT" | jq -r '.contract.id')
REVISION=$(printf '%s' "$CONTRACT" | jq -r '.contract.draft_revision')
# 3. Freeze the draft into version 1 (createContractVersion) using the draft revision you just read.
VERSION=$(jq --argjson rev "$REVISION" '.expected_revision = $rev' "$HERE/create-version.request.json" > "$JAR.body" && api POST "/api/v1/contracts/$CONTRACT_ID/versions" "$JAR.body")
CONTRACT_VERSION_ID=$(printf '%s' "$VERSION" | jq -r '.version.id')
CONTRACT_VERSION_NUMBER=$(printf '%s' "$VERSION" | jq -r '.version.number')
# 4. Publish the version (publishContractVersion). The body is an empty JSON object.
api POST "/api/v1/contracts/$CONTRACT_ID/versions/$CONTRACT_VERSION_NUMBER/publish" "$HERE/publish.request.json" > /dev/null
# 5. Create the transform draft (createTransform). The declarative-v1 program travels as a JSON string.
TRANSFORM=$(api POST /api/v1/transforms "$HERE/create-transform.request.json")
TRANSFORM_ID=$(printf '%s' "$TRANSFORM" | jq -r '.transform.id')
TRANSFORM_REVISION=$(printf '%s' "$TRANSFORM" | jq -r '.transform.draft_revision')
# 6. Freeze and publish transform version 1 (createTransformVersion, publishTransformVersion).
jq --argjson rev "$TRANSFORM_REVISION" '.expected_revision = $rev' "$HERE/create-version.request.json" > "$JAR.body"
TRANSFORM_VERSION=$(api POST "/api/v1/transforms/$TRANSFORM_ID/versions" "$JAR.body")
TRANSFORM_VERSION_ID=$(printf '%s' "$TRANSFORM_VERSION" | jq -r '.version.id')
TRANSFORM_VERSION_NUMBER=$(printf '%s' "$TRANSFORM_VERSION" | jq -r '.version.number')
api POST "/api/v1/transforms/$TRANSFORM_ID/versions/$TRANSFORM_VERSION_NUMBER/publish" "$HERE/publish.request.json" > /dev/null
rm -f "$JAR.body"
printf 'contract_version_id=%s\ntransform_version_id=%s\n' "$CONTRACT_VERSION_ID" "$TRANSFORM_VERSION_ID"
declarative-transform/expected-output.json · 138 bytes · sha256 c1143b19e46631cc…{"display_name":"Iulia Popescu","first_name":"Iulia","middle_name":null,"preferred_contact":"[email protected]","source":"docs-example"}
declarative-transform/fixture.json · 2800 bytes · sha256 ebf292f76fff3407…{
"schema": "docula.example-fixture/v1",
"slug": "declarative-transform",
"guide": "/developers/guides/declarative-v1-transforms",
"title": "Declarative-v1 transform",
"summary": "A person contract, a declarative-v1 program that uses every course operator ($copy, $copy_optional, $literal, $concat, $coalesce), a sample input, the exact output produced by the engine, and the curl sequence that publishes both the contract and the transform.",
"operations": ["login", "createContract", "createContractVersion", "publishContractVersion", "createTransform", "createTransformVersion", "publishTransformVersion"],
"related": ["contract-versioning", "docx-template"],
"transform": {
"definition": "transform.json",
"input": "input.json",
"expectedOutput": "expected-output.json",
"authority": "internal/transforms/examples_fixture_test.go"
},
"files": [
{ "path": "contract.json", "purpose": "JSON Schema 2020-12 contract the input must satisfy.", "validate": { "kind": "json-schema-2020-12" } },
{ "path": "transform.json", "purpose": "declarative-v1 program: copy, optional copy, literal, concat and coalesce.", "validate": { "kind": "declarative-v1" } },
{ "path": "input.json", "purpose": "Sample input case; satisfies contract.json and omits the optional fields.", "validate": { "kind": "instance", "schemaFile": "contract.json" } },
{ "path": "expected-output.json", "purpose": "Canonical JSON produced by the engine for input.json; regenerated by the Go test.", "validate": { "kind": "json" }, "authority": "internal/transforms/examples_fixture_test.go" },
{ "path": "create-contract.request.json", "purpose": "createContract body; schema embeds contract.json as a string.", "validate": { "kind": "openapi", "schema": "#/components/schemas/CreateContractRequest" }, "embeds": [{ "field": "schema", "file": "contract.json" }] },
{ "path": "create-transform.request.json", "purpose": "createTransform body; source embeds transform.json as a string.", "validate": { "kind": "openapi", "schema": "#/components/schemas/CreateTransformRequest", "expect": { "/format": "json" } }, "embeds": [{ "field": "source", "file": "transform.json" }] },
{ "path": "create-version.request.json", "purpose": "createContractVersion / createTransformVersion body carrying the expected draft revision.", "validate": { "kind": "openapi", "schema": "#/components/schemas/RevisionRequest" } },
{ "path": "publish.request.json", "purpose": "publishContractVersion / publishTransformVersion body: an empty JSON object.", "validate": { "kind": "openapi", "schema": "#/components/schemas/EmptyObject" } },
{ "path": "curl.sh", "purpose": "Login, create and publish the contract, create and publish the transform.", "validate": { "kind": "shell" } }
]
}
declarative-transform/input.json · 87 bytes · sha256 90a29afa7c31dcf9…{
"first_name": "Iulia",
"last_name": "Popescu",
"email": "[email protected]"
}
declarative-transform/publish.request.json · 3 bytes · sha256 ca3d163bab055381…{}
declarative-transform/transform.json · 531 bytes · sha256 aa969a3ce067413d…{
"language": "declarative-v1",
"output": {
"first_name": { "$copy": "/first_name" },
"middle_name": { "$copy_optional": "/middle_name" },
"display_name": {
"$concat": [
{ "$copy": "/first_name" },
{ "$literal": " " },
{ "$copy": "/last_name" }
]
},
"preferred_contact": {
"$coalesce": [
{ "$copy_optional": "/phone" },
{ "$copy_optional": "/email" },
{ "$literal": "none" }
]
},
"source": { "$literal": "docs-example" }
}
}
