# Changing base schema

Learn how to create fields, update field options, and create tables from your
custom extension.

## Overview

The Blocks SDK provides the ability to [read data from](https://airtable.com/developers/extensions/guides/read-data-from-airtable.md)
and [write data to](https://airtable.com/developers/extensions/guides/write-back-to-airtable.md) your base. This guide will
showcase how you can use the SDK to also modify your base's underlying schema.
This refers to what tables exist in the base, what fields make up those tables,
and how those fields are configured.

The methods outlined below will allow you to programmatically create tables,
create fields, and update field options, all from your custom extension. These
tools are especially helpful if your extension requires a specific base schema.
For example, a task tracking extension might rely on a date field to function
properly. Rather than requiring the user to manually configure tables and fields
accordingly, your extension can do it for them.

## Create new fields

You can create a new field on an existing table using the [`Table.createFieldAsync`](https://airtable.com/developers/extensions/api/models/table.md#createFieldAsync)
method. This method allows you to specify the field name, type, and options (if
any). For example, this could be used to automatically create a "Status" field
in a specified table, with options for "Not started", "In progress", and "Done":

```js
import {FieldType} from '@airtable/blocks/models';
import {colors} from '@airtable/blocks/ui';

const newField = await table.createFieldAsync('Status', FieldType.SINGLE_SELECT, {
    choices: [
        {name: 'Not started', color: colors.RED_LIGHT_1},
        {name: 'In progress', color: colors.YELLOW_LIGHT_1},
        {name: 'Done', color: colors.GREEN_LIGHT_1},
    ],
});
```

Creating & updating fields via the SDK is currently supported for most field
types. Linked record fields and computed fields such as formulas, lookups, and
rollups are not currently supported. Reference the [`FieldType`](https://airtable.com/developers/extensions/api/fieldtype.md)
documentation for a detailed list of supported fields & expected formats.

## Update existing fields

You can update the configuration of an existing field using [`Field.updateOptionsAsync`](https://airtable.com/developers/extensions/api/models/field.md#updateOptionsAsync). This lets you
modify `field.options`, which represents the configuration of a field (for
instance, the choices of a single select field, or the precision of a number
field). The options format varies by field type, and not all field types have
configurable options. You can find the expected options format for each field
type on the [`FieldType`](https://airtable.com/developers/extensions/api/fieldtype.md) documentation page—look for "Field
options [write] format" under the appropriate field.

At this time, changing the field type is not supported. Additionally, the
current API for updating options on a single or multiple select field only
supports creating new options—existing options cannot be deleted.

## Create new tables

You can use the [`Base.createTableAsync`](https://airtable.com/developers/extensions/api/models/base.md#createTableAsync)
method to create a new table, and define the initial set of fields for that
table. The first field in the list will become the primary field for your
table. Just like the main Airtable UI, only some field types can be the primary
field for a table—refer to this [support article](https://support.airtable.com/docs/the-primary-field)
for more details.

As an example, this method could be used to create a "Tasks" table with the
following 4 fields:
- Name (text field, primary)
- Due date (date field)
- Assignee (collaborator field)
- Status (single select field)

```js
import {base} from '@airtable/blocks';
import {FieldType} from '@airtable/blocks/models';
import {colors} from '@airtable/blocks/ui';

const newTasksTable = await base.createTableAsync('Tasks', [
    {name: 'Name', type: FieldType.SINGLE_LINE_TEXT},
    {name: 'Due date', type: FieldType.DATE, options: {dateFormat: {name: 'us'}}},
    {name: 'Assignee', type: FieldType.SINGLE_COLLABORATOR},
    {
        name: 'Status',
        type: FieldType.SINGLE_SELECT,
        options: {
            choices: [
                {name: 'Not started', color: colors.RED_LIGHT_1},
                {name: 'In progress', color: colors.YELLOW_LIGHT_1},
                {name: 'Done', color: colors.GREEN_LIGHT_1},
            ],
        },
    },
]);
```

## Usage

Just like the other SDK write methods for creating, updating, and deleting
records, each of these new methods comes with built-in permission check
helpers: `checkPermissionsFor[Action]` and `hasPermissionTo[Action]`. Reference
[Write back to Airtable: Permissions](https://airtable.com/developers/extensions/guides/write-back-to-airtable.md#permissions)
for an overview of how to use these helpers to ensure only permitted actions
can be performed in your extension.

Here’s an example of how to employ these permission checks:

```js
import {FieldType} from '@airtable/blocks/models';
import {Box, Button, Text} from '@airtable/blocks/ui';

function CreateFieldButton({table}) {
    const permissionCheckResult = table.checkPermissionsForCreateField();

    function createField() {
        if (table.hasPermissionToCreateField()) {
            table.createFieldAsync('New field', FieldType.SINGLE_LINE_TEXT);
        }
    }

    return (
        <Box>
            <Button
                disabled={permissionCheckResult.hasPermission}
                onClick={createField}
            >
                Create field
            </Button>
            {!permissionCheckResult.hasPermission && (
                <Text marginTop={2}>{permissionCheckResult.reasonDisplayString}</Text>
            )}
        </Box>
    );
}
```

These new base schema methods also share the same principles as the other
write methods for [asynchronous execution](https://airtable.com/developers/extensions/guides/write-back-to-airtable.md#asynchronous-updates)
and [rate limiting](https://airtable.com/developers/extensions/guides/write-back-to-airtable.md#size-limits-rate-limits).
