# Vocabularies and textures

> Use the recommended and closed vocabularies that @welldot/core publishes as data, show English and Portuguese labels, type open fields with OpenVocab, and look up FGDC textures.

The spec recommends a list of values for most string fields and fixes the list for a few ([Vocabularies](/format/concepts/vocabularies)). `@welldot/core` publishes every list as data, with labels keyed by language, so forms, tables and reports can show readable names without keeping their own translations.

## Vocabulary entries

Each vocabulary is an array of entries:

```ts
import { WELL_TYPES } from '@welldot/core';

WELL_TYPES[0];
// { value: 'tubular', label: { en: 'Tubular', pt: 'Tubular' } }
```

An entry has a `value` (what the file stores), a `label` with at least `en` and `pt`, and `deprecated: true` when the spec deprecates the value (`artesian` in `WELL_TYPES`).

## Labels

```ts
import {
  CONSTRUCTION_MATERIALS,
  PERMIT_TYPES,
  getVocabLabel,
} from '@welldot/core';

getVocabLabel(PERMIT_TYPES, 'abstraction_permit', 'pt'); // 'Outorga de direito de uso'
getVocabLabel(CONSTRUCTION_MATERIALS, 'stainless_steel', 'pt-BR'); // 'Aço inox'
getVocabLabel(CONSTRUCTION_MATERIALS, 'Aço galvanizado DIN 2440', 'pt'); // returned as is
```

`getVocabLabel(vocab, value, locale)` falls back from `pt-BR` to `pt` to `en`. A value that is not in the list, such as free text or an `x-` value, is returned unchanged, which is exactly what the spec asks a tool to display ([recommended vocabularies](/format/spec/v2/format-reference#recommended-vocabularies)).

Other helpers:

| Helper                                   | Use                                                                                                                      |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `vocabValues(vocab)`                     | The recommended values, for a select list. Deprecated values are left out unless you pass `{ includeDeprecated: true }`. |
| `getVocabEntry(vocab, value)`            | The entry of a value, or `undefined`.                                                                                    |
| `isVocabValue(vocab, value)`             | Whether a value is recommended (a type guard).                                                                           |
| `formatVocabList(vocab, values, locale)` | Comma-separated labels of a multi-valued field, such as `well_purpose`.                                                  |
| `resolveLanguageText(text, locale)`      | Resolves any `{ en, pt, … }` label object with the same fallback.                                                        |

```ts
import {
  WELL_PURPOSES,
  formatVocabList,
  vocabValues,
  WELL_TYPES,
} from '@welldot/core';

vocabValues(WELL_TYPES); // ['tubular', 'hand_dug', 'horizontal', 'infiltration_gallery']
formatVocabList(
  WELL_PURPOSES,
  ['production', 'monitoring', 'x-irrigation'],
  'en',
);
// 'Production, Monitoring well, x-irrigation'
```

## Typing open fields

Open fields are typed with `OpenVocab<T>`, which is `T | (string & {})`: editors autocomplete the recommended values while any string still type-checks.

```ts
import type { OpenVocab, PermitType } from '@welldot/core';

const a: OpenVocab<PermitType> = 'abstraction_permit'; // suggested
const b: OpenVocab<PermitType> = 'x-special'; // also fine
```

## The vocabularies

| Vocabulary                                                                     | Field                                                                                               |
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
| `WELL_TYPES`                                                                   | `well_type`                                                                                         |
| `WELL_PURPOSES`                                                                | `well_purpose[]`                                                                                    |
| `DRILLING_METHODS`                                                             | `bore_hole[].drilling_method`                                                                       |
| `CONSTRUCTION_MATERIALS`                                                       | `well_case[].type`, `well_screen[].type`, `reduction[].type`, `pump_installations[].riser_material` |
| `SCREEN_SLOT_TYPES`                                                            | `well_screen[].slot_type`                                                                           |
| `CENTRALIZER_TYPES`                                                            | `centralizers[].type`                                                                               |
| `CEMENT_PAD_TYPES`                                                             | `cement_pad.type`                                                                                   |
| `HYDRODYNAMIC_EVENT_TYPES`, `MEASUREMENT_METHODS`                              | `hydrodynamic_events[].type`, `.measurement_method`                                                 |
| `AQUIFER_ANALYSIS_METHODS`                                                     | `aquifer_analysis[].method`                                                                         |
| `HISTORY_LOG_CATEGORIES`, `HISTORY_LOG_SEVERITIES`, `MAINTENANCE_TYPES`        | `history_logs[]` fields                                                                             |
| `PUMP_TYPES`, `POWER_SOURCES`                                                  | `pump_installations[]` fields                                                                       |
| `PERMIT_TYPES`, `WATER_USES`, `CONDITION_CATEGORIES`, `PERMIT_HISTORY_TYPES`   | `permits[]` fields                                                                                  |
| `METER_TYPES`, `READING_SOURCES`, `ESTIMATION_METHODS`                         | `meters[]`, `production[]` fields                                                                   |
| `DOCUMENT_TYPES`                                                               | `attachments[].document_type`                                                                       |
| `SAMPLE_TYPES`, `SAMPLING_METHODS`, `SAMPLING_POINT_TYPES`, `SAMPLING_DEVICES` | `water_samples[]` fields                                                                            |

Closed vocabularies ship in the same shape, so `getVocabLabel` labels them too: `WELL_STATUSES` (`history_logs[].status`), `PERMIT_ADMINISTRATIVE_STATUSES`, `VOLUME_LIMIT_PERIODS`, `PRODUCTION_ENTRY_TYPES`, `RESULT_QUALIFIERS`, `VALIDATION_STATUSES`, `BAROMETRIC_COMPENSATIONS`, `READING_AGGREGATIONS` and others. Each one is checked against its TypeScript type at compile time, so it cannot drift from the schema.

The `@welldot/core` test suite compares every list with the tables in the spec. Each constant has a page in the [API reference](/core/api).

## FGDC textures

`FGDC_TEXTURES_OPTIONS` lists the FGDC lithology patterns (FGDC-STD-013-2006) as `{ code, label }`. Use it to look up a code or build a picker for `lithology[].texture`:

```ts
import { FGDC_TEXTURES_OPTIONS } from '@welldot/core';

FGDC_TEXTURES_OPTIONS.find(t => t.code === 607);
// { code: 607, label: 'Massive sand or sandstone' }

const options = FGDC_TEXTURES_OPTIONS.map(t => ({
  value: t.code,
  label: t.label,
}));
```

Codes are grouped by series: 100 surficial, 200 sedimentary, 300 igneous, 400 miscellaneous and metamorphic, 500 glacial and periglacial, 600 sedimentary lithology, 700 metamorphic and igneous lithology. The 600 and 700 series are the ones with drawn patterns and the most useful for well logs; the [FGDC texture reference](/format/spec/reference/fgdc-textures) marks which codes are available. [`@welldot/render`](/render) draws these patterns.
