Skip to content

Commit

Permalink
feature: added command to get storage items
Browse files Browse the repository at this point in the history
  • Loading branch information
ShayElkana committed Nov 2, 2023
1 parent 610a7fa commit 2d09dc2
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 1 deletion.
71 changes: 71 additions & 0 deletions src/commands/code/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Flags } from '@oclif/core';
import { StatusCodes } from 'http-status-codes';

import { AuthenticatedCommand } from 'commands-base/authenticated-command';
import { DynamicChoicesService } from 'services/dynamic-choices-service';
import { PromptService } from 'services/prompt-service';
import { getStorageItemsSearch } from 'services/storage-service';
import { HttpError } from 'types/errors';
import logger from 'utils/logger';

const clientAccountNumberMessage = 'Client account number';
const termMessage = 'Term to search for';

const fetchAndPrintStorageKeyValuesResults = async (appId: number, clientAccountId: number, term: string) => {
const itemsFound = await getStorageItemsSearch(appId, clientAccountId, term);
logger.table(itemsFound.records);
if (itemsFound.hasMoreRecords) {
console.log('There more records, please search for a more specific term.');
}
};

export default class Storage extends AuthenticatedCommand {
static description = 'Get keys and values stored on monday for a specific customer.';

static examples = ['<%= config.bin %> <%= command.id %> -i APP_VERSION_ID'];

static flags = Storage.serializeFlags({
appId: Flags.integer({
char: 'a',
aliases: ['v'],
description: 'Select the app that you wish to retrieve the key for',
}),
clientAccountId: Flags.integer({
char: 'c',
description: `${clientAccountNumberMessage}.`,
}),
term: Flags.string({
char: 't',
description: `${termMessage}.`,
}),
});

public async run(): Promise<void> {
const { flags } = await this.parse(Storage);
let { appId, clientAccountId, term } = flags;
if (!appId) {
appId = await DynamicChoicesService.chooseApp();
}

if (!clientAccountId) {
clientAccountId = await PromptService.promptInputNumber(`${clientAccountNumberMessage}:`, true);
}

if (!term) {
term = await PromptService.promptInput(`${termMessage}:`, true);
}

await fetchAndPrintStorageKeyValuesResults(appId, clientAccountId, term);
try {
this.preparePrintCommand(this, { appId, clientAccountId, term });
} catch (error: unknown) {
if (error instanceof HttpError && error.code === StatusCodes.NOT_FOUND) {
logger.error(`No deployment found for provided app version id - "${appId}"`);
} else {
logger.error(`An unknown error happened while fetching deployment status for app version id - "${appId}"`);
}

process.exit(0);
}
}
}
4 changes: 4 additions & 0 deletions src/consts/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export const getDeploymentSignedUrl = (appVersionId: number): string => {
return `${appVersionIdBaseUrl(appVersionId)}/deployments/signed-url`;
};

export const getStorageItemsSearchUrl = (appId: number, clientAccountId: number, term: string): string => {
return `/api/storage/app/${appId}/account/${clientAccountId}/records?term=${encodeURI(term)}`;
};

export const getLogsStreamForAppVersionIdUrl = (
appVersionId: number,
logsType: LogType,
Expand Down
2 changes: 1 addition & 1 deletion src/services/prompt-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const PromptService = {
},
]);

return res.input;
return Number(res.input);
},

async promptFile(message: string, extensions: string[]) {
Expand Down
17 changes: 17 additions & 0 deletions src/services/schemas/storage-service-schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { z } from 'zod';

import { baseResponseHttpMetaDataSchema } from 'services/schemas/api-service-schemas';

export const appStorageApiRecordsResponseSchema = z.object({
key: z.string(),
value: z.string(),
backendOnly: z.boolean(),
});

export const appStorageApiRecordsSearchResponseSchema = z
.object({
term: z.string(),
records: z.array(appStorageApiRecordsResponseSchema),
hasMoreRecords: z.boolean(),
})
.merge(baseResponseHttpMetaDataSchema);
36 changes: 36 additions & 0 deletions src/services/storage-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getStorageItemsSearchUrl } from 'consts/urls';
import { execute } from 'services/api-service';
import { appStorageApiRecordsSearchResponseSchema } from 'services/schemas/storage-service-schemas';
import { HttpError } from 'types/errors';
import { HttpMethodTypes } from 'types/services/api-service';
import { AppStorageApiRecordsSearchResponseSchema } from 'types/services/storage-service';
import logger from 'utils/logger';
import { appsUrlBuilder } from 'utils/urls-builder';

export const getStorageItemsSearch = async (
appId: number,
clientAccountId: number,
term: string,
): Promise<AppStorageApiRecordsSearchResponseSchema> => {
const DEBUG_TAG = 'get_storage_items_search_url';
try {
const baseSignUrl = getStorageItemsSearchUrl(appId, clientAccountId, term);
const url = appsUrlBuilder(baseSignUrl);
const response = await execute<AppStorageApiRecordsSearchResponseSchema>(
{
url,
headers: { Accept: 'application/json' },
method: HttpMethodTypes.GET,
},
appStorageApiRecordsSearchResponseSchema,
);
return response;
} catch (error: any | HttpError) {
logger.debug(error, DEBUG_TAG);
if (error instanceof HttpError) {
throw error;
}

throw new Error('Failed to build remote location for upload.');
}
};
5 changes: 5 additions & 0 deletions src/types/services/storage-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { z } from 'zod';

import { appStorageApiRecordsSearchResponseSchema } from 'services/schemas/storage-service-schemas';

export type AppStorageApiRecordsSearchResponseSchema = z.infer<typeof appStorageApiRecordsSearchResponseSchema>;

0 comments on commit 2d09dc2

Please sign in to comment.