Introduction
Documentation of the Projection service schema definition.
A projection can be defined by a GraphQL schema:
type User
@upsertOn(
on: { topic: "myApp", eventTypes: ["createUser", "updateUser"] }
identifyBy: { payload: ["id"] }
)
@removeOn(
on: { topic: "myApp", eventTypes: ["removeUser"] }
identifyBy: { payload: ["id"] }
) {
name: String!
}
The name of the projection equals the name of the type in the schema. The name will be part of the corresponding queries and subscriptions in the GraphQL API, too.
Views
A view is a projection that is based on one or more other projections. Views can be used for advanced reporting tasks that need to aggregate a lot of data.
A view can be defined by a GraphQL schema and a SQL file:
type UserStatistics @view(sqlFile: "./userStatistics.sql") {
name: String! @index
numberOfUsers: Int!
}
The name of the view equals the name of the type in the schema. The name will be part of the corresponding queries and subscriptions in the GraphQL API, too.
SELECT name AS name, COUNT(1) AS numberOfUsers FROM user GROUP BY name
For more information about how to define a view please refer to the documentation of the @view
directive.
Base Views
Base views can be used in views to reuse the same base view for multiple views. They work the same as views.
For more information about how to define a base view please refer to the documentation of the @baseView
directive.
Object Directives
The following directives can be applied to the whole projection:
Directive | Description |
---|---|
@dangerouslyUpsertOn | Upsert data from several topics into the same projection |
@dangerouslyRemoveOn | Remove data from several topics from the same projection |
@expires | Automatically remove data after expiration |
@filterByJwtData | Filter data based on a field in the JWT |
@global | Projections over all tenants |
@permission | Restrict access permissions on the projection |
@removeOn | Remove projection data |
@unique | Unique constraints on multiple fields |
@upsertOn | Create or update projection data |
@view | A view can be used to calculate complex reports |
@webhook | Use webhooks if you need complex logic to generate projection data |
Fields
Supported field types:
- String
- ID
- Boolean
- Int
- Float
- DateTime (unix timestamp, milliseconds)
- Enums
- Objects / references to other projections or CRUD types
- Arrays of all types listed above
- All types listed above in their required form
[EventEnvelope!]!
Event Envelope
The field type [EventEnvelope!]!
is a special field type that can only be used in this form at
the root level of a projection (not in a nested object). It will automatically aggregate all
events that are applied on the projection entry into an array. Use the type in conjunction with
the @aggregateEvents
directive. This is very useful for debugging.
Every projection will automatically get three fields:
Field | Type | Description |
---|---|---|
id | ID! | The identifier of the projection |
createdAt | DateTime! | The creation time of the entry |
changedAt | DateTime! | The time of the last change of the entry |
By default the value of a field equals the value of the event payload field that has the exact same name.
Required fields are marked by an !
, e.g. String!
.
Fields with the !
flag will default to their zero value (""
for strings, 0
for numbers, false
for booleans, []
for arrays).
Field Directives
By default the value of a field equals the value of the event payload field that has the exact same name. This behavior can be changed by using directives on a field level:
Directive | Description |
---|---|
@aggregateEvents | Aggregate all events that changed the entry |
@changedAt | Reflects the last change time of the entry |
@createdAt | Reflects the creation time of the entry |
@changedBy | Reflects the user that has last changed the entry |
@createdBy | Reflects the user that has created the entry |
@default | Set a default value |
@fromJwtData | Fill a field with data from the JWT |
@from | Set the value of a field by an expression |
@gdpr | Apply GDPR logic on a field |
@identifier | Fill a field by the id of the projection entry |
@immutable | Mark a field as immutable |
@index | Make a field filterable ans sortable |
@permission | Restrict access permissions on the field |
@projectedAt | Reflects the projection time of the entry |
@safeHtml | Sanitize html strings |
@sequence | Automated sequence generator |
@unique | Make a field unique |
@validate | Validate field data |
@webhook | Execute complex calculations in a webhook |
Debugging
Use the [EventEnvelope!]!
field type at the root level of your projection to aggregate all events that are applied to a projection entry.
type User @upsertOn(...) {
name: String!
events: [EventEnvelope!]! @aggregateEvents
}