Streams

Introduction

The Streams platform leans heavily on domain-driven design (DDD). We call these domain abstractions streams, hence our namesake.

An example could be configuring a domain model (a stream) for a website's pages, users of an application, or feedback submissions from a form.

Defining Streams

You can define stream configurations in the streams/ directory using JSON files. The filenames serve as a handle, which you can use to reference the stream later.

It is highly encouraged to use the plural form of a noun when naming Streams—for example, contacts and people. You may also use naming conventions like business_contacts or neat-people.

The Basics

To get started, you need only specify the handle, which is the filename itself, and some fields to describe the domain object's structure.

Let's create a little stream to hold information for a simple CRM.

// streams/contacts.json
{
    "name": "Contacts",
    "source": {
        "type": "filebase",
        "filename": "streams/data/contacts",
        "format": "json"
    },
    "config": {
        "prototype": "Streams\\Core\\Entry\\Entry",
        "collection": "Illuminate\\Support\\Collection"
    },
    "fields": {
        "name": "string",
        "email": "email",
        "company": {
            "type": "relationship",
            "config": {
                "related": "companies"
            }
        }
    }
}

Fields

Fields are an essential descriptor of the domain object. They describe what properties the domain object will have available and how the property data works. Things like accessors, data mutation, and casting can be controlled by the field's type.

The fieldsconfiguration keys serve as a handle, which you can use to reference the field later. For example, the above contact fields can be accessed later like this:

$entry->email;              // The email value.
$entry->company->email;     // The related company's email value.

Stream Routes

Streams can streamline routing by defining routes in their configuration.

// streams/contacts.json
{
    "routes": {
        "index": "contacts",
        "view": "contacts/{id}"
    }
}

You can also use an array to include other route options.

// streams/contacts.json
{
    "routes": {
        "contact": {
            "csrf": false,
            "uri": "form/{entry.email}"
        }
    }
}

Stream Validation

Streams simplify validation by defining validation in their configuration.

// streams/contacts.json
{
    "rules": {
        "name": [
            "required",
            "max:100"
        ],
        "email": [
            "required",
            "email:rfc,dns"
        ],
        "company": "required|unique"
    }
}

Caching

Streams provides a touch-free caching system you can define in the configuration.

// streams/contacts.json
{
    "cache": false,
    "ttl": 1800 // 30 minutes
}

Sources

Sources define the source information for entry data which you can define in the configuration.

// streams/contacts.json
{
    "source": {
        "type": "filebase",
        "format": "md",
        "prototype": "Streams\\Core\\Entry\\Entry"
    }
}

Stream Entries

Domain entities are called entries within the Streams platform. A stream defines entry attributes, or fields, that dictate the entry's properties, data-casting, and more.

Advanced Streams

JSON References

You can use JSON file references within stream configurations to point to other JSON files using the @ symbol followed by a relative path to the file. In this way, you can reuse various configuration information or tidy up larger files. The referenced file's JSON data directly replaces the reference.

// streams/contacts.json
{
    "name": "Contacts",
    "fields": "@streams/fields/contacts.json"
}
// streams/fields/contacts.json
{
    "name": "string",
    "email": "email",
    "company": {
        "type": "relationship",
        "stream": "company"
    }
}

Extend a Stream

A stream can extend another stream, which works like a recursive merge.

// streams/family.json
{
    "name": "Family Members",
    "extend": "contacts",
    "fields": {
        "relation": {
            "type": "selection",
            "config": {
                "options": {
                    "mother": "Mother",
                    "father": "Father",
                    "brother": "Brother",
                    "sister": "Sister"
                }
            }
        }
    }
}

In the above example, all contacts fields are available to you, as well as the new relation field.

$entry->email;      // The email value.
$entry->relation;   // The relation value.

Stream Sources

You can configure the flat-file database as well as other sources for storing data including any Laravel database. No code changes required.