Composition
Compose procs into custom behavior to support advanced use-cases.
Compositions define a chain of procs. When called, the result of each proc is passed as input to the next proc in the composition. The entire composition is evaluated in a single api call to proc, making compositions a performant option when building complex behaviors. Here's a simple composition that appends a hardcoded value to the given input and truncates the result to a maximum allowed length of 10 characters.
Setup
require "proc"
client = Proc.connect("PROCAUTH")
const Proc = require("@proc.dev/client");
const client = Proc.connect("PROCAUTH");
authorization=PROCAUTH
composition = client.type.string.truncate(
length: 3
) >> client.type.string.append(
value: "..."
)
composition.call("hello")
let composition = client.type.string.truncate(
undefined, {length: 3}
).compose(
client.type.string.append(
undefined, {value: "..."}
)
);
composition.call("hello");
curl "https://proc.run/core/exec" --silent \
--header "authorization: bearer $authorization" \
--header "content-type: application/vnd.proc+json" \
--header "accept: text/plain" \
--data '[["$$", "proc", ["{}", [">>", ["%%", "hello"]], ["()", "type.string.truncate", ["$$", "length", ["%%", 3]]], ["()", "type.string.append", ["$$", "value", ["%%", "..."]]]]]]'
hel...
The cURL example above shows what's happening behind the scenes in the client libraries: the composition api builds a
data structure representing the composition, then evaluates it with a call to core.exec
. You can think of
compositions like ephemeral programs that are constructed dynamically by the client and evaluated within proc.
Compositions can also be deployed as custom endpoints—learn more in the stored proc docs.
Passing Compositions as Values
Compositions can be passed as input or argument values to other proc calls. Building on the truncation example above, we
can turn the composition into a callable value, then pass it as input to keyv.set
to persist the truncated value in
the key-value store.
Setup
require "proc"
client = Proc.connect("PROCAUTH")
const Proc = require("@proc.dev/client");
const client = Proc.connect("PROCAUTH");
authorization=PROCAUTH
composition = client.type.string.truncate(
length: 3
) >> client.type.string.append(
value: "..."
)
client.keyv.set.call(
bucket: "zb2fbf41", value: composition
)
let composition = client.type.string.truncate(
undefined, {length: 3}
).compose(
client.type.string.append(
undefined, {value: "..."}
)
);
client.keyv.set.call(
undefined, zb2fbf41
);
curl "https://proc.run/keyv/set?bucket=zb2fbf41" --silent \
--header "authorization: bearer $authorization" \
--header "content-type: application/vnd.proc+json" \
--header "accept: text/plain" \
--data '[["$$", "value", ["{}", ["()", "type.string.truncate", ["$$", "length", ["%%", 3]]], ["()", "type.string.append", ["$$", "value", ["%%", "..."]]]]]]'
true
Using with
instead of call
builds a callable value that is evaluated within proc rather than on the client.
Stuck? Want to chat about an idea? Join the community on Discord.