1.4.0 • Published 8 months ago

nuxt-cereal v1.4.0

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

nuxt-cereal

🥣 Cereal-ize JSON data into literally-typed constants, enums, & options in Nuxt.

 Release Notes

Configuration

  1. Install the module
pnpm add nuxt-cereal
  1. Create a config
// ~/cereal.config.ts
import { defineCerealConfig } from "nuxt-cereal/config";

export default defineCerealConfig({
  constants: {
    foo: "an example string",
  },
  enums: {
    bar: ["primary", "secondary", "tertiary"],
  },
  options: {
    baz: [
      { key: 1, label: "One" },
      { key: 2, label: "Two" },
    ],
  },
});
  1. Activate the module
// ~/nuxt.config.ts
import cereal from "./cereal.config";

export default defineNuxtConfig({
  modules: ["nuxt-cereal"],
  cereal,
});
  1. Eat some cereal, you are done!

Features

Define a JSON config object for:

  • constants A key/value collection of static strings & numbers
  • enums A key/value collection of static string arrays & number arrays
  • options A key/value collection of static option arrays w/ key & label properties

The config object is "cereal-ized" into read-only literals & implemented in Nuxt using a set of utility types/composables.

Types

Type templates are created using the JSON definitions & are automatically available in composables/components:

TypeDescription
ConstantString-literal keys of the constants cereal config
ConstantValue<C extends Constant>Literal value of the provided constants config key
EnumString-literal keys of the enums cereal config
EnumValue<E extends Enum>Literal values of the provided enums config key
EnumValueItem<E extends Enum>Template values of the provided enums config key
OptionString-literal keys of the options cereal config
OptionValue<O extends Option>Literal values of the provided options config key
OptionValueItem<O extends Option>Template values of the provided options config key

Example

These utility types can be useful when creating components. Let's say we have a button component that has a variant property that can be set to either filled, outlined, or plain. We can configure that option as an enum and use the helper types to define our component properties:

// ~/cereal.config.ts
export default defineCerealConfig({
  enums: {
    buttonVariant: ["filled", "outlined", "plain"],
  },
});
<script setup lang="ts">
// ~/components/Button.vue
defineProps<{
  variant: EnumValue<"buttonVariant">; // a string-literal type of the options in our config
}>();
</script>

<template>
  <button :data-variant="variant">
    <slot />
  </button>
</template>

Functions

Type-safe utility functions that enable access to the configuration literal values are automatically imported in any component/composable:

FunctionDescription
isConstant(key)Check if a provided string is a constants key & cast to Constant if valid
useConstant(key)Grab the literal value represented by the provided constants key
useConstantsConfig()Grab the entire constants configuration as an object literal
useConstantsKeys()Grab an array ofavailable constants configuration keys
isEnum(key)Check if a provided string is a enums key & cast to Enum if valid
useEnum(key)Grab the literal value represented by the provided enums key
useEnumsConfig()Grab the entire enums configuration as an object literal
useEnumsKeys()Grab an array ofavailable enums configuration keys
isOption(key)Check if a provided string is a options key & cast to Option if valid
useOption(key)Grab the literal value represented by the provided options key
useOptionsConfig()Grab the entire options configuration as an object literal
useOptionsKeys()Grab an array ofavailable options configuration keys

Example

These functions can be leveraged w/ generics to extend the power of our components even further. Imagine we have a pre-defined set of dropdowns needed for a form. We can quickly build a component that uses our cereal-ized data to provide a type-safe selector that only needs a key to get started:

// ~/cereal.config.ts
export default defineCerealConfig({
  options: {
    breakfast: [
      { key: "cereal", label: "Cereal" },
      { key: "pancakes", label: "Pancakes" },
      { key: "eggs", label: "Eggs" },
    ],
    lunch: [
      { key: "sandwhich", label: "Sandwhich" },
      { key: "soup", label: "Soup" },
      { key: "salad", label: "Salad" },
    ],
    dinner: [
      { key: "steak", label: "Steak" },
      { key: "lobster", label: "Lobster" },
      { key: "risotto", label: "Risotto" },
    ],
  },
});
<script setup lang="ts" generic="O extends Option">
// ~/components/Select.vue
const props = defineProps<{
  option: O; // "breakfast" | "lunch" | "dinner"
  modelValue?: OptionValueItem<O>["key"]; // if "breakfast" is the option, allowed values are "cereal" | "pancakes" | "eggs"
}>();

const emits = defineEmits<{
  "update:modelValue": [OptionValueItem<O>];
}>();

const options = useOption(props.option);
const modelValue = useVModel(props, "modelValue", emits, { passive: true }); // https://vueuse.org/core/useVModel/#usevmodel
</script>

<template>
  <select v-model="modelValue">
    <option v-for="o in options" :key="o.key" :value="o.key">
      {{ o.label }}
    </option>
  </select>
</template>

Server

The server does not have the access to the rich literal types we have in the frontend, but we can still use cereal-ized data within the server context:

FunctionDescription
useConstant(key)Access the value of a given constant key, evaluates to string | number.
useEnum(key)Access the value of a given enum key, evaluates to string[] | number.
useOptions(key)Access the value of a given options key, evaluates to { key: string | number; value: string}[].

License

MIT License © 2024-PRESENT Alexander Thorwaldson

1.4.0

8 months ago

1.3.9

9 months ago

1.3.8

9 months ago

1.3.7

9 months ago

1.3.6

9 months ago

1.3.5

9 months ago

1.3.4

9 months ago

1.3.3

9 months ago

1.3.2

9 months ago

1.3.1

9 months ago

1.3.0

9 months ago

1.1.0

9 months ago