Ask deeper questions with `exists`
TLDR
We add a new `exists` helper for building relational filters, Vue bindings and new storage options for the Triplit server.
exists
helper for queries with relational filters
You can now use an exists
method to help build subqueries that reference your schema.
import { Schema as S, exists } from '@triplit/client';
const schema = {
todos: {
schema: S.Schema({
id: S.Id(),
text: S.String(),
assignee_ids: S.Set(S.String()),
assignees: S.RelationMany('users', {
where: ['id', 'in', '$assignee_ids'],
}),
}),
},
users: {
schema: S.Schema({
id: S.Id(),
name: S.String(),
team: S.String(),
title: S.String(),
}),
},
};
// Todos where at least one assignee is on the engineering team
// and has the title of manager
const query = client.query('todos').where(
exists('assignees', {
where: [
['team', '=', 'engineering'],
['title', '=', 'manager'],
],
})
);
You may be tempted to write the query above as:
const query = client
.where('assignees.team', '=', 'engineering')
.where('assignees.title', '=', 'manager');
However, this will instead query for todos where at least one assignee is on the engineering team and where at least one assignee has the title of manager.
Vue support
Thanks to the contribution of Mo, Triplit now has Vue.js bindings. You can now use useQuery
and useConnectionStatus
in your Vue components by adding @triplit/vue
. We plan on adding a Vue template for create-triplit-app
in the coming weeks.
<script setup lang="ts">
import Todo from './components/Todo.vue';
import { schema } from '../triplit/schema';
import { useQuery, useConnectionStatus } from '@triplit/vue';
import { computed } from 'vue';
import { client } from './triplit';
const { fetching, results, error } = useQuery(client, client.query('todos'));
const { connectionStatus } = useConnectionStatus(client);
const todos = computed(() =>
results.value ? [...results.value.values()] : []
);
</script>
<template>
<div>
<div class="title">
<h1>Todos</h1>
<span v-if="connectionStatus === 'OPEN'">🟢</span>
<span v-else-if="connectionStatus === 'CLOSED'">🔴</span>
<span v-else>🟡</span>
</div>
<span v-if="fetching">Loading...</span>
<span v-else-if="error">Error: {{ error.message }}</span>
<ul v-else>
<Todo
v-for="todo in todos"
:key="todo.id"
:id="todo.id"
:text="todo.text"
:completed="todo.completed"
/>
</ul>
</div>
</template>
LMBD, LevelDB and file storage options for local developments and custom servers
We've added more storage providers for Triplit servers. You can now use LMBD, LevelDB and file storage for your local development server or custom server.
For instance:
npx triplit dev -s lmdb
Will start a local development server with LMBD storage. Read the CLI docs to see all of the available storage options for triplit dev
.
You can also use these storage providers if you're building a custom, self-hosted Triplit server. Read the server docs to see how to configure storage providers for your server.
Safer schema updates in the console
You've always been able to make changes to your schema with the Triplit console, including adding, removing and updating collections and attributes. Triplit has a validation process for schema changes, that is documented here. Now, those same restrictions are enforced in the console. If you try to make a change that would break existing data, you'll see a warning and the change will not be applied.
When you're done making changes in the console, you can expect your server schema to be "ahead" of your client schema. To update your client schema, we recommend running
npx triplit schema print > triplit/schema.ts
Which will update your local schema file with the latest schema from your server.
New docs for self-hosting with Triplit Cloud
Connecting a self-hosted machine to Triplit Cloud enables you to use the Triplit Console to view and manage your data, and to use the Triplit Dashboard to update your server's configuration without needing to redeploy it. Read the newly streamlined self-hosted deployments guide to get up and running in no time.
Simple catch-all filters for easier rules
Triplit where
filters now support simple boolean arguments. For example, you can now write
const schema = {
announcements: {
schema: S.Schema({
id: S.Id(),
title: S.String(),
body: S.String(),
}),
rules: {
read: { anyoneCanRead: { filter: [true] } },
// No one can write to announcements, but service role tokens ignore rules
write: { onlyServiceRolesCanWrite: { filter: [false] } },
},
},
};
Check back soon for a blog post on our redesigned rules and permissions system.