createEntity
is used to create a new entity. An optional id
can be used to create an entity with a specific id. You can also publish the entity, in one atomic operation, by providing { publish: true }
to the options.
interface DossierClient {
createEntity(
entity: EntityCreate<Entity>,
options?: EntityMutationOptions,
): PromiseResult<
EntityCreatePayload,
"BadRequest" | "Conflict" | "NotAuthorized" | "Generic"
>;
}
interface EntityCreate {
id?: string;
info: {
type: string;
name?: string;
version?: 1;
authKey?: string | null;
};
fields: Record<string, unknown>;
}
interface EntityMutationOptions {
publish?: boolean;
}
interface EntityCreatePayload {
effect: 'created' | 'createdAndPublished' | 'none';
entity: Entity;
}
Creating an entity generates a createEntity
or createAndPublishEntity
event.
This example shows how to create an entity of the type Message
, which is an entity type we create as part of the initialization at the bottom of this page. When you run the example you'll see that the full created entity is returned. The effect
will be "created"
.
const result = await client.createEntity({
info: { type: "Message" },
fields: { text: "Hello" },
});
console.log(result.isOk() ? JSON.stringify(result.value, null, 2) : result);
This example shows how to publish the entity at the same time as creating it. If the publishing fails, the creation will also fail – i.e. it's an atomic action. To show that the entity is published we fetch it with the Published Dossier Client.
const result = await client.createEntity(
{ info: { type: "Message" }, fields: { text: "Hello" } },
{ publish: true },
);
if (result.isOk()) {
const id = result.value.entity.id;
console.log(`Entity created: ${id} (effect: ${result.value.effect})`);
const publishedResult = await publishedClient.getEntity({ id });
console.log(
publishedResult.isOk()
? JSON.stringify(publishedResult.value, null, 2)
: publishedResult,
);
} else {
console.error(result.error, result.message);
}
This example shows how to create an entity with a specific id. Here we use a random UUIDv4 id (but other UUIDs can be used as well). One use case can be if you're migrating content from another system. Another is if you want to handle if the connection to Dossier is unreliable in order to check if the entity was successfully created even if you never get the response.
const id = crypto.randomUUID();
const createEntity = {
id,
info: { type: "Message" },
fields: { text: "Hello" },
};
const result = await client.createEntity(createEntity);
console.log(
result.isOk()
? `Created with id: ${result.value.entity.id} (effect: ${result.value.effect})`
: result,
);
// Pretend we didn't get the result and try again
const retryResult = await client.createEntity(createEntity);
console.log(
retryResult.isOk()
? `Created with id: ${retryResult.value.entity.id} (effect: ${retryResult.value.effect})`
: retryResult,
);
This example shows how to use the Dossier Exception Client to make the API call.
The normal Dossier Client returns a PromiseResult
for all operations. Even if the API call fails, no exceptions are thrown. The benefit is that you are forced to handle errors for all calls and TypeScript helps you in knowing which errors can occur. However, sometimes it can be easier to use exceptions.
const exceptionClient = client.toExceptionClient();
const { entity } = await exceptionClient.createEntity({
info: { type: "Message" },
fields: { text: "Hello" },
});
console.log(`Created entity: ${entity.id}`);
try {
await exceptionClient.createEntity({
info: { type: "MissingEntityType" },
fields: {},
});
} catch (error) {
console.error("Failed to create entity:", error);
}
This example shows the sync event that is generated when creating an entity. Sync events can be used to create a complete copy of a Dossier, by replaying the sync events.
// Get sync events before creating the entity, to get the id of the last event
const syncEventsBefore = (
await server.getSyncEvents({ after: null, limit: 10 })
).valueOrThrow();
const lastSyncEvent = syncEventsBefore.events.at(-1);
// Create an entity
const result = await client.createEntity({
info: { type: "Message" },
fields: { text: "Hello" },
});
result.throwIfError();
// Get sync events after creating the entity
const syncEventsAfter = (
await server.getSyncEvents({ after: lastSyncEvent.id, limit: 10 })
).valueOrThrow();
console.log("Sync events:");
console.log(JSON.stringify(syncEventsAfter.events, null, 2));
This code used to set up Dossier for the examples on this page. The examples are run entirely in the browser.
const dossierCore = await import("https://esm.sh/@dossierhq/core@0.7.6");
const dossierServer = await import("https://esm.sh/@dossierhq/server@0.7.6");
const dossierSqlJs = await import("https://esm.sh/@dossierhq/sql.js@0.7.6");
const { default: initSqlJs } = await import("https://esm.sh/sql.js@1.10.3");
const logger = dossierCore.NoOpLogger;
const SQL = await initSqlJs({
locateFile: (file) => `https://sql.js.org/dist/${file}`,
});
const database = new SQL.Database();
const databaseAdapterResult = await dossierSqlJs.createSqlJsAdapter(
{ logger },
database,
{
migrate: true,
fts: { version: "fts4" },
journalMode: "memory",
},
);
const databaseAdapter = databaseAdapterResult.valueOrThrow();
const serverResult = await dossierServer.createServer({ databaseAdapter });
const server = serverResult.valueOrThrow();
const sessionResult = await server.createSession({
provider: "sys",
identifier: "user",
});
const session = sessionResult.valueOrThrow();
const client = server.createDossierClient(session.context);
const publishedClient = server.createPublishedDossierClient(session.context);
const schemaResult = await client.updateSchemaSpecification({
entityTypes: [
{
name: "Message",
nameField: "text",
fields: [{ name: "text", type: "String" }],
},
],
});
schemaResult.throwIfError();