diff --git a/src/components/dictionaries/DictionaryCard.vue b/src/components/dictionaries/DictionaryCard.vue new file mode 100644 index 0000000..f2a46bc --- /dev/null +++ b/src/components/dictionaries/DictionaryCard.vue @@ -0,0 +1,287 @@ + + + + + Dictionaries + + + + + + + + + + + Manage Dictionaries + + + + No dictionaries found. + Loading dictionaries data. Please wait. + + + + {{ slotProps.data.write_only ? 'Yes' : 'No' }} + + + + + {{ $d(slotProps.data.created_at, 'long') }} + + + + + {{ $d(slotProps.data.updated_at, 'long') }} + + + + + + + + + + + + + + + + + + Are you sure you want to delete {{ dictionary_selected.name }}? + + + + + Deleting dictionary and activating new version... + + This may take a few seconds + + + + + + + + diff --git a/src/components/dictionaries/DictionaryItemsCard.vue b/src/components/dictionaries/DictionaryItemsCard.vue new file mode 100644 index 0000000..36de049 --- /dev/null +++ b/src/components/dictionaries/DictionaryItemsCard.vue @@ -0,0 +1,410 @@ + + + + + + Name + + {{ nameError }} + + Must start with a letter and contain only letters, numbers, underscores, and spaces + + + + + + Write-only (items are not readable) + + + + No items defined. + Loading dictionary items. Please wait... + + + Manage Items + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creating dictionary and activating version... + + + + + + + Are you sure you want to delete {{ item_selected.item_key }}? + + + + + + + diff --git a/src/components/dictionaries/dictionary.interface.ts b/src/components/dictionaries/dictionary.interface.ts new file mode 100644 index 0000000..39ccfdd --- /dev/null +++ b/src/components/dictionaries/dictionary.interface.ts @@ -0,0 +1,14 @@ +import type Identifiable from '@/components/base/type'; + +export interface DictionaryItemEntity extends Identifiable { + item_key: string; + item_value: string; + op: string; +} + +export interface DictionaryEntity extends Identifiable { + name: string; + write_only: boolean; + items: DictionaryItemEntity[]; + service_id: string; +} diff --git a/src/components/dictionaries/dictionary.service.ts b/src/components/dictionaries/dictionary.service.ts new file mode 100644 index 0000000..6f8820e --- /dev/null +++ b/src/components/dictionaries/dictionary.service.ts @@ -0,0 +1,191 @@ +import APIService from '../base/api'; +import type { DictionaryEntity, DictionaryItemEntity } from './dictionary.interface'; + +export type APIResponse = [null, null] | [Error]; + +export default class DictionaryAPIService extends APIService { + constructor(service_id: string, token: string) { + super(service_id, token); + } + + /** + * Get all dictionaries for a specific version + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary/ + * GET /service/{service_id}/version/{version_id}/dictionary + */ + async getDictionaries(version: number): Promise { + try { + const response = await this.wsClient.get(`service/${this.service_id}/version/${version}/dictionary`); + return response.data; + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Get all items in a dictionary + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary-item/ + * GET /service/{service_id}/dictionary/{dictionary_id}/items + */ + async getDictionaryItems(dictionary_id: string): Promise { + try { + const response = await this.wsClient.get(`service/${this.service_id}/dictionary/${dictionary_id}/items`); + return response.data; + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Create a new dictionary + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary/ + * POST /service/{service_id}/version/{version_id}/dictionary + */ + async createDictionary(version: number, name: string, write_only: boolean = false): Promise { + try { + const dto = JSON.stringify({ name, write_only }); + const response = await this.wsClient.post(`service/${this.service_id}/version/${version}/dictionary`, dto); + return response.data; + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Update a dictionary + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary/ + * PUT /service/{service_id}/version/{version_id}/dictionary/{dictionary_name} + */ + async updateDictionary( + version: number, + dictionary_name: string, + new_name: string, + write_only?: boolean, + ): Promise { + try { + const dto: { name: string; write_only?: boolean } = { name: new_name }; + if (write_only !== undefined) { + dto.write_only = write_only; + } + const response = await this.wsClient.put( + `service/${this.service_id}/version/${version}/dictionary/${encodeURIComponent(dictionary_name)}`, + JSON.stringify(dto), + ); + return response.data; + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Delete a dictionary + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary/ + * DELETE /service/{service_id}/version/{version_id}/dictionary/{dictionary_name} + */ + async deleteDictionary(version: number, dictionary_name: string): Promise { + try { + await this.wsClient.delete( + `service/${this.service_id}/version/${version}/dictionary/${encodeURIComponent(dictionary_name)}`, + ); + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Create a dictionary item + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary-item/ + * POST /service/{service_id}/dictionary/{dictionary_id}/item + */ + async createDictionaryItem(dictionary_id: string, item_key: string, item_value: string): Promise { + try { + const dto = JSON.stringify({ item_key, item_value }); + const response = await this.wsClient.post(`service/${this.service_id}/dictionary/${dictionary_id}/item`, dto); + return response.data; + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Update a dictionary item + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary-item/ + * PUT /service/{service_id}/dictionary/{dictionary_id}/item/{item_key} + */ + async updateDictionaryItem( + dictionary_id: string, + item_key: string, + item_value: string, + ): Promise { + try { + const dto = JSON.stringify({ item_value }); + const response = await this.wsClient.put( + `service/${this.service_id}/dictionary/${dictionary_id}/item/${encodeURIComponent(item_key)}`, + dto, + ); + return response.data; + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Delete a dictionary item + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary-item/ + * DELETE /service/{service_id}/dictionary/{dictionary_id}/item/{item_key} + */ + async deleteDictionaryItem(dictionary_id: string, item_key: string): Promise { + try { + await this.wsClient.delete( + `service/${this.service_id}/dictionary/${dictionary_id}/item/${encodeURIComponent(item_key)}`, + ); + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Upsert a dictionary item (create or update) + * https://www.fastly.com/documentation/reference/api/dictionaries/dictionary-item/ + * POST /service/{service_id}/dictionary/{dictionary_id}/item (upsert endpoint) + */ + async upsertDictionaryItem(dictionary_id: string, item_key: string, item_value: string): Promise { + try { + const dto = JSON.stringify({ item_key, item_value }); + const response = await this.wsClient.post(`service/${this.service_id}/dictionary/${dictionary_id}/item`, dto); + return response.data; + } catch (error) { + console.error(error); + throw error; + } + } + + /** + * Batch update dictionary items (create, update, delete) + * This method processes an array of items with operation flags + */ + async updateDictionaryItems(dictionary_id: string, items: DictionaryItemEntity[]): Promise { + try { + for (const item of items) { + if (item.op === 'create') { + await this.createDictionaryItem(dictionary_id, item.item_key, item.item_value); + } else if (item.op === 'update') { + await this.updateDictionaryItem(dictionary_id, item.item_key, item.item_value); + } else if (item.op === 'delete') { + await this.deleteDictionaryItem(dictionary_id, item.item_key); + } + } + } catch (error) { + console.error(error); + throw error; + } + } +} diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 3b3c7ab..192b095 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -12,6 +12,7 @@ import ProgressSpinner from 'primevue/progressspinner'; import SetupCard from '@/components/SetupCard.vue'; import AclsCard from '@/components/acls/AclCard.vue'; +import DictionaryCard from '@/components/dictionaries/DictionaryCard.vue'; import DomaCard from '@/components/domains/DomainCard.vue'; import HistCard from '@/components/project/HistoryCard.vue'; import InfoCard from '@/components/project/InfoCard.vue'; @@ -241,6 +242,7 @@ const vclVersionIsDefined = computed(() => credentialsStore.vclVersionIsDefined. +
+ Deleting dictionary and activating new version... + + This may take a few seconds +