GUIDE 14 / 28 · NATIVE 2.0.7

Settings & validation

Read settings reliably, normalize values, persist small configuration and handle schema UI limitations.

Schema defaults and runtime values#

The schema describes labels, input types, options and descriptions. Runtime getConfig returns the config object; it does not merge schema.default values. The example manifests therefore include actual initial config values. Also implement fallback values in code so an older manifest still works.

Boolean and select controls use defaults for display when a value is absent. String/number/textarea types use text inputs and may show defaults as placeholders. A displayed placeholder is not a saved runtime value.

Normalize before use#

JavaScript
function readSettings(context) {
  const raw = context.getConfig();
  const number = Number(raw.minimumSeconds ?? 10);
  return {
    minimumSeconds: Number.isFinite(number) ? Math.max(0, Math.min(600, number)) : 10,
    enabled: raw.enabled === true,
    mode: ['quiet', 'notify'].includes(raw.mode) ? raw.mode : 'quiet'
  };
}

Do not use truthiness for a string boolean: the string 'false' is truthy. Use strict boolean checks for values from checkbox fields, and reject unsupported modes. Validate action payloads independently of the settings form.

Save and migrate configuration#

saveConfig performs a shallow merge. Saving one field keeps other top-level fields, while saving a nested object replaces that entire nested value. Manifest storage is synchronous and intended for small state/configuration, not per-frame counters or large datasets.

JavaScript
const config = context.getConfig();
if (config.settingsVersion !== 1) {
  context.saveConfig({
    minimumSeconds: Number(config.minimumSeconds ?? 10),
    settingsVersion: 1
  });
}

Use a version field for one-time migrations, preserve user choices and check native.log when writes fail. The API does not return a storage-success acknowledgement from saveConfig.

Masked fields and packaging#

Password inputs hide the value while the form is visible. Values are still stored in plugin.json as plain text. Keep credentials out of logs, tab HTML, screenshots and shared plugin archives. Distribute empty endpoint/token fields and require explicit setup.

Configuration saves update the manifest visible to the manager. Your code should read getConfig at the time of an action rather than caching old values forever. See Packaging & compatibility for release preparation.

Implementation reference: PluginManager.tsx; src/main/plugins/PluginManager.ts · native 2.0.7.