This is an automated email from the ASF dual-hosted git repository.

matrei pushed a commit to branch remove-airtable
in repository https://gitbox.apache.org/repos/asf/grails-static-website.git

commit ecdf5ca2572dc65edb581789e08210a98c2c4546
Author: Mattias Reichel <[email protected]>
AuthorDate: Wed Jan 14 17:49:33 2026 +0100

    fix: remove airtable
    
    The airtable events source is no longer used.
---
 .github/workflows/publish.yml                      |   2 -
 .../groovy/org/grails/events/GrailsAirtable.groovy | 113 ------
 .../groovy/org/grails/gradle/RenderSiteTask.groovy |  14 +-
 .../main/java/org/grails/airtable/AirtableApi.java |  63 ----
 .../java/org/grails/airtable/AirtableApiError.java |  39 ---
 .../java/org/grails/airtable/AirtableBaseApi.java  | 108 ------
 .../grails/airtable/AirtableBaseConfiguration.java |  31 --
 .../AirtableBaseConfigurationProperties.java       |  54 ---
 .../java/org/grails/airtable/AirtableClient.java   |  53 ---
 .../org/grails/airtable/AirtableConfiguration.java |  46 ---
 .../airtable/AirtableConfigurationProperties.java  |  85 -----
 .../java/org/grails/airtable/AirtableError.java    |  47 ---
 .../java/org/grails/airtable/AirtableFactory.java  |  42 ---
 .../main/java/org/grails/airtable/CellFormat.java  |  29 --
 .../main/java/org/grails/airtable/Direction.java   |  30 --
 .../src/main/java/org/grails/airtable/Record.java  |  74 ----
 .../main/java/org/grails/airtable/RecordList.java  |  41 ---
 .../src/main/java/org/grails/airtable/Sort.java    |  90 -----
 .../main/java/org/grails/airtable/TimeZone.java    | 383 ---------------------
 .../main/java/org/grails/airtable/UserLocale.java  | 133 -------
 .../grails/airtable/AirtableApiErrorSpec.groovy    |  15 -
 .../org/grails/airtable/AirtableBaseApiSpec.groovy |  89 -----
 .../airtable/AirtableBaseConfigurationSpec.groovy  |  18 -
 .../airtable/AirtableConfigurationSpec.groovy      |  22 --
 .../org/grails/airtable/AirtableErrorSpec.groovy   |  14 -
 .../ApplicationContextSpecification.groovy         |  17 -
 .../org/grails/airtable/CellFormatSpec.groovy      |  14 -
 .../grails/airtable/ConfigurationFixture.groovy    |  17 -
 .../org/grails/airtable/DirectionSpec.groovy       |  14 -
 .../test/groovy/org/grails/airtable/Event.groovy   |  18 -
 .../org/grails/airtable/MicronautAirtable.groovy   |  85 -----
 .../org/grails/airtable/RecordListSpec.groovy      |  14 -
 .../groovy/org/grails/airtable/RecordSpec.groovy   |  15 -
 .../groovy/org/grails/airtable/SortSpec.groovy     |  20 --
 .../groovy/org/grails/airtable/TimeZoneSpec.groovy |  11 -
 .../org/grails/airtable/UserLocaleSpec.groovy      |  11 -
 36 files changed, 1 insertion(+), 1870 deletions(-)

diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index ef18c4ecb7f..61d6af58e82 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -45,8 +45,6 @@ jobs:
           GITHUB_SLUG: apache/grails-website
           GH_TOKEN: ${{ secrets.GRAILS_GHTOKEN }}
           GH_BRANCH: asf-site-production
-          # AIRTABLE_BASE_ID: ${{ secrets.AIRTABLE_BASE_ID }}
-          # AIRTABLE_API_KEY: ${{ secrets.AIRTABLE_API_KEY }}
           GRADLE_ENTERPRISE_BUILD_CACHE_NODE_USER: ${{ 
secrets.GRADLE_ENTERPRISE_BUILD_CACHE_NODE_USER }}
           GRADLE_ENTERPRISE_BUILD_CACHE_NODE_KEY: ${{ 
secrets.GRADLE_ENTERPRISE_BUILD_CACHE_NODE_KEY }}
           GRADLE_TASK: build
diff --git a/buildSrc/src/main/groovy/org/grails/events/GrailsAirtable.groovy 
b/buildSrc/src/main/groovy/org/grails/events/GrailsAirtable.groovy
deleted file mode 100644
index a63563665aa..00000000000
--- a/buildSrc/src/main/groovy/org/grails/events/GrailsAirtable.groovy
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.grails.events
-
-import groovy.transform.CompileStatic
-import groovy.transform.Memoized
-import org.grails.airtable.AirtableBaseApi
-import org.grails.airtable.Record
-
-import java.time.LocalDate
-import java.util.stream.Collectors
-
-@CompileStatic
-class GrailsAirtable {
-
-    public static final String FIELD_NAME = 'Name'
-    public static final String FIELD_LINK = 'link'
-    public static final String FIELD_LOCATION = 'location'
-    public static final String FIELD_LINK_OCI = 'our webpage'
-    public static final String FIELD_EVENT_NAME = 'asset or event'
-    public static final String FIELD_DATE = 'start/publish date'
-    public static final String FIELD_OCI_SPEAKERS = 'OCI speaker(s)'
-    public static final String FIELD_GUEST_SPEAKERS = 'Guest Speakers'
-    public static final String FIELD_PRACTICE_AREA = 'practice area'
-    public static final String TABLE_PRACTICE_AREAS = 'Practice Areas'
-    public static final String TABLE_FOCUS = 'Focus'
-    public static final String TABLE_OCI_TEAM = 'OCI Team'
-    public static final String TABLE_GUEST_SPEAKERS = 'Guest Speakers'
-    public static final String FIELD_STATUS = 'status'
-    public static final String STATUS_SCHEDULED = 'scheduled'
-    public static final String FIELD_EVENTS = 'events'
-
-    AirtableBaseApi api
-
-    GrailsAirtable(AirtableBaseApi api) {
-        this.api = api
-    }
-
-    List<Event> fetchGrailsByPracticeName(String practiceName) {
-        String areaId = practiceId(practiceName)
-        fetchEvents(areaId)
-    }
-
-    @Memoized
-    List<Event> fetchEvents(String practiceId) {
-        List<Record> records = api.list(TABLE_FOCUS,
-                null,
-                null,
-                null,
-                null,
-                null,
-                "All Upcoming Events",
-                null,
-                null,
-                null).records
-        records.stream().filter(record -> {
-            (record.fields[FIELD_PRACTICE_AREA] && 
(record.fields[FIELD_PRACTICE_AREA] as List<String>).contains(practiceId)) &&
-                    (record.fields[FIELD_STATUS] == STATUS_SCHEDULED) &&
-                    (record.fields[FIELD_EVENTS] as boolean)
-        }).map(record -> {
-            String d = record.fields[FIELD_DATE]
-            Event e = new Event()
-            e.link = record.fields[FIELD_LINK] ?: record.fields[FIELD_LINK_OCI]
-            e.location = record.fields[FIELD_LOCATION]
-            e.name = record.fields[FIELD_EVENT_NAME]
-            e.date = LocalDate.of(d.substring(0, 4) as Integer , 
d.substring(5, 7) as Integer, d.substring(8, 10) as Integer)
-            List<String> ociSpeakers = 
record.fields[FIELD_OCI_SPEAKERS].collect { ociSpeakerName(it as String) }
-            List<String> guestSpeakers = 
record.fields[FIELD_GUEST_SPEAKERS].collect { guestSpeakerName(it as String) }
-            e.speakers = ociSpeakers + guestSpeakers
-            e
-        }).collect(Collectors.toList())
-    }
-
-    String ociSpeakerName(String speakerId) {
-        speakerName(TABLE_OCI_TEAM, speakerId)
-    }
-
-    String guestSpeakerName(String speakerId) {
-        speakerName(TABLE_GUEST_SPEAKERS, speakerId)
-    }
-
-    @Memoized
-    String speakerName(String speakerTable, String speakerId) {
-        List<Record> records = api.list(speakerTable,
-                [FIELD_NAME],
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null).records
-        records.find { Record record ->
-            record.id == speakerId
-        }?.fields[FIELD_NAME] as String
-    }
-
-    @Memoized
-    String practiceId(String practiceName) {
-        List<Record> practiceAreaRecords = api.list(TABLE_PRACTICE_AREAS,
-                [FIELD_NAME],
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null).records
-        practiceAreaRecords.find { Record record ->
-            (record.fields[FIELD_NAME] as 
String).equalsIgnoreCase(practiceName)
-        }?.id
-    }
-}
diff --git a/buildSrc/src/main/groovy/org/grails/gradle/RenderSiteTask.groovy 
b/buildSrc/src/main/groovy/org/grails/gradle/RenderSiteTask.groovy
index ff72597a92e..1f311b32b2d 100644
--- a/buildSrc/src/main/groovy/org/grails/gradle/RenderSiteTask.groovy
+++ b/buildSrc/src/main/groovy/org/grails/gradle/RenderSiteTask.groovy
@@ -5,13 +5,12 @@ import groovy.transform.CompileDynamic
 import groovy.transform.CompileStatic
 import org.grails.ContentAndMetadata
 import org.grails.Page
-import org.grails.airtable.AirtableBaseApi
 import io.micronaut.context.ApplicationContext
 import org.grails.documentation.SiteMap
 import org.grails.documentation.SoftwareVersion
 import org.grails.events.Event
 import org.grails.events.EventsPage
-import org.grails.events.GrailsAirtable
+
 import io.micronaut.inject.qualifiers.Qualifiers
 import org.gradle.api.DefaultTask
 import org.gradle.api.provider.ListProperty
@@ -94,17 +93,6 @@ class RenderSiteTask extends DefaultTask {
                                         String versionsBeforeGrails6
     ) {
         String eventsHtml = ""
-        if (System.getenv("AIRTABLE_API_KEY") != null && 
System.getenv("AIRTABLE_BASE_ID") != null) {
-            Map<String, Object> configuration = [:]
-            configuration['airtable.api-key'] = 
System.getenv("AIRTABLE_API_KEY")
-            configuration['airtable.bases.2022.id'] =  
System.getenv("AIRTABLE_BASE_ID")
-            ApplicationContext applicationContext = 
ApplicationContext.run(configuration)
-            AirtableBaseApi api = applicationContext.getBean(AirtableBaseApi, 
Qualifiers.byName("2022"))
-            GrailsAirtable airtable = new GrailsAirtable(api)
-            List<Event> events = airtable.fetchGrailsByPracticeName('2GM')
-            eventsHtml = EventsPage.eventsTable(events)
-            applicationContext.close()
-        }
         [
                 title: title,
                 description: about,
diff --git a/buildSrc/src/main/java/org/grails/airtable/AirtableApi.java 
b/buildSrc/src/main/java/org/grails/airtable/AirtableApi.java
deleted file mode 100644
index 5319d9052b0..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/AirtableApi.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.annotations.Nullable;
-import io.micronaut.http.annotation.Header;
-import io.micronaut.http.annotation.PathVariable;
-import io.micronaut.http.annotation.QueryValue;
-
-import javax.validation.constraints.NotBlank;
-import java.util.List;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-public interface AirtableApi {
-
-    /**
-     * @see <a 
href="https://support.airtable.com/hc/en-us/articles/203255215-Formula-Field-Reference";>Formulas</a>.
-     *
-     * @param authorization Airtable API Key e.g. Bearer XXXX
-     * @param baseId Airtable base Id
-     * @param table Airtable Table
-     * @param fields Only data for fields whose names are in this list will be 
included in the result. If you don't need every field, you can use this 
parameter to reduce the amount of data transferred.
-     * @param filterByFormula A formula used to filter records. The formula 
will be evaluated for each record, and if the result is not 0, false, "", NaN, 
[], or #Error! the record will be included in the response. If combined with 
the view parameter, only records in that view which satisfy the formula will be 
returned.
-     * @param maxRecords The maximum total number of records that will be 
returned in your requests. If this value is larger than pageSize (which is 100 
by default), you may have to load multiple pages to reach this total.
-     * @param pageSize The number of records returned in each request. Must be 
less than or equal to 100. Default is 100.
-     * @param sort A list of sort objects that specifies how to record will be 
ordered.
-     * @param view The name or ID of a view in the Focus table. If set, only 
the records in that view will be returned. The records will be sorted according 
to the order of the view unless the sort parameter is included, which overrides 
that order. Fields hidden in this view will be returned in the results. To only 
return a subset of fields, use the fields parameter.
-     * @param cellFormat The format that should be used for cell values. 
Default value json
-     * @param timeZone The time zone that should used to format dates when 
using string as cellFormat. This parameter is required when using string as the 
cell format
-     * @param userLocale The user locale that should be used to format dates 
when using String as cellFormat.
-     * @return A list records in a table
-     */
-    RecordList list(@Header String authorization,
-                            @NonNull @NotBlank @PathVariable String version,
-                            @NonNull @NotBlank @PathVariable String baseId,
-                            @NonNull @NotBlank @PathVariable String table,
-                            @Nullable @QueryValue("fields[]") List<String> 
fields,
-                            @Nullable @QueryValue String filterByFormula,
-                            @Nullable @QueryValue Integer maxRecords,
-                            @Nullable @QueryValue Integer pageSize,
-                            @Nullable @QueryValue List<Sort> sort,
-                            @Nullable @QueryValue String view,
-                            @Nullable @QueryValue CellFormat cellFormat,
-                            @Nullable @QueryValue TimeZone timeZone,
-                            @Nullable @QueryValue UserLocale userLocale);
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/AirtableApiError.java 
b/buildSrc/src/main/java/org/grails/airtable/AirtableApiError.java
deleted file mode 100644
index 712dc245a20..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/AirtableApiError.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import io.micronaut.core.annotation.Introspected;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@Introspected
-public class AirtableApiError {
-
-    private AirtableError error;
-
-    public AirtableApiError() {
-    }
-
-    public AirtableError getError() {
-        return error;
-    }
-
-    public void setError(AirtableError error) {
-        this.error = error;
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/AirtableBaseApi.java 
b/buildSrc/src/main/java/org/grails/airtable/AirtableBaseApi.java
deleted file mode 100644
index 98adb7f00a9..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/AirtableBaseApi.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.annotations.Nullable;
-import io.micronaut.core.util.StringUtils;
-import io.micronaut.http.HttpHeaderValues;
-import io.micronaut.http.annotation.PathVariable;
-import io.micronaut.http.annotation.QueryValue;
-import io.micronaut.http.client.exceptions.HttpClientException;
-import io.micronaut.http.client.exceptions.HttpClientResponseException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.validation.constraints.NotBlank;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-public class AirtableBaseApi {
-    private static final Logger LOG = 
LoggerFactory.getLogger(AirtableBaseApi.class);
-
-    private final AirtableClient airtableClient;
-    private final AirtableConfiguration airtableConfiguration;
-    private final AirtableBaseConfiguration airtableBaseConfiguration;
-
-    public AirtableBaseApi(AirtableClient airtableClient,
-                           AirtableConfiguration airtableConfiguration,
-                           AirtableBaseConfiguration 
airtableBaseConfiguration) {
-        this.airtableClient = airtableClient;
-        this.airtableConfiguration = airtableConfiguration;
-        this.airtableBaseConfiguration = airtableBaseConfiguration;
-    }
-
-    public RecordList list(@NonNull @NotBlank @PathVariable String table,
-                                   @Nullable @QueryValue("fields[]") 
List<String> fields,
-                                   @Nullable @QueryValue String 
filterByFormula,
-                                   @Nullable @QueryValue Integer maxRecords,
-                                   @Nullable @QueryValue Integer pageSize,
-                                   @Nullable @QueryValue List<Sort> sort,
-                                   @Nullable @QueryValue String view,
-                                   @Nullable @QueryValue CellFormat cellFormat,
-                                   @Nullable @QueryValue TimeZone timeZone,
-                                   @Nullable @QueryValue UserLocale 
userLocale) {
-        try {
-            return 
airtableClient.list(HttpHeaderValues.AUTHORIZATION_PREFIX_BEARER + 
StringUtils.SPACE + airtableConfiguration.getApiKey(),
-                    airtableConfiguration.getApiVersion(),
-                    airtableBaseConfiguration.getId(),
-                    table,
-                    fields,
-                    filterByFormula,
-                    maxRecords,
-                    pageSize,
-                    sort,
-                    view,
-                    cellFormat,
-                    timeZone,
-                    userLocale);
-        } catch (HttpClientResponseException e) {
-            if (LOG.isErrorEnabled()) {
-                LOG.error("HTTPClientResponseException getting records - 
status {}", e.getStatus());
-            }
-            Optional<AirtableApiError> airtableApiErrorOptional = 
e.getResponse().getBody(AirtableApiError.class);
-            if (airtableApiErrorOptional.isPresent()) {
-                AirtableApiError airtableApiError = 
airtableApiErrorOptional.get();
-                if (LOG.isErrorEnabled()) {
-                    LOG.error("Airtable API Error - type {} message {}",
-                            airtableApiError.getError() != null ? 
airtableApiError.getError().getType() : "",
-                            airtableApiError.getError() != null ? 
airtableApiError.getError().getMessage() : "");
-                }
-            }
-        }
-        RecordList recordList = new RecordList();
-        recordList.setRecords(Collections.emptyList());
-        return recordList;
-    }
-
-    public RecordList list(@NonNull @NotBlank @PathVariable String table) {
-        return list(table,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null);
-    }
-}
diff --git 
a/buildSrc/src/main/java/org/grails/airtable/AirtableBaseConfiguration.java 
b/buildSrc/src/main/java/org/grails/airtable/AirtableBaseConfiguration.java
deleted file mode 100644
index 36df49054b8..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/AirtableBaseConfiguration.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-public interface AirtableBaseConfiguration {
-    /**
-     *
-     * @return Airtable base id
-     */
-    @NonNull
-    String getId();
-}
diff --git 
a/buildSrc/src/main/java/org/grails/airtable/AirtableBaseConfigurationProperties.java
 
b/buildSrc/src/main/java/org/grails/airtable/AirtableBaseConfigurationProperties.java
deleted file mode 100644
index 49ab6bc64dc..00000000000
--- 
a/buildSrc/src/main/java/org/grails/airtable/AirtableBaseConfigurationProperties.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-import io.micronaut.context.annotation.EachProperty;
-import io.micronaut.context.annotation.Parameter;
-
-import javax.validation.constraints.NotBlank;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@EachProperty(AirtableConfigurationProperties.PREFIX + ".bases")
-public class AirtableBaseConfigurationProperties implements 
AirtableBaseConfiguration {
-
-    private final String name;
-
-    public AirtableBaseConfigurationProperties(@Parameter String name) {
-        this.name = name;
-    }
-
-    @NonNull
-    @NotBlank
-    private String id;
-
-    @NonNull
-    @Override
-    public String getId() {
-        return id;
-    }
-
-    /**
-     *
-     * @param id Sets Airtable base id
-     */
-    public void setId(@NonNull String id) {
-        this.id = id;
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/AirtableClient.java 
b/buildSrc/src/main/java/org/grails/airtable/AirtableClient.java
deleted file mode 100644
index 3ecb8aadc7a..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/AirtableClient.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.annotations.Nullable;
-import io.micronaut.http.annotation.Get;
-import io.micronaut.http.annotation.Header;
-import io.micronaut.http.annotation.PathVariable;
-import io.micronaut.http.annotation.QueryValue;
-import io.micronaut.http.client.annotation.Client;
-
-import javax.validation.constraints.NotBlank;
-import java.util.List;
-
-/**
- * Micronaut declarative HTTP Client to consume Airtable API.
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@Client(value = "${airtable.url:`" + 
AirtableConfigurationProperties.DEFAULT_URL + "`}",
-        errorType = AirtableApiError.class)
-public interface AirtableClient extends AirtableApi {
-
-    @Override
-    @Get("/{version}/{baseId}/{table}")
-    RecordList list(@Header String authorization,
-                            @NonNull @NotBlank @PathVariable String version,
-                            @NonNull @NotBlank @PathVariable String baseId,
-                            @NonNull @NotBlank @PathVariable String table,
-                            @Nullable @QueryValue("fields[]") List<String> 
fields,
-                            @Nullable @QueryValue String filterByFormula,
-                            @Nullable @QueryValue Integer maxRecords,
-                            @Nullable @QueryValue Integer pageSize,
-                            @Nullable @QueryValue List<Sort> sort,
-                            @Nullable @QueryValue String view,
-                            @Nullable @QueryValue CellFormat cellFormat,
-                            @Nullable @QueryValue TimeZone timeZone,
-                            @Nullable @QueryValue UserLocale userLocale);
-}
diff --git 
a/buildSrc/src/main/java/org/grails/airtable/AirtableConfiguration.java 
b/buildSrc/src/main/java/org/grails/airtable/AirtableConfiguration.java
deleted file mode 100644
index ffe031ca268..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/AirtableConfiguration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-public interface AirtableConfiguration {
-
-    /**
-     *
-     * @return Airtable API URL
-     */
-    @NonNull
-    String getUrl();
-
-    /**
-     *
-     * @return Airtable API Key
-     */
-    @NonNull
-    String getApiKey();
-
-    /**
-     *
-     * @return Airtable API version
-     */
-    @NonNull
-    String getApiVersion();
-}
diff --git 
a/buildSrc/src/main/java/org/grails/airtable/AirtableConfigurationProperties.java
 
b/buildSrc/src/main/java/org/grails/airtable/AirtableConfigurationProperties.java
deleted file mode 100644
index 7b255ba4725..00000000000
--- 
a/buildSrc/src/main/java/org/grails/airtable/AirtableConfigurationProperties.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-import io.micronaut.context.annotation.ConfigurationProperties;
-import javax.validation.constraints.NotBlank;
-
-/**
- * {@link ConfigurationProperties} implementation of {@link 
AirtableConfiguration}.
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@ConfigurationProperties(AirtableConfigurationProperties.PREFIX)
-public class AirtableConfigurationProperties implements AirtableConfiguration {
-
-    public static final String PREFIX = "airtable";
-
-    public static final String V0 = "v0";
-
-    public static final String DEFAULT_URL = "https://api.airtable.com/";;
-
-    @NonNull
-    @NotBlank
-    private String url = DEFAULT_URL;
-
-    @NonNull
-    @NotBlank
-    private String apiKey;
-
-    @NonNull
-    @NotBlank
-    private String apiVersion = V0;
-
-    @Override
-    @NonNull
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(@NonNull String url) {
-        this.url = url;
-    }
-
-    @Override
-    @NonNull
-    public String getApiKey() {
-        return apiKey;
-    }
-
-    /**
-     *
-     * @param apiKey Sets Airtable API key
-     */
-    public void setApiKey(@NonNull String apiKey) {
-        this.apiKey = apiKey;
-    }
-
-    @Override
-    @NonNull
-    public String getApiVersion() {
-        return apiVersion;
-    }
-
-    /**
-     *
-     * @param apiVersion Airtable API Version {@value 
AirtableConfigurationProperties#V0}.
-     */
-    public void setApiVersion(@NonNull String apiVersion) {
-        this.apiVersion = apiVersion;
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/AirtableError.java 
b/buildSrc/src/main/java/org/grails/airtable/AirtableError.java
deleted file mode 100644
index 79b7d355f76..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/AirtableError.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import io.micronaut.core.annotation.Introspected;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@Introspected
-public class AirtableError {
-    private String type;
-    private String message;
-
-    public AirtableError() {
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/AirtableFactory.java 
b/buildSrc/src/main/java/org/grails/airtable/AirtableFactory.java
deleted file mode 100644
index 7ee72ae786a..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/AirtableFactory.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import io.micronaut.context.annotation.EachBean;
-import io.micronaut.context.annotation.Factory;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@Factory
-public class AirtableFactory {
-
-    private final AirtableClient airtableClient;
-    private final AirtableConfiguration airtableConfiguration;
-
-    public AirtableFactory(AirtableClient airtableClient,
-                           AirtableConfiguration airtableConfiguration) {
-        this.airtableClient = airtableClient;
-        this.airtableConfiguration = airtableConfiguration;
-    }
-
-
-    @EachBean(AirtableBaseConfiguration.class)
-    public AirtableBaseApi buildEngine(AirtableBaseConfiguration 
baseConfiguration) {
-        return new AirtableBaseApi(airtableClient, airtableConfiguration, 
baseConfiguration);
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/CellFormat.java 
b/buildSrc/src/main/java/org/grails/airtable/CellFormat.java
deleted file mode 100644
index f36ab73fa25..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/CellFormat.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-public enum CellFormat {
-    JSON, STRING;
-
-    @Override
-    public String toString() {
-        return name().toLowerCase();
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/Direction.java 
b/buildSrc/src/main/java/org/grails/airtable/Direction.java
deleted file mode 100644
index c9cc6d01b34..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/Direction.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-public enum Direction {
-
-    ASC, DESC;
-
-    @Override
-    public String toString() {
-        return name().toLowerCase();
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/Record.java 
b/buildSrc/src/main/java/org/grails/airtable/Record.java
deleted file mode 100644
index a23dd4e6a65..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/Record.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import edu.umd.cs.findbugs.annotations.NonNull;
-import io.micronaut.core.annotation.Introspected;
-
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import java.util.Map;
-
-/**
- * Airtable records
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@Introspected
-public class Record {
-
-    @NonNull
-    @NotBlank
-    private String id;
-
-    @NonNull
-    @NotNull
-    private Map<String, Object> fields;
-
-    @NonNull
-    @NotBlank
-    private String createdTime;
-
-    public Record() {
-    }
-
-    @NonNull
-    public String getId() {
-        return id;
-    }
-
-    public void setId(@NonNull String id) {
-        this.id = id;
-    }
-
-    @NonNull
-    public Map<String, Object> getFields() {
-        return fields;
-    }
-
-    public void setFields(@NonNull Map<String, Object> fields) {
-        this.fields = fields;
-    }
-
-    @NonNull
-    public String getCreatedTime() {
-        return createdTime;
-    }
-
-    public void setCreatedTime(@NonNull String createdTime) {
-        this.createdTime = createdTime;
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/RecordList.java 
b/buildSrc/src/main/java/org/grails/airtable/RecordList.java
deleted file mode 100644
index 2ef6ff75063..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/RecordList.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import io.micronaut.core.annotation.Introspected;
-
-import java.util.List;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@Introspected
-public class RecordList {
-
-    private List<Record> records;
-
-    public RecordList() {
-    }
-
-    public List<Record> getRecords() {
-        return records;
-    }
-
-    public void setRecords(List<Record> records) {
-        this.records = records;
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/Sort.java 
b/buildSrc/src/main/java/org/grails/airtable/Sort.java
deleted file mode 100644
index c7414371a6c..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/Sort.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-import io.micronaut.core.annotation.Introspected;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-@Introspected
-public class Sort {
-
-    public static final Direction DEFAULT_DIRECTION = Direction.ASC;
-
-    /**
-     *  key specifying the name of the field to sort on.
-     */
-    private String field;
-    private Direction direction = DEFAULT_DIRECTION;
-
-    /**
-     * Constructor.
-     */
-    public Sort() {
-    }
-
-    /**
-     * Constructor.
-     * @param field key specifying the name of the field to sort on.
-     */
-    public Sort(String field) {
-        this.field = field;
-    }
-
-    /**
-     * Constructor.
-     * @param field key specifying the name of the field to sort on.
-     * @param direction "asc" or "desc" direction key.
-     */
-    public Sort(String field, Direction direction) {
-        this.field = field;
-        this.direction = direction;
-    }
-
-    /**
-     *
-     * @return key specifying the name of the field to sort on.
-     */
-    public String getField() {
-        return field;
-    }
-
-    /**
-     *
-     * @param field  key specifying the name of the field to sort on.
-     */
-    public void setField(String field) {
-        this.field = field;
-    }
-
-    /**
-     *
-     * @return "asc" or "desc" direction key.
-     */
-    public Direction getDirection() {
-        return direction;
-    }
-
-    /**
-     *
-     * @param direction "asc" or "desc" direction key.
-     */
-    public void setDirection(Direction direction) {
-        this.direction = direction;
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/TimeZone.java 
b/buildSrc/src/main/java/org/grails/airtable/TimeZone.java
deleted file mode 100644
index 138623dc261..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/TimeZone.java
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-/**
- * <a 
href="https://support.airtable.com/hc/en-us/articles/216141558-Supported-timezones-for-SET-TIMEZONE";>Airtable
 supported time zones</a>
- * @author Sergio del Amo
- * @since 1.0.0
- */
-public enum TimeZone {
-    AFRICA_ABIDJAN("Africa/Abidjan"),
-    AFRICA_ACCRA("Africa/Accra"),
-    AFRICA_ALGIERS("Africa/Algiers"),
-    AFRICA_BISSAU("Africa/Bissau"),
-    AFRICA_CAIRO("Africa/Cairo"),
-    AFRICA_CASABLANCA("Africa/Casablanca"),
-    AFRICA_CEUTA("Africa/Ceuta"),
-    AFRICA_EL_AAIUN("Africa/El_Aaiun"),
-    AFRICA_JOHANNESBURG("Africa/Johannesburg"),
-    AFRICA_KHARTOUM("Africa/Khartoum"),
-    AFRICA_LAGOS("Africa/Lagos"),
-    AFRICA_MAPUTO("Africa/Maputo"),
-    AFRICA_MONROVIA("Africa/Monrovia"),
-    AFRICA_NAIROBI("Africa/Nairobi"),
-    AFRICA_NDJAMENA("Africa/Ndjamena"),
-    AFRICA_TRIPOLI("Africa/Tripoli"),
-    AFRICA_TUNIS("Africa/Tunis"),
-    AFRICA_WINDHOEK("Africa/Windhoek"),
-
-    AMERICA_ADAK("America/Adak"),
-    AMERICA_ANCHORAGE("America/Anchorage"),
-    AMERICA_ARAGUAINA("America/Araguaina"),
-    AMERICA_ARGENTINA_BUENOS_AIRES("America/Argentina/Buenos_Aires"),
-    AMERICA_ARGENTINA_CATAMARCA("America/Argentina/Catamarca"),
-    AMERICA_ARGENTINA_CORDOBA("America/Argentina/Cordoba"),
-    AMERICA_ARGENTINA_JUJUY("America/Argentina/Jujuy"),
-    AMERICA_ARGENTINA_LA_RIOJA("America/Argentina/La_Rioja"),
-    AMERICA_ARGENTINA_MENDOZA("America/Argentina/Mendoza"),
-    AMERICA_ARGENTINA_RIO_GALLEGOS("America/Argentina/Rio_Gallegos"),
-    AMERICA_ARGENTINA_SALTA("America/Argentina/Salta"),
-    AMERICA_ARGENTINA_SAN_JUAN("America/Argentina/San_Juan"),
-    AMERICA_ARGENTINA_SAN_LUIS("America/Argentina/San_Luis"),
-    AMERICA_ARGENTINA_TUCUMAN("America/Argentina/Tucuman"),
-    AMERICA_ARGENTINA_USHUAIA("America/Argentina/Ushuaia"),
-    AMERICA_ASUNCION("America/Asuncion"),
-    AMERICA_ATIKOKAN("America/Atikokan"),
-    AMERICA_BAHIA("America/Bahia"),
-    AMERICA_BAHIA_BANDERAS("America/Bahia_Banderas"),
-    AMERICA_BARBADOS("America/Barbados"),
-    AMERICA_BELEM("America/Belem"),
-    AMERICA_BELIZE("America/Belize"),
-    AMERICA_BLANC_SABLON("America/Blanc-Sablon"),
-    AMERICA_BOA_VISTA("America/Boa_Vista"),
-    AMERICA_BOGOTA("America/Bogota"),
-    AMERICA_BOISE("America/Boise"),
-    AMERICA_CAMBRIDGE_BAY("America/Cambridge_Bay"),
-    AMERICA_CAMPO_GRANDE("America/Campo_Grande"),
-    AMERICA_CANCUN("America/Cancun"),
-    AMERICA_CARACAS("America/Caracas"),
-    AMERICA_CAYENNE("America/Cayenne"),
-    AMERICA_CHICAGO("America/Chicago"),
-    AMERICA_CHIHUAHUA("America/Chihuahua"),
-    AMERICA_COSTA_RICA("America/Costa_Rica"),
-    AMERICA_CRESTON("America/Creston"),
-    AMERICA_CUIABA("America/Cuiaba"),
-    AMERICA_CURACAO("America/Curacao"),
-    AMERICA_DANMARKSHAVN("America/Danmarkshavn"),
-    AMERICA_DAWSON("America/Dawson"),
-    AMERICA_DAWSON_CREEK("America/Dawson_Creek"),
-    AMERICA_DENVER("America/Denver"),
-    AMERICA_DETROIT("America/Detroit"),
-    AMERICA_EDMONTON("America/Edmonton"),
-    AMERICA_EIRUNEPE("America/Eirunepe"),
-    AMERICA_EL_SALVADOR("America/El_Salvador"),
-    AMERICA_FORT_NELSON("America/Fort_Nelson"),
-    AMERICA_FORTALEZA("America/Fortaleza"),
-    AMERICA_GLACE_BAY("America/Glace_Bay"),
-    AMERICA_GODTHAB("America/Godthab"),
-    AMERICA_GOOSE_BAY("America/Goose_Bay"),
-    AMERICA_GRAND_TURK("America/Grand_Turk"),
-    AMERICA_GUATEMALA("America/Guatemala"),
-    AMERICA_GUAYAQUIL("America/Guayaquil"),
-    AMERICA_GUYANA("America/Guyana"),
-    AMERICA_HALIFAX("America/Halifax"),
-    AMERICA_HAVANA("America/Havana"),
-    AMERICA_HERMOSILLO("America/Hermosillo"),
-    AMERICA_INDIANA_INDIANAPOLIS("America/Indiana/Indianapolis"),
-    AMERICA_INDIANA_KNOX("America/Indiana/Knox"),
-    AMERICA_INDIANA_MARENGO("America/Indiana/Marengo"),
-    AMERICA_INDIANA_PETERSBURG("America/Indiana/Petersburg"),
-    AMERICA_INDIANA_TELL_CITY("America/Indiana/Tell_City"),
-    AMERICA_INDIANA_VEVAY("America/Indiana/Vevay"),
-    AMERICA_INDIANA_VINCENNES("America/Indiana/Vincennes"),
-    AMERICA_INDIANA_WINAMAC("America/Indiana/Winamac"),
-    AMERICA_INUVIK("America/Inuvik"),
-    AMERICA_IQALUIT("America/Iqaluit"),
-    AMERICA_JAMAICA("America/Jamaica"),
-    AMERICA_JUNEAU("America/Juneau"),
-    AMERICA_KENTUCKY_LOUISVILLE("America/Kentucky/Louisville"),
-    AMERICA_KENTUCKY_MONTICELLO("America/Kentucky/Monticello"),
-    AMERICA_LA_PAZ("America/La_Paz"),
-    AMERICA_LIMA("America/Lima"),
-    AMERICA_LOS_ANGELES("America/Los_Angeles"),
-    AMERICA_MACEIO("America/Maceio"),
-    AMERICA_MANAGUA("America/Managua"),
-    AMERICA_MANAUS("America/Manaus"),
-    AMERICA_MARTINIQUE("America/Martinique"),
-    AMERICA_MATAMOROS("America/Matamoros"),
-    AMERICA_MAZATLAN("America/Mazatlan"),
-    AMERICA_MENOMINEE("America/Menominee"),
-    AMERICA_MERIDA("America/Merida"),
-    AMERICA_METLAKATLA("America/Metlakatla"),
-    AMERICA_MEXICO_CITY("America/Mexico_City"),
-    AMERICA_MIQUELON("America/Miquelon"),
-    AMERICA_MONCTON("America/Moncton"),
-    AMERICA_MONTERREY("America/Monterrey"),
-    AMERICA_MONTEVIDEO("America/Montevideo"),
-    AMERICA_NASSAU("America/Nassau"),
-    AMERICA_NEW_YORK("America/New_York"),
-    AMERICA_NIPIGON("America/Nipigon"),
-    AMERICA_NOME("America/Nome"),
-    AMERICA_NORONHA("America/Noronha"),
-    AMERICA_NORTH_DAKOTA_BEULAH("America/North_Dakota/Beulah"),
-    AMERICA_NORTH_DAKOTA_CENTER("America/North_Dakota/Center"),
-    AMERICA_NORTH_DAKOTA_NEW_SALEM("America/North_Dakota/New_Salem"),
-    AMERICA_OJINAGA("America/Ojinaga"),
-    AMERICA_PANAMA("America/Panama"),
-    AMERICA_PANGNIRTUNG("America/Pangnirtung"),
-    AMERICA_PARAMARIBO("America/Paramaribo"),
-    AMERICA_PHOENIX("America/Phoenix"),
-    AMERICA_PORT_AU_PRINCE("America/Port-au-Prince"),
-    AMERICA_PORT_OF_SPAIN("America/Port_of_Spain"),
-    AMERICA_PORTO_VELHO("America/Porto_Velho"),
-    AMERICA_PUERTO_RICO("America/Puerto_Rico"),
-    AMERICA_RAINY_RIVER("America/Rainy_River"),
-    AMERICA_RANKIN_INLET("America/Rankin_Inlet"),
-    AMERICA_RECIFE("America/Recife"),
-    AMERICA_REGINA("America/Regina"),
-    AMERICA_RESOLUTE("America/Resolute"),
-    AMERICA_RIO_BRANCO("America/Rio_Branco"),
-    AMERICA_SANTAREM("America/Santarem"),
-    AMERICA_SANTIAGO("America/Santiago"),
-    AMERICA_SANTO_DOMINGO("America/Santo_Domingo"),
-    AMERICA_SAO_PAULO("America/Sao_Paulo"),
-    AMERICA_SCORESBYSUND("America/Scoresbysund"),
-    AMERICA_SITKA("America/Sitka"),
-    AMERICA_ST_JOHNS("America/St_Johns"),
-    AMERICA_SWIFT_CURRENT("America/Swift_Current"),
-    AMERICA_TEGUCIGALPA("America/Tegucigalpa"),
-    AMERICA_THULE("America/Thule"),
-    AMERICA_THUNDER_BAY("America/Thunder_Bay"),
-    AMERICA_TIJUANA("America/Tijuana"),
-    AMERICA_TORONTO("America/Toronto"),
-    AMERICA_VANCOUVER("America/Vancouver"),
-    AMERICA_WHITEHORSE("America/Whitehorse"),
-    AMERICA_WINNIPEG("America/Winnipeg"),
-    AMERICA_YAKUTAT("America/Yakutat"),
-    AMERICA_YELLOWKNIFE("America/Yellowknife"),
-
-    ANTARCTICA_CASEY("Antarctica/Casey"),
-    ANTARCTICA_DAVIS("Antarctica/Davis"),
-    ANTARCTICA_DUMONTDURVILLE("Antarctica/DumontDUrville"),
-    ANTARCTICA_MACQUARIE("Antarctica/Macquarie"),
-    ANTARCTICA_MAWSON("Antarctica/Mawson"),
-    ANTARCTICA_PALMER("Antarctica/Palmer"),
-    ANTARCTICA_ROTHERA("Antarctica/Rothera"),
-    ANTARCTICA_SYOWA("Antarctica/Syowa"),
-    ANTARCTICA_TROLL("Antarctica/Troll"),
-    ANTARCTICA_VOSTOK("Antarctica/Vostok"),
-
-    ASIA_ALMATY("Asia/Almaty"),
-    ASIA_AMMAN("Asia/Amman"),
-    ASIA_ANADYR("Asia/Anadyr"),
-    ASIA_AQTAU("Asia/Aqtau"),
-    ASIA_AQTOBE("Asia/Aqtobe"),
-    ASIA_ASHGABAT("Asia/Ashgabat"),
-    ASIA_BAGHDAD("Asia/Baghdad"),
-    ASIA_BAKU("Asia/Baku"),
-    ASIA_BANGKOK("Asia/Bangkok"),
-    ASIA_BARNAUL("Asia/Barnaul"),
-    ASIA_BEIRUT("Asia/Beirut"),
-    ASIA_BISHKEK("Asia/Bishkek"),
-    ASIA_BRUNEI("Asia/Brunei"),
-    ASIA_CHITA("Asia/Chita"),
-    ASIA_CHOIBALSAN("Asia/Choibalsan"),
-    ASIA_COLOMBO("Asia/Colombo"),
-    ASIA_DAMASCUS("Asia/Damascus"),
-    ASIA_DHAKA("Asia/Dhaka"),
-    ASIA_DILI("Asia/Dili"),
-    ASIA_DUBAI("Asia/Dubai"),
-    ASIA_DUSHANBE("Asia/Dushanbe"),
-    ASIA_GAZA("Asia/Gaza"),
-    ASIA_HEBRON("Asia/Hebron"),
-    ASIA_HO_CHI_MINH("Asia/Ho_Chi_Minh"),
-    ASIA_HONG_KONG("Asia/Hong_Kong"),
-    ASIA_HOVD("Asia/Hovd"),
-    ASIA_IRKUTSK("Asia/Irkutsk"),
-    ASIA_JAKARTA("Asia/Jakarta"),
-    ASIA_JAYAPURA("Asia/Jayapura"),
-    ASIA_JERUSALEM("Asia/Jerusalem"),
-    ASIA_KABUL("Asia/Kabul"),
-    ASIA_KAMCHATKA("Asia/Kamchatka"),
-    ASIA_KARACHI("Asia/Karachi"),
-    ASIA_KATHMANDU("Asia/Kathmandu"),
-    ASIA_KHANDYGA("Asia/Khandyga"),
-    ASIA_KOLKATA("Asia/Kolkata"),
-    ASIA_KRASNOYARSK("Asia/Krasnoyarsk"),
-    ASIA_KUALA_LUMPUR("Asia/Kuala_Lumpur"),
-    ASIA_KUCHING("Asia/Kuching"),
-    ASIA_MACAU("Asia/Macau"),
-    ASIA_MAGADAN("Asia/Magadan"),
-    ASIA_MAKASSAR("Asia/Makassar"),
-    ASIA_MANILA("Asia/Manila"),
-    ASIA_NICOSIA("Asia/Nicosia"),
-    ASIA_NOVOKUZNETSK("Asia/Novokuznetsk"),
-    ASIA_NOVOSIBIRSK("Asia/Novosibirsk"),
-    ASIA_OMSK("Asia/Omsk"),
-    ASIA_ORAL("Asia/Oral"),
-    ASIA_PONTIANAK("Asia/Pontianak"),
-    ASIA_PYONGYANG("Asia/Pyongyang"),
-    ASIA_QATAR("Asia/Qatar"),
-    ASIA_QYZYLORDA("Asia/Qyzylorda"),
-    ASIA_RANGOON("Asia/Rangoon"),
-    ASIA_RIYADH("Asia/Riyadh"),
-    ASIA_SAKHALIN("Asia/Sakhalin"),
-    ASIA_SAMARKAND("Asia/Samarkand"),
-    ASIA_SEOUL("Asia/Seoul"),
-    ASIA_SHANGHAI("Asia/Shanghai"),
-    ASIA_SINGAPORE("Asia/Singapore"),
-    ASIA_SREDNEKOLYMSK("Asia/Srednekolymsk"),
-    ASIA_TAIPEI("Asia/Taipei"),
-    ASIA_TASHKENT("Asia/Tashkent"),
-    ASIA_TBILISI("Asia/Tbilisi"),
-    ASIA_TEHRAN("Asia/Tehran"),
-    ASIA_THIMPHU("Asia/Thimphu"),
-    ASIA_TOKYO("Asia/Tokyo"),
-    ASIA_TOMSK("Asia/Tomsk"),
-    ASIA_ULAANBAATAR("Asia/Ulaanbaatar"),
-    ASIA_URUMQI("Asia/Urumqi"),
-    ASIA_UST_NERA("Asia/Ust-Nera"),
-    ASIA_VLADIVOSTOK("Asia/Vladivostok"),
-    ASIA_YAKUTSK("Asia/Yakutsk"),
-    ASIA_YEKATERINBURG("Asia/Yekaterinburg"),
-    ASIA_YEREVAN("Asia/Yerevan"),
-
-    ATLANTIC_AZORES("Atlantic/Azores"),
-    ATLANTIC_BERMUDA("Atlantic/Bermuda"),
-    ATLANTIC_CANARY("Atlantic/Canary"),
-    ATLANTIC_CAPE_VERDE("Atlantic/Cape_Verde"),
-    ATLANTIC_FAROE("Atlantic/Faroe"),
-    ATLANTIC_MADEIRA("Atlantic/Madeira"),
-    ATLANTIC_REYKJAVIK("Atlantic/Reykjavik"),
-    ATLANTIC_SOUTH_GEORGIA("Atlantic/South_Georgia"),
-    ATLANTIC_STANLEY("Atlantic/Stanley"),
-
-    AUSTRALIA_ADELAIDE("Australia/Adelaide"),
-    AUSTRALIA_BRISBANE("Australia/Brisbane"),
-    AUSTRALIA_BROKEN_HILL("Australia/Broken_Hill"),
-    AUSTRALIA_CURRIE("Australia/Currie"),
-    AUSTRALIA_DARWIN("Australia/Darwin"),
-    AUSTRALIA_EUCLA("Australia/Eucla"),
-    AUSTRALIA_HOBART("Australia/Hobart"),
-    AUSTRALIA_LINDEMAN("Australia/Lindeman"),
-    AUSTRALIA_LORD_HOWE("Australia/Lord_Howe"),
-    AUSTRALIA_MELBOURNE("Australia/Melbourne"),
-    AUSTRALIA_PERTH("Australia/Perth"),
-    AUSTRALIA_SYDNEY("Australia/Sydney"),
-    GMT("GMT"),
-    EUROPE_AMSTERDAM("Europe/Amsterdam"),
-    EUROPE_ANDORRA("Europe/Andorra"),
-    EUROPE_ASTRAKHAN("Europe/Astrakhan"),
-    EUROPE_ATHENS("Europe/Athens"),
-    EUROPE_BELGRADE("Europe/Belgrade"),
-    EUROPE_BERLIN("Europe/Berlin"),
-    EUROPE_BRUSSELS("Europe/Brussels"),
-    EUROPE_BUCHAREST("Europe/Bucharest"),
-    EUROPE_BUDAPEST("Europe/Budapest"),
-    EUROPE_CHISINAU("Europe/Chisinau"),
-    EUROPE_COPENHAGEN("Europe/Copenhagen"),
-    EUROPE_DUBLIN("Europe/Dublin"),
-    EUROPE_GIBRALTAR("Europe/Gibraltar"),
-    EUROPE_HELSINKI("Europe/Helsinki"),
-    EUROPE_ISTANBUL("Europe/Istanbul"),
-    EUROPE_KALININGRAD("Europe/Kaliningrad"),
-    EUROPE_KIEV("Europe/Kiev"),
-    EUROPE_KIROV("Europe/Kirov"),
-    EUROPE_LISBON("Europe/Lisbon"),
-    EUROPE_LONDON("Europe/London"),
-    EUROPE_LUXEMBOURG("Europe/Luxembourg"),
-    EUROPE_MADRID("Europe/Madrid"),
-    EUROPE_MALTA("Europe/Malta"),
-    EUROPE_MINSK("Europe/Minsk"),
-    EUROPE_MONACO("Europe/Monaco"),
-    EUROPE_MOSCOW("Europe/Moscow"),
-    EUROPE_OSLO("Europe/Oslo"),
-    EUROPE_PARIS("Europe/Paris"),
-    EUROPE_PRAGUE("Europe/Prague"),
-    EUROPE_RIGA("Europe/Riga"),
-    EUROPE_ROME("Europe/Rome"),
-    EUROPE_SAMARA("Europe/Samara"),
-    EUROPE_SIMFEROPOL("Europe/Simferopol"),
-    EUROPE_SOFIA("Europe/Sofia"),
-    EUROPE_STOCKHOLM("Europe/Stockholm"),
-    EUROPE_TALLINN("Europe/Tallinn"),
-    EUROPE_TIRANE("Europe/Tirane"),
-    EUROPE_ULYANOVSK("Europe/Ulyanovsk"),
-    EUROPE_UZHGOROD("Europe/Uzhgorod"),
-    EUROPE_VIENNA("Europe/Vienna"),
-    EUROPE_VILNIUS("Europe/Vilnius"),
-    EUROPE_VOLGOGRAD("Europe/Volgograd"),
-    EUROPE_WARSAW("Europe/Warsaw"),
-    EUROPE_ZAPOROZHYE("Europe/Zaporozhye"),
-    EUROPE_ZURICH("Europe/Zurich"),
-
-    INDIAN_CHAGOS("Indian/Chagos"),
-    INDIAN_CHRISTMAS("Indian/Christmas"),
-    INDIAN_COCOS("Indian/Cocos"),
-    INDIAN_KERGUELEN("Indian/Kerguelen"),
-    INDIAN_MAHE("Indian/Mahe"),
-    INDIAN_MALDIVES("Indian/Maldives"),
-    INDIAN_MAURITIUS("Indian/Mauritius"),
-    INDIAN_REUNION("Indian/Reunion"),
-    PACIFIC_APIA("Pacific/Apia"),
-    PACIFIC_AUCKLAND("Pacific/Auckland"),
-    PACIFIC_BOUGAINVILLE("Pacific/Bougainville"),
-    PACIFIC_CHATHAM("Pacific/Chatham"),
-    PACIFIC_CHUUK("Pacific/Chuuk"),
-    PACIFIC_EASTER("Pacific/Easter"),
-    PACIFIC_EFATE("Pacific/Efate"),
-    PACIFIC_ENDERBURY("Pacific/Enderbury"),
-    PACIFIC_FAKAOFO("Pacific/Fakaofo"),
-    PACIFIC_FIJI("Pacific/Fiji"),
-    PACIFIC_FUNAFUTI("Pacific/Funafuti"),
-    PACIFIC_GALAPAGOS("Pacific/Galapagos"),
-    PACIFIC_GAMBIER("Pacific/Gambier"),
-    PACIFIC_GUADALCANAL("Pacific/Guadalcanal"),
-    PACIFIC_GUAM("Pacific/Guam"),
-    PACIFIC_HONOLULU("Pacific/Honolulu"),
-    PACIFIC_KIRITIMATI("Pacific/Kiritimati"),
-    PACIFIC_KOSRAE("Pacific/Kosrae"),
-    PACIFIC_KWAJALEIN("Pacific/Kwajalein"),
-    PACIFIC_MAJURO("Pacific/Majuro"),
-    PACIFIC_MARQUESAS("Pacific/Marquesas"),
-    PACIFIC_NAURU("Pacific/Nauru"),
-    PACIFIC_NIUE("Pacific/Niue"),
-    PACIFIC_NORFOLK("Pacific/Norfolk"),
-    PACIFIC_NOUMEA("Pacific/Noumea"),
-    PACIFIC_PAGO_PAGO("Pacific/Pago_Pago"),
-    PACIFIC_PALAU("Pacific/Palau"),
-    PACIFIC_PITCAIRN("Pacific/Pitcairn"),
-    PACIFIC_POHNPEI("Pacific/Pohnpei"),
-    PACIFIC_PORT_MORESBY("Pacific/Port_Moresby"),
-    PACIFIC_RAROTONGA("Pacific/Rarotonga"),
-    PACIFIC_TAHITI("Pacific/Tahiti"),
-    PACIFIC_TARAWA("Pacific/Tarawa"),
-    PACIFIC_TONGATAPU("Pacific/Tongatapu"),
-    PACIFIC_WAKE("Pacific/Wake"),
-    PACIFIC_WALLIS("Pacific/Wallis");
-
-    private String identifier;
-
-    TimeZone(String identifier) {
-        this.identifier = identifier;
-    }
-
-    @Override
-    public String toString() {
-        return identifier;
-    }
-}
diff --git a/buildSrc/src/main/java/org/grails/airtable/UserLocale.java 
b/buildSrc/src/main/java/org/grails/airtable/UserLocale.java
deleted file mode 100644
index dc278e53492..00000000000
--- a/buildSrc/src/main/java/org/grails/airtable/UserLocale.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2017-2022 original authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.grails.airtable;
-
-/**
- * @author Sergio del Amo
- * @since 1.0.0
- */
-public enum UserLocale {
-    AF("af", "Afrikaans", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'af'), 
'LLLL') => Woensdag, 8 Junie 2016 20:22"),
-    AR_MA("ar-ma", "Moroccan Arabic", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'ar-ma'), 'LLLL') => الأربعاء 8 يونيو 2016 20:22"),
-    AR_SA("ar-sa","Arabic (Saudi Arabia)","DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'ar-sa'), 'LLLL') => الأربعاء ٨ يونيو ٢٠١٦ ٢٠:٢٢"),
-    AR_TN("ar-tn", "Tunisian Arabic", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'ar-tn'), 'LLLL') => الأربعاء 8 جوان 2016 20:22"),
-    AR("ar","Arabic","DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ar'), 'LLLL') 
=> الأربعاء ٨ حزيران يونيو ٢٠١٦ ٢٠:٢٢"),
-    AZ("az","Azerbaijani", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'az'), 
'LLLL') => Çərşənbə, 8 iyun 2016 20:22"),
-    BE("be","Belarusian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'be'), 
'LLLL') => серада, 8 чэрвеня 2016 г., 20:22"),
-    BG("bg","Bulgarian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'bg'), 
'LLLL') => сряда, 8 юни 2016 20:22"),
-    BN("bn","Bengali","DATETIME_FORMAT(SET_LOCALE({Date Field}, 'bn'), 'LLLL') 
=> বুধবার, ৮ জুন ২০১৬, রাত ৮:২২ সময়"),
-    BO("bo","Tibetan", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'bo'), 
'LLLL') => གཟའ་ལྷག་པ་, ༨ ཟླ་བ་དྲུག་པ ༢༠༡༦, མཚན་མོ ༨:༢༢"),
-    BR("br","Breton","DATETIME_FORMAT(SET_LOCALE({Date Field}, 'br'), 'LLLL') 
=> Merc'her, 8 a viz Mezheven 2016 8e22 PM"),
-    BS("bs", "Bosnian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'bs'), 
'LLLL') => srijeda, 8. juni 2016 20:22"),
-    CA("ca","Catalan", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ca'), 
'LLLL') => dimecres 8 juny 2016 20:22"),
-    CS("cs","Czech", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'cs'), 'LLLL') 
=> středa 8. červen 2016 20:22"),
-    CV("cv", "Chuvash", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'cv'), 
'LLLL') => юнкун, 2016 ҫулхи ҫӗртме уйӑхӗн 8-мӗшӗ, 20:22"),
-    CY("cy", "Welsh", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'cy'), 'LLLL') 
=> Dydd Mercher, 8 Mehefin 2016 20:22"),
-    DA("da","Danish", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'da'), 'LLLL') 
=> onsdag d. 8. juni 2016 20:22"),
-    DE_AT("de-at","Austrian German", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'de-at'), 'LLLL') => Dienstag, 12. Jänner 2016 18:48"),
-    DE("de","German", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'de'), 'LLLL') 
=> Dienstag, 12. Januar 2016 18:48"),
-    EL("el","Modern Greek", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'el'), 
'LLLL') => Τετάρτη, 8 Ιουνίου 2016 8:22 ΜΜ"),
-    EN_AU("en-au","Australian English", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'en-au'), 'LLL') => 8 June 2016 8:22 PM"),
-    EN_CA("en-ca","Canadian English", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'en-ca'), 'LLL') => 8 June, 2016 8:22 PM"),
-    EN_GB("en-gb","British English", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'en-gb'), 'LLL') => 8 June 2016 20:22"),
-    EN_IE("en-ie","Irish English", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'en-ie'), 'LLL') => June 8, 2016 8:22 PM"),
-    EN_NZ("en-nz","New Zealand English", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'en-nz'), 'LLL') => June 8, 2016 8:22 PM"),
-    EO("eo","Esperanto", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'eo'), 
'LLLL') => Merkredo, la 8-an de junio, 2016 20:22"),
-    ES("es","Spanish", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'es'), 
'LLLL') => Miércoles, 8 de Junio de 2016 20:22"),
-    ET("et","Estonian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'et'), 
'LLLL') => kolmapäev, 8. juuni 2016 20:22"),
-    EU("eu","Euskara (Basque)", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'eu'), 'LLLL') => asteazkena, 2016ko ekainaren 8a 20:22"),
-    FA("fa","Persian (Farsi)", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'fa'), 'LLLL') => چهارشنبه، ۸ ژوئن ۲۰۱۶ ۲۰:۲۲"),
-    FI("fi","Finnish", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'fi'), 
'LLLL') => keskiviikko, 8. kesäkuuta 2016, klo 20.22"),
-    FO("fo","Faroese", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'fo'), 
'LLLL') => mikudagur 8. juni, 2016 20:22"),
-    FR_CA("fr-ca","Canadian French", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'fr-ca'), 'LLLL') => mercredi 8 juin 2016 20:22"),
-    FR_CH("fr-ch","Swiss French", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'fr-ch'), 'LLLL') => mercredi 8 juin 2016 20:22"),
-    FR("fr","French", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'fr'), 'LLLL') 
=> mercredi 8 juin 2016 20:22"),
-    FY("fy","Frisian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'fy'), 
'LLLL') => woansdei 8 juny 2016 20:22"),
-    GL("gl","Galician", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'gl'), 
'LLLL') => Mércores 8 Xuño 2016 20:22"),
-    HE("he","Hebrew", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'he'), 'LLLL') 
=> רביעי, 8 ביוני 2016 20:22"),
-    HI("hi","Hindi", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'hi'), 'LLLL') 
=> बुधवार, ८ जून २०१६, रात ८:२२ बजे"),
-    HR("hr","Hrvatski (Croatian)", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'hr'), 'LLLL') => 2016. június 8., szerda 20:22"),
-    HU("hu","Hungarian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'hu'), 
'LLLL') => 2016. június 8., szerda 20:22"),
-    HY_AM("hy-am","Armenian (Hayeren)", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'hy-am'), 'LLLL') => չորեքշաբթի, 8 հունիսի 2016 թ., 20:22"),
-    ID("id","Bahasa Indonesia (Indonesian)", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'id'), 'LLLL') => Rabu, 8 Juni 2016 pukul 20.22"),
-    IS("is","Icelandic", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'is'), 
'LLLL') => miðvikudagur, 8. júní 2016 kl. 20:22"),
-    IT("it","Italian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'it'), 
'LLLL') => Mercoledì, 8 giugno 2016 20:22"),
-    JA("ja","Japanese", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ja'), 
'LLLL') => 2016年6月8日午後8時22分 水曜日"),
-    JV("jv","Boso Jowo (Javanese)", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'jv'), 'LLLL') => Rebu, 8 Juni 2016 pukul 20.22"),
-    KA("ka","Georgian (Kartuli)", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'ka'), 'LLLL') => ოთხშაბათი, 8 ივნისი 2016 8:22 PM"),
-    KM("km","Khmer", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'km'), 'LLLL') 
=> ពុធ, 8 មិថុនា 2016 20:22"),
-    KO("ko","Korean", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ko'), 'LLLL') 
=> 2016년 6월 8일 수요일 오후 8시 22분"),
-    LB("lb","Luxembourgish", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'lb'), 
'LLLL') => Mëttwoch, 8. Juni 2016 20:22 Auer"),
-    LT("lt","Lithuanian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'lt'), 
'LLLL') => 2016 m. birželis 8 d., trečiadienis, 20:22 val."),
-    LV("lv","Latvian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'lv'), 
'LLLL') => 2016. gada 8. jūnijs, trešdiena, 20:22"),
-    ME("me","Montenegrin", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'me'), 
'LLLL') => srijeda, 8. jun 2016 20:22"),
-    MK("mk","Macedonian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'mk'), 
'LLLL') => среда, 8 јуни 2016 20:22"),
-    ML("ml","Malayalam (Kairali)", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'ml'), 'LLLL') => ബുധനാഴ്ച, 8 ജൂൺ 2016, രാത്രി 8:22 -നു"),
-    MR("mr","Marathi", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'mr'), 
'LLLL') => बुधवार, ८ जून २०१६, रात्री ८:२२ वाजता"),
-    MS("ms","Bahasa Malaysia (Standard Malay)", 
"DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ms'), 'LLLL') => Rabu, 8 Jun 2016 
pukul 20.22"),
-    MY("my","Burmese", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'my'), 
'LLLL') => ဗုဒ္ဓဟူး ၈ ဇွန် ၂၀၁၆ ၂၀:၂၂"),
-    NB("nb","Norwegian Bokmål", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'nb'), 'LLLL') => onsdag 8. juni 2016 kl. 20.22"),
-    NE("ne","Nepali", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ne'), 'LLLL') 
=> बुधबार, ८ जुन २०१६, रातीको ८:२२ बजे"),
-    NL("nl","Dutch", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'nl'), 'LLLL') 
=> woensdag 8 juni 2016 20:22"),
-    NN("nn","Norwegian Nynorsk", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'nn'), 'LLLL') => onsdag 8 juni 2016 20:22"),
-    PL("pl","Polish", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'pl'), 'LLLL') 
=> środa, 8 czerwca 2016 20:22"),
-    PT_BR("pt-br","Brazilian Portuguese", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'pt-br'), 'LLLL') => Quarta-Feira, 8 de Junho de 2016 às 20:22"),
-    PT("pt","Portuguese", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'pt'), 
'LLLL') => Quarta-Feira, 8 de Junho de 2016 20:22"),
-    RO("ro","Romanian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ro'), 
'LLLL') => miercuri, 8 iunie 2016 20:22"),
-    RU("ru","Russian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ru'), 
'LLLL') => среда, 8 июня 2016 г., 20:22"),
-    SI("si","Sinhala (Sinhalese)", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'si'), 'LLLL') => 2016 ජූනි 8 වැනි බදාදා, ප.ව. 8:22:02"),
-    SK("sk","Slovak", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'sk'), 'LLLL') 
=> streda 8. jún 2016 20:22"),
-    SL("sl","Slovenian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'sl'), 
'LLLL') => sreda, 8. junij 2016 20:22"),
-    SQ("sq","Albanian (Shqip)", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 
'sq'), 'LLLL') => E Mërkurë, 8 Qershor 2016 20:22"),
-    SR_CYRL("sr-cyrl","Serbian Cyrillic", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'sr-cyrl'), 'LLLL') => среда, 8. јун 2016 20:22"),
-    SR("sr","Serbian Latin", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'sr'), 
'LLLL') => sreda, 8. jun 2016 20:22"),
-    SV("sv","Swedish", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'sv'), 
'LLLL') => onsdag 8 juni 2016 20:22"),
-    TA("ta","Tamil", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'ta'), 'LLLL') 
=> புதன்கிழமை, 8 ஜூன் 2016, 20:22"),
-    TH("th","Thai", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'th'), 'LLLL') 
=> วันพุธที่ 8 มิถุนายน 2016 เวลา 20 นาฬิกา 22 นาที"),
-    TL_PH("tl-ph","Tagalog/Filipino", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'tl-ph'), 'LLLL') => Miyerkules, Hunyo 08, 2016 20:22"),
-    TR("tr","Turkish", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'tr'), 
'LLLL') => Çarşamba, 8 Haziran 2016 20:22"),
-    TZL("tzl","Talossan", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'tzl'), 
'LLLL') => Márcuri, li 8. Gün dallas 2016 20.22"),
-    TZM_LATN("tzm-latn","Morocco Central Atlas Tamaziɣt (Amazigh/Berber) in 
Latin", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'tzm-latn'), 'LLLL') => akras 
8 ywnyw 2016 20:22"),
-    TZM("tzm","Morocco Central Atlas Tamaziɣt (Amazigh/Berber)", 
"DATETIME_FORMAT(SET_LOCALE({Date Field}, 'tzm'), 'LLLL') => ⴰⴽⵔⴰⵙ 8 ⵢⵓⵏⵢⵓ 2016 
20:22"),
-    UK("uk","Ukrainian", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'uk'), 
'LLLL') => середа, 8 червня 2016 р., 20:22"),
-    UZ("uz","Uzbek", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'uz'), 'LLLL') 
=> 8 июнь 2016, Чоршанба 20:22"),
-    VI("vi","Vietnamese", "DATETIME_FORMAT(SET_LOCALE({Date Field}, 'vi'), 
'LLLL') => thứ tư, 8 tháng 6 năm 2016 20:2"),
-    ZH_CN("zh-cn","Simplified Chinese", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'zh-cn'), 'LLLL') => 2016年6月8日星期三晚上8点22分"),
-    ZH_TW("zh-tw","Traditional Chinese", "DATETIME_FORMAT(SET_LOCALE({Date 
Field}, 'zh-tw'), 'LLLL') => 2016年6月8日星期三晚上8點22分");
-
-    private String modifier;
-    private String description;
-    private String example;
-
-    UserLocale(String modifier, String description, String example) {
-     this.modifier = modifier;
-     this.description = description;
-     this.example = example;
-    }
-
-    public String getDescription() {
-     return description;
-    }
-
-    public String getExample() {
-     return example;
-    }
-
-    @Override
-    public String toString() {
-     return modifier;
-    }
-}
diff --git 
a/buildSrc/src/test/groovy/org/grails/airtable/AirtableApiErrorSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/AirtableApiErrorSpec.groovy
deleted file mode 100644
index 01455e0451c..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/AirtableApiErrorSpec.groovy
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.grails.airtable
-
-import io.micronaut.core.beans.BeanIntrospection
-import spock.lang.Specification
-
-class AirtableApiErrorSpec extends Specification {
-
-    void "AirtableApiError is annotated with @Introspected"() {
-        when:
-        BeanIntrospection.getIntrospection(AirtableApiError)
-
-        then:
-        noExceptionThrown()
-    }
-}
diff --git 
a/buildSrc/src/test/groovy/org/grails/airtable/AirtableBaseApiSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/AirtableBaseApiSpec.groovy
deleted file mode 100644
index c599c82f89d..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/AirtableBaseApiSpec.groovy
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.grails.airtable
-
-import io.micronaut.context.ApplicationContext
-import io.micronaut.context.annotation.Requires
-import io.micronaut.http.annotation.Controller
-import io.micronaut.http.annotation.Get
-import io.micronaut.http.annotation.PathVariable
-import io.micronaut.inject.qualifiers.Qualifiers
-import io.micronaut.runtime.server.EmbeddedServer
-import spock.lang.AutoCleanup
-import spock.lang.Shared
-import spock.lang.Ignore
-
-class AirtableBaseApiSpec extends ApplicationContextSpecification {
-
-    @Override
-    Map<String, Object> getConfiguration() {
-        println "http://localhost:$mockAirtablePort";
-        super.configuration + [
-                'airtable.url': 
"http://localhost:$mockAirtablePort".toString(),
-                'airtable.api-key': 'secret',
-                'airtable.bases.2020.id': 'appxxxyyy',
-        ]
-    }
-
-    @AutoCleanup
-    @Shared
-    EmbeddedServer mockAirtable = ApplicationContext.run(EmbeddedServer, 
['spec.name': 'Airtable',
-                                                                          
'micronaut.server.port': mockAirtablePort])
-
-    @Ignore
-    void "bean of type AirtableBaseApi named 2020 exists"() {
-        when:
-        AirtableBaseApi api = applicationContext.getBean(AirtableBaseApi, 
Qualifiers.byName("2020"))
-
-        then:
-        noExceptionThrown()
-
-        when:
-        MicronautAirtable micronautAirtable = new MicronautAirtable(api)
-        List<Event> events = micronautAirtable.fetchMicronautEvents()
-
-        then:
-        events
-        events.each { Event event ->
-            assert event.name
-            assert event.date
-            println event.toString()
-        }
-    }
-
-    @Requires(property = 'spec.name', value = 'Airtable')
-    @Controller
-    static class AirtableController {
-
-        @Get("/v0/appxxxyyy/{table}")
-        RecordList list(@PathVariable String table) {
-            if (table == MicronautAirtable.TABLE_PRACTICE_AREAS) {
-                RecordList recordList = new RecordList()
-                recordList.records = new ArrayList<>()
-                Record record = new Record()
-                record.id = "recaaa"
-                record.fields = ["Name": "MICRONAUT"]
-                record.createdTime = "2018-05-08T16:21:17.000Z"
-                recordList.records << record
-                return recordList
-            } else if (table == MicronautAirtable.TABLE_FOCUS) {
-                RecordList recordList = new RecordList()
-                recordList.records = new ArrayList<>()
-                Record record = new Record()
-                record.id = "recbbb"
-                record.fields = ["name": "Introduction to Micronaut 2.0", 
"category": "meetup", "events": true, "status": "scheduled (confirmed)", 
"link": 
"https://www.meetup.com/Stuttgart-Cloud-Foundry-Meetup/events/271983604/";, 
"practice area": ["recaaa"], "start/publish date": "2020-07-30", "time": "5:45 
to 8:45 pm GMT+2", "speaker(s)": ["recccc"], "location": "online", "Meetup": 
"Stuttgart Cloud Foundry Meetup", "month": "07 July", "quarter": "3"]
-                record.createdTime = "2020-07-17T15:57:31.000Z"
-                recordList.records << record
-                return recordList
-            } else if (table == MicronautAirtable.TABLE_SMES) {
-                RecordList recordList = new RecordList()
-                recordList.records = new ArrayList<>()
-                Record record = new Record()
-                record.id = "recccc"
-                record.fields = ["Name":"Sergio del Amo Caballero"]
-                record.createdTime = "2020-07-17T15:57:31.000Z"
-                recordList.records << record
-                return recordList
-            }
-            return new RecordList()
-        }
-    }
-}
diff --git 
a/buildSrc/src/test/groovy/org/grails/airtable/AirtableBaseConfigurationSpec.groovy
 
b/buildSrc/src/test/groovy/org/grails/airtable/AirtableBaseConfigurationSpec.groovy
deleted file mode 100644
index e683a669609..00000000000
--- 
a/buildSrc/src/test/groovy/org/grails/airtable/AirtableBaseConfigurationSpec.groovy
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.grails.airtable
-
-import io.micronaut.inject.qualifiers.Qualifiers
-
-class AirtableBaseConfigurationSpec extends ApplicationContextSpecification {
-    @Override
-    Map<String, Object> getConfiguration() {
-        super.configuration + [
-                'airtable.api-key': 'secret',
-                'airtable.bases.2022.id': 'appxxxyyy',
-        ]
-    }
-
-    void "bean of type AirtableBaseConfiguration named 2022 exists"() {
-        expect:
-        applicationContext.containsBean(AirtableBaseConfiguration, 
Qualifiers.byName("2022"))
-    }
-}
diff --git 
a/buildSrc/src/test/groovy/org/grails/airtable/AirtableConfigurationSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/AirtableConfigurationSpec.groovy
deleted file mode 100644
index 958b00b62f0..00000000000
--- 
a/buildSrc/src/test/groovy/org/grails/airtable/AirtableConfigurationSpec.groovy
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.grails.airtable
-
-class AirtableConfigurationSpec extends ApplicationContextSpecification {
-    @Override
-    Map<String, Object> getConfiguration() {
-        super.configuration + [
-                'airtable.api-key': 'secret',
-                'airtable.bases.2022.id': 'appxxxyyy',
-        ]
-    }
-
-    void "bean of type AirtableConfiguration exists"() {
-        expect:
-        applicationContext.containsBean(AirtableConfiguration)
-
-        and:
-        applicationContext.getBean(AirtableConfiguration).getApiVersion() == 
'v0'
-
-        and:
-        applicationContext.getBean(AirtableConfiguration).getApiKey()
-    }
-}
diff --git 
a/buildSrc/src/test/groovy/org/grails/airtable/AirtableErrorSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/AirtableErrorSpec.groovy
deleted file mode 100644
index 493e1a8c00a..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/AirtableErrorSpec.groovy
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.grails.airtable
-
-import io.micronaut.core.beans.BeanIntrospection
-import spock.lang.Specification
-
-class AirtableErrorSpec extends Specification {
-    void "AirtableError is annotated with @Introspected"() {
-        when:
-        BeanIntrospection.getIntrospection(AirtableError)
-
-        then:
-        noExceptionThrown()
-    }
-}
diff --git 
a/buildSrc/src/test/groovy/org/grails/airtable/ApplicationContextSpecification.groovy
 
b/buildSrc/src/test/groovy/org/grails/airtable/ApplicationContextSpecification.groovy
deleted file mode 100644
index d9305f05ad3..00000000000
--- 
a/buildSrc/src/test/groovy/org/grails/airtable/ApplicationContextSpecification.groovy
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.grails.airtable
-
-import io.micronaut.context.ApplicationContext
-import io.micronaut.core.io.socket.SocketUtils
-import spock.lang.AutoCleanup
-import spock.lang.Shared
-import spock.lang.Specification
-
-abstract class ApplicationContextSpecification extends Specification 
implements ConfigurationFixture {
-
-    @Shared
-    int mockAirtablePort = SocketUtils.findAvailableTcpPort()
-
-    @AutoCleanup
-    @Shared
-    ApplicationContext applicationContext = 
ApplicationContext.run(configuration)
-}
diff --git a/buildSrc/src/test/groovy/org/grails/airtable/CellFormatSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/CellFormatSpec.groovy
deleted file mode 100644
index 04711405800..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/CellFormatSpec.groovy
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.grails.airtable
-
-import spock.lang.Specification
-
-class CellFormatSpec extends Specification {
-
-    void "CellFormat::toString() returns lowercase string"() {
-        expect:
-        CellFormat.JSON.toString() == 'json'
-
-        and:
-        CellFormat.STRING.toString() == 'string'
-    }
-}
diff --git 
a/buildSrc/src/test/groovy/org/grails/airtable/ConfigurationFixture.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/ConfigurationFixture.groovy
deleted file mode 100644
index 978b4a4316e..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/ConfigurationFixture.groovy
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.grails.airtable
-
-trait ConfigurationFixture {
-
-    Map<String, Object> getConfiguration() {
-        Map<String, Object> m = [:]
-        if (specName) {
-            m['spec.name'] = specName
-        }
-        m
-    }
-
-    String getSpecName() {
-        null
-    }
-
-}
\ No newline at end of file
diff --git a/buildSrc/src/test/groovy/org/grails/airtable/DirectionSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/DirectionSpec.groovy
deleted file mode 100644
index 3c3f1a03d22..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/DirectionSpec.groovy
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.grails.airtable
-
-import spock.lang.Specification
-
-class DirectionSpec extends Specification {
-
-    void "Direction::toString() returns lowercase string"() {
-        expect:
-        Direction.ASC.toString() == 'asc'
-
-        and:
-        Direction.DESC.toString() == 'desc'
-    }
-}
diff --git a/buildSrc/src/test/groovy/org/grails/airtable/Event.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/Event.groovy
deleted file mode 100644
index ff5d6226437..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/Event.groovy
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.grails.airtable
-
-import edu.umd.cs.findbugs.annotations.Nullable
-import groovy.transform.CompileStatic
-import groovy.transform.ToString
-
-import java.time.LocalDate
-
-@ToString
-@CompileStatic
-class Event {
-    String name
-    LocalDate date
-    List<String> speakers
-
-    @Nullable
-    String link
-}
diff --git 
a/buildSrc/src/test/groovy/org/grails/airtable/MicronautAirtable.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/MicronautAirtable.groovy
deleted file mode 100644
index 15ea266767d..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/MicronautAirtable.groovy
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.grails.airtable
-
-import groovy.transform.CompileStatic
-import groovy.transform.Memoized
-
-import java.time.LocalDate
-
-@CompileStatic
-class MicronautAirtable {
-
-    public static final String FIELD_NAME = 'Name'
-    public static final String FIELD_LINK = 'link'
-    public static final String FIELD_NAME_LOWERCASE = 'name'
-    public static final String FIELD_DATE = 'start/publish date'
-    public static final String FIELD_SPEAKERS = 'speaker(s)'
-    public static final String FIELD_PRACTICE_AREA = 'practice area'
-    public static final String TABLE_PRACTICE_AREAS = 'Practice Areas'
-    public static final String TABLE_FOCUS = 'Focus'
-    public static final String TABLE_SMES = 'SMEs'
-
-    AirtableBaseApi api
-
-    MicronautAirtable(AirtableBaseApi api) {
-        this.api = api
-    }
-
-    @Memoized
-    List<Event> fetchEvents(String practiceId) {
-        List<Record> records = api.list(TABLE_FOCUS,
-                null,
-                null,
-                null,
-                null,
-                null,
-                "All Upcoming Events",
-                null,
-                null,
-                null).records
-        records.findAll { Record record ->
-            (record.fields[FIELD_PRACTICE_AREA] && 
(record.fields[FIELD_PRACTICE_AREA] as List<String>).contains(practiceId))
-        }.collect { Record record ->
-            String d = record.fields[FIELD_DATE]
-            Event e = new Event()
-            e.link = record.fields[FIELD_LINK]
-            e.name = record.fields[FIELD_NAME_LOWERCASE]
-            e.date = LocalDate.of(d.substring(0, 4) as Integer , 
d.substring(5, 7) as Integer, d.substring(8, 10) as Integer)
-            e.speakers = record.fields[FIELD_SPEAKERS].collect { 
speakerName(it as String) }
-            e
-        }
-    }
-
-    @Memoized
-    String speakerName(String speakerId) {
-        List<Record> records = api.list(TABLE_SMES,
-                [FIELD_NAME],
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null).records
-        records.find { Record record ->
-            record.id == speakerId
-        }?.fields[FIELD_NAME] as String
-    }
-
-    @Memoized
-    String practiceId(String practiceName) {
-        List<Record> practiceAreaRecords = api.list(TABLE_PRACTICE_AREAS,
-                [FIELD_NAME],
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null).records
-        practiceAreaRecords.find { Record record ->
-            (record.fields[FIELD_NAME] as 
String).equalsIgnoreCase(practiceName)
-        }?.id
-    }
-}
diff --git a/buildSrc/src/test/groovy/org/grails/airtable/RecordListSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/RecordListSpec.groovy
deleted file mode 100644
index 3c8a6e6dcdd..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/RecordListSpec.groovy
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.grails.airtable
-
-import io.micronaut.core.beans.BeanIntrospection
-import spock.lang.Specification
-
-class RecordListSpec extends Specification {
-    void "RecordList is annotated with @Introspected"() {
-        when:
-        BeanIntrospection.getIntrospection(RecordList)
-
-        then:
-        noExceptionThrown()
-    }
-}
diff --git a/buildSrc/src/test/groovy/org/grails/airtable/RecordSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/RecordSpec.groovy
deleted file mode 100644
index b468f077911..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/RecordSpec.groovy
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.grails.airtable
-
-import io.micronaut.core.beans.BeanIntrospection
-import spock.lang.Specification
-
-class RecordSpec extends Specification {
-
-    void "Record is annotated with @Introspected"() {
-        when:
-        BeanIntrospection.getIntrospection(Record)
-
-        then:
-        noExceptionThrown()
-    }
-}
diff --git a/buildSrc/src/test/groovy/org/grails/airtable/SortSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/SortSpec.groovy
deleted file mode 100644
index 155eb32bc42..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/SortSpec.groovy
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.grails.airtable
-
-import io.micronaut.core.beans.BeanIntrospection
-import spock.lang.Specification
-
-class SortSpec extends Specification {
-
-    void "Sort is annotated with @Introspected"() {
-        when:
-        BeanIntrospection.getIntrospection(Sort)
-
-        then:
-        noExceptionThrown()
-    }
-
-    void "sort default direction is asc"() {
-        expect:
-        new Sort().direction == Direction.ASC
-    }
-}
diff --git a/buildSrc/src/test/groovy/org/grails/airtable/TimeZoneSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/TimeZoneSpec.groovy
deleted file mode 100644
index 64f56c81136..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/TimeZoneSpec.groovy
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.grails.airtable
-
-import spock.lang.Specification
-
-class TimeZoneSpec extends Specification {
-
-    void "TimeZone::toString() returns identifier in regular case"() {
-        expect:
-        TimeZone.PACIFIC_TAHITI.toString() == 'Pacific/Tahiti'
-    }
-}
diff --git a/buildSrc/src/test/groovy/org/grails/airtable/UserLocaleSpec.groovy 
b/buildSrc/src/test/groovy/org/grails/airtable/UserLocaleSpec.groovy
deleted file mode 100644
index 4c33d474a1d..00000000000
--- a/buildSrc/src/test/groovy/org/grails/airtable/UserLocaleSpec.groovy
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.grails.airtable
-
-import spock.lang.Specification
-
-class UserLocaleSpec extends Specification {
-
-    void "UserLocale::toString() returns modifier in lowercase"() {
-        expect:
-        UserLocale.BS.toString() == 'bs'
-    }
-}

Reply via email to