Skip to content

notPersisted

Meta marker to exclude stores or fields from persistence.

Import

ts
import { notPersisted } from "storion/persist";

Store-Level Exclusion

Exclude an entire store from persistence:

ts
import { store } from "storion";
import { notPersisted } from "storion/persist";

const sessionStore = store({
  name: "session",
  state: {
    token: "",
    refreshToken: "",
    expiry: 0,
  },
  meta: notPersisted(), // Entire store excluded
  setup({ state }) {
    return {
      setTokens: (token: string, refreshToken: string, expiry: number) => {
        state.token = token;
        state.refreshToken = refreshToken;
        state.expiry = expiry;
      },
      clear: () => {
        state.token = "";
        state.refreshToken = "";
        state.expiry = 0;
      },
    };
  },
});

Field-Level Exclusion

Exclude specific fields from persistence:

ts
const userStore = store({
  name: 'user',
  state: {
    name: '',
    email: '',
    password: '',         // Sensitive - don't persist
    confirmPassword: '',  // Temporary - don't persist
    rememberMe: false,    // Will be persisted
  },
  meta: meta.of(
    notPersisted.for('password'),
    notPersisted.for('confirmPassword'),
  ),
  setup: /* ... */,
});

Multiple Fields

Exclude multiple fields with a single entry:

ts
const formStore = store({
  name: 'form',
  state: {
    username: '',
    password: '',
    confirmPassword: '',
    securityAnswer: '',
    savedData: {},
  },
  meta: notPersisted.for(['password', 'confirmPassword', 'securityAnswer']),
  setup: /* ... */,
});

How It Works

When persist processes a store:

  1. Store-level check: If notPersisted() is in meta, the entire store is skipped
  2. Field-level filtering: Fields marked with notPersisted.for() are excluded from:
    • dehydrate() - not saved to storage
    • hydrate() - not restored from storage

Example: Form with Validation

ts
const signupStore = store({
  name: "signup",
  state: {
    // Persist these (user convenience)
    email: "",
    username: "",
    agreeToTerms: false,

    // Don't persist (security/temporary)
    password: "",
    confirmPassword: "",
    validationErrors: {} as Record<string, string>,
    isSubmitting: false,
  },
  meta: notPersisted.for([
    "password",
    "confirmPassword",
    "validationErrors",
    "isSubmitting",
  ]),
  setup({ state, update }) {
    return {
      setField: (field: keyof typeof state, value: unknown) => {
        (state as any)[field] = value;
      },

      validate: () => {
        const errors: Record<string, string> = {};

        if (state.password.length < 8) {
          errors.password = "Password must be at least 8 characters";
        }
        if (state.password !== state.confirmPassword) {
          errors.confirmPassword = "Passwords do not match";
        }

        state.validationErrors = errors;
        return Object.keys(errors).length === 0;
      },

      submit: async () => {
        if (!this.validate()) return;

        state.isSubmitting = true;
        try {
          await api.signup({
            email: state.email,
            username: state.username,
            password: state.password,
          });
        } finally {
          state.isSubmitting = false;
        }
      },
    };
  },
});

Use Cases

Use CaseLevelExample
Session tokensStoremeta: notPersisted()
PasswordsFieldnotPersisted.for('password')
Confirmation inputsFieldnotPersisted.for('confirmPassword')
Validation stateFieldnotPersisted.for('errors')
Loading flagsFieldnotPersisted.for('isLoading')
Sensitive dataStore/FieldCredit cards, SSN, etc.
Derived/computedFieldCached calculations

Combining with filter

You can use both notPersisted and filter option:

ts
persist({
  // Only persist these stores
  filter: (ctx) => ['user', 'settings', 'cart'].includes(ctx.spec.displayName),

  handler: (ctx) => ({
    load: () => /* ... */,
    save: (state) => /* ... */,
  }),
})

// Plus per-store field exclusions via notPersisted.for()

See Also

Released under the MIT License.