On this page

Collections

Collections are models that represent database tables. To create a collection, add a file named [collection-name].ts to the collections directory of your project and export the defineCollection function as the default export.


Example

Here is an example of a products collection:

# collections/products.ts

import { defineCollection } from '#pruvious'

export default defineCollection({
  name: 'products',
  mode: 'multi',
  translatable: true,
  fields: {
    name: {
      type: 'text',
      options: {
        required: true,
      },
    },
    price: {
      type: 'number',
      options: {
        required: true,
        decimals: 2,
        min: 0,
      },
      additional: {
        translatable: false,
      },
    },
  },
})

There are two types of collections:

  • Single-entry collections: These collections work with only one record and are suitable for option pages, global variables, and similar purposes.

  • Multi-entry collections: These collections work with multiple records and are suitable for pages, users, products, and other similar entities.

Single-entry collections

Single-entry collections contain only one record. This collection mode is a suitable for website settings, where global values like menus are stored.

Here's an example of a settings collection:

# collections/settings.ts

import { defineCollection } from '#pruvious'

export default defineCollection({
  name: 'settings',
  mode: 'single',
  apiRoutes: { read: 'public' },
  dashboard: {
    fieldLayout: [
      {
        Header: ['headerMenu'],
        Footer: ['copyrightText', 'socialMedia'],
      },
    ],
  },
  fields: {
    headerMenu: {
      type: 'repeater',
      options: {
        addLabel: 'Add menu item',
        subfields: {
          link: { type: 'link', options: { required: true } },
          label: { type: 'text', options: { required: true } },
        },
        fieldLayout: [['link', 'label']],
      },
    },
    copyrightText: {
      type: 'text',
      options: {
        required: true,
      },
    },
    socialMedia: {
      type: 'repeater',
      options: {
        addLabel: 'Add social media link',
        subfields: {
          link: { type: 'link', options: { required: true } },
          icon: { type: 'icon', options: { required: true } },
        },
        fieldLayout: [['link', 'icon']],
      },
    },
  },
})

If the apiRoutes.read parameter is set to 'public', you can fetch the data from this collection using the getCollectionData utility function. Here's an example:

# components/Footer.vue

<template>
  <footer class="container">
    <div class="flex items-center justify-between gap-4 ph:flex-col">
      <p>{{ copyrightText }}</p>

      <ul class="flex gap-3">
        <li v-for="{ icon, link } of socialMedia">
          <NuxtLink :to="link" rel="noopener noreferrer nofollow" target="_blank" class="flex h-6 w-6">
            <PruviousIcon :icon="icon" class="m-auto h-3.5 w-3.5" />
          </NuxtLink>
        </li>
      </ul>
    </div>
  </footer>
</template>

<script lang="ts" setup>
import { getCollectionData } from '#pruvious/client'

const { copyrightText, socialMedia } = await getCollectionData('settings')
</script>

Single-entry collections are stored in the same database table, with each translation of a single collection stored in a separate row.

Multi-entry collections

Multi-entry collections have their own database table and columns, which enable them to store multiple records (rows). When defining multi-entry collections, they offer additional options compared to single-entry collections. These options include more CRUD API routes, field indexes, constraints, a content builder, and more.

An example of a multi-entry collection is shown at the top of this page.

Page-like collections

There are situations where you may need to segregate certain pages on your website, such as products, news, documentation, and similar content categories. These pages often have a slug prefix in the URL and their layout and allowed blocks may differ from the rest of the website. In such cases, it is helpful to have a separate collection, apart from the standard pages collection, where you can store your data. This offers several benefits, including isolating a database table from the rest of your pages, which simplifies data querying.

Pruvious provides a utility called pageLikeCollection that generates the same configuration as the default pages collection. This utility enables you to easily customize the definition to a certain extent. Here is an example of the products collection, which will be publicly accessible under the URL prefix shop.

# collections/products.ts

import { defineCollection } from '#pruvious'
import { pageLikeCollection } from '#pruvious/standard'

export default defineCollection(
  pageLikeCollection({
    name: 'products',
    pathPrefix: 'shop',
    allowedLayouts: ['product'],
    additionalFields: {
      name: {
        type: 'text',
        options: {
          required: true,
        },
      },
      price: {
        type: 'number',
        options: {
          required: true,
          decimals: 2,
          min: 0,
        },
        additional: {
          translatable: false,
        },
      },
    },
    additionalPublicPagesFields: ['name', 'price'],
  }),
)

Check out the pageLikeCollection function on GitHub to see what it's creating.

Definition

Here is an overview of all collection properties. Properties exclusive to multi-entry collections are marked with the M symbol, and required properties are marked with R.

PropertyDescription

name R

A unique collection name. The name should only consist of lowercase alphanumeric characters and hyphens. It must start with a letter, end with an alphanumeric character, and cannot have two consecutive hyphens. Examples of valid names are: products, news, form-entries, etc.

mode R

Specifies the mode of the collection entries (single or multi).

fields R

The fields used in the collection. Field names should follow camelCase formatting and must not exceed 60 characters in length.

createdAtField

The name of an automatically generated and read-only field that stores a timestamp indicating when a collection record was created. You can disable this field by setting its property to false.

updatedAtField

The name of an automatically generated and read-only field that stores a timestamp indicating when a collection record was last updated. You can disable this field by setting its property to false.

translatable

Specifies whether the collection supports translations.

label

Collection related labels shown in the dashboard. You can provide either an object or a plural lowercase string of the collection name. If not specified, labels will be auto-generated from the collection name.

apiRoutes

Determines the default API routes enabled for this collection.

dashboard

Dashboard related settings.

publicPages M

Determines whether the collection records are page-like and publicly accessible via the API.

contentBuilder M

Specifies if the block builder is enabled for this collection.

search M

Specifies searchable fields and their order for search queries.

compositeIndexes M

An array of composite indexes represented as arrays of collection field names.

uniqueCompositeIndexes M

An array of unique composite indexes represented as arrays of collection field names.

duplicate M

The function used for duplicating records.

mirrorTranslation M

The function used for mirroring record translations.

guards

Array of custom guards executed during collection record creation, reading, updating, or deletion via standard API routes.

cacheQueries

Specifies whether to cache SELECT database queries for this collection if their execution time exceeds the specified value in milliseconds.

clearCacheRules

Specifies whether to clear the cache when a record is created, updated, or deleted.

nonCachedFields

An array of fields that should not be cached due to their sensitive nature.

For more information, see the collection definition types on GitHub.

Guards

Guards are security layers that prevent unauthorized access to specific records. Here's an example of a collection guard:

# collections/protected.ts

import { defineCollection, hasCapability } from '#pruvious'

export default defineCollection({
  name: 'protected',
  mode: 'single',
  guards: [
    ({ user }) => {
      if (!hasCapability(user, 'custom-capability')) {
        throw new Error('Access denied')
      }
    },
  ],
  fields: {
    // ...
  },
})

The guards are executed in the given order and can be assigned for specific CRUD operations. Pruvious also provides field guards that can be added in the field definition.

Default fields

Collections include the following automatically generated fields:

  • id - The unique identifier of the record.

  • translations - An automatically generated unique identifier that groups multi-entry collection records as translations of each other. When populated, this field resolves to a key-value object. The key represents he language code, and the value is the corresponding record's ID or null if no record in this language exists.

  • language - The language code associated with this collection record. If not provided, the code of the primary language will be used. Learn more about translations here.

  • createdAt - Timestamp indicating when the record was created.

  • updatedAt - Timestamp indicating when the record was last updated.

Last updated on January 6, 2024 at 12:44