store/cockpit/baseQuery: add cockpit baseQuery
Add a `cockpitBaseQuery` for api calls that need to be made against the `cloudapi` on the osbuild-composer unix-socket. This function adds an extra step of parsing the result and transforming it into JSON. We need to wrap the `cockpit.http.request` call in a Promise rather than async/await because cockpit rejects the http request with two arguments (error & data/body) and we need to handle this appropriately. It is not possible to do this with a try/catch block
This commit is contained in:
parent
8e58548385
commit
6b3b3ea3cc
4 changed files with 91 additions and 3 deletions
67
src/store/cockpit/baseQuery.ts
Normal file
67
src/store/cockpit/baseQuery.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import { BaseQueryFn } from '@reduxjs/toolkit/query';
|
||||
import cockpit from 'cockpit';
|
||||
|
||||
import type { Method, Params, Headers } from './types.js';
|
||||
|
||||
const cockpitApi = cockpit.http('/run/cloudapi/api.socket', {
|
||||
superuser: 'try',
|
||||
});
|
||||
|
||||
export const baseQuery =
|
||||
(
|
||||
{ baseUrl }: { baseUrl: string } = { baseUrl: '' }
|
||||
): BaseQueryFn<
|
||||
{
|
||||
url: string;
|
||||
method?: Method;
|
||||
body?: unknown;
|
||||
params?: Params;
|
||||
headers?: Headers;
|
||||
},
|
||||
// we have to explicitly set the result type as `any`,
|
||||
// since each of the endpoints might have a slightly
|
||||
// different output. Unfortunately, typescript still
|
||||
// complains if we try set the result type as `unknown`
|
||||
// see the above comment
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
any,
|
||||
unknown
|
||||
> =>
|
||||
async (options) => {
|
||||
// we need to wrap this call in a Promise rather than
|
||||
// async/await because cockpit rejects the http request
|
||||
// with two arguments (error & data/body)
|
||||
return new Promise((resolve, reject) => {
|
||||
return cockpitApi
|
||||
.request({
|
||||
path: baseUrl + options.url,
|
||||
body: options.body ?? '',
|
||||
method: options.method ?? 'GET',
|
||||
params: options.params,
|
||||
headers: options.headers,
|
||||
})
|
||||
.then((result) => {
|
||||
resolve({ data: JSON.parse(result) });
|
||||
})
|
||||
.catch(
|
||||
// cockpit rejects the promise with two arguments.
|
||||
// The first argument is the error, the second is the
|
||||
// data object from the `osbuild-composer` error.
|
||||
// This makes typescript unhappy.
|
||||
// @ts-expect-error see above comment
|
||||
(error: { message: string; problem: string }, data: string) => {
|
||||
let body = data;
|
||||
try {
|
||||
body = JSON.parse(body);
|
||||
} finally {
|
||||
reject({
|
||||
problem: error.problem,
|
||||
message: error.message,
|
||||
options,
|
||||
body,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
4
src/store/cockpit/types.ts
Normal file
4
src/store/cockpit/types.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type Params = Record<string, any>;
|
||||
export type Method = 'GET' | 'DELETE' | 'POST' | 'PUT' | 'PATCH'; // We can add more if we need
|
||||
export type Headers = { [name: string]: string };
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
|
||||
import { createApi } from '@reduxjs/toolkit/query/react';
|
||||
|
||||
import { baseQuery } from './cockpit/baseQuery';
|
||||
|
||||
export const emptyCockpitApi = createApi({
|
||||
reducerPath: 'cockpitApi',
|
||||
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
|
||||
tagTypes: ['Composes'],
|
||||
baseQuery: baseQuery({
|
||||
baseUrl: '/api/image-builder-composer/v2',
|
||||
}),
|
||||
endpoints: () => ({}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import type { Method, Headers, Params } from '../../../store/cockpit/types';
|
||||
|
||||
type userinfo = {
|
||||
home: string;
|
||||
};
|
||||
|
||||
type requestOptions = {
|
||||
path: string;
|
||||
method: Method;
|
||||
body: unknown;
|
||||
headers: Headers | undefined;
|
||||
params: Params | undefined;
|
||||
};
|
||||
|
||||
export default {
|
||||
transport: {
|
||||
host: '',
|
||||
|
|
@ -40,6 +49,11 @@ export default {
|
|||
post: (path: string, data: object, headers?: object): string => {
|
||||
return '';
|
||||
},
|
||||
request: (request: requestOptions): Promise<string> => {
|
||||
return new Promise((resolve) => {
|
||||
resolve('');
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue