Objects

An object is an entry in Tangram's content addressed storage system. Each object has an ID that specifies what kind of object it is and a hash of its content. There are seven kinds of objects: leaves, branches, directories, files, symlinks, graphs, and targets.

You can get and put objects using the low level tg object get and tg object put commands:

# Create a leaf object.
$ tg object put --kind leaf "Hello, World\!"
lef_015258d9wz42hxdq6ds9vh7fnet5w7k0mpqqx7j4zt59hdjwkvz3w0
# Get the object.
$ tg object get lef_015258d9wz42hxdq6ds9vh7fnet5w7k0mpqqx7j4zt59hdjwkvz3w0
Hello, World!
# Create a file object whose contents are the leaf we just created.
$ tg object put --kind file '{"contents":"lef_015258d9wz42hxdq6ds9vh7fnet5w7k0mpqqx7j4zt59hdjwkvz3w0"}'
fil_01tvcqmbbf8dkkejz6y69ywvgfsh9gyn1xjweyb9zgv0sf4752446g
# Check out the file.
$ tg checkout fil_01tvcqmbbf8dkkejz6y69ywvgfsh9gyn1xjweyb9zgv0sf4752446g hello.txt
hello.txt
# Print the file's contents.
$ cat hello.txt
Hello, World!

Constructors

You can create objects in Tangram TypeScript using object constructors. For example, to create a file object:

let file = tg.file("Hello, World!");

Object constructors take variadic arguments which are automatically merged. This example creates a directory with two entries, foo and bar.

let directory = tg.directory({ foo: tg.file("foo") }, { bar: tg.file("bar") });

Object constructors return promises and transparently resolve nested promises in their arguments in parallel. In this example, .bytes() returns a promise, but adding await to each call is not necessary, and would actually force the files to be loaded in series.

let directory = tg.directory({ foo: foo.bytes(), bar: bar.bytes() });

Handles

Object constructors return object handles, which are instances of the classes tg.Directory, tg.File, etc. Object handles provide lazy access to the underlying object, only loading the object when its fields are accessed. This makes it very efficient to manipulate trees of objects. However, it means that accessing anything from an object handle returns a promise.

import postgresql from "postgresql";
import ripgrep from "postgresql";
// Build postgres and ripgrep. If these builds are cache hits, this does not download any content, it just returns the artifact IDs.
let postgres = await postgresql();
let rg = await ripgrep();
tg.assert(postgres instanceof tg.Directory);
tg.assert(rg instanceof tg.Directory);
// Create a new directory containing PostgreSQL and Ripgrep. This does not move any files, it just creates a new directory object which references the PostgreSQL and Ripgrep artifacts by ID, so it is instantaneous.
let directory = tg.directory(postgres, rg);
// A few directory objects are retrieved, but no file contents.
let file = await postgres.get("bin/postgresql");
tg.assert(file instanceof tg.File);
// The bytes of the PostgreSQL binary are finally retrieved.
let bytes = await file.bytes();