generic-odata-typescript-client
v4.0.17
Published
template for accessing odata apis, with local typings in constants
Downloads
46
Readme
generic-odata-typescript-client
General usage
You supply the Odata source and resourcepath. Typically in the form of a API and a db schema + table/view and use these as part of your GOTCConfig
interface ODATARESOURCE {
'api/v1': string;
'api/v2': string;
}
interface ODATARESOURCEPATH {
'Controller1': string;
'Controller2': string;
'Controller3': string;
}
export const configName: GOTCConfig<ODATARESOURCE, ODATARESOURCEPATH> = {
baseURL: process.env.URL || '',
headers: { 'X-Api-Key': YOUR_API_KEY },
limitterOptions: { tokensPerInterval: 95, interval: 'minute' },
};
The limmitterOptions is to limit API calls to an api to X request pr interval etc. 95 request pr minutes.
interval options are: "second" | "sec" | "minute" | "min" | "hour" | "hr" | "day";
If not specified the default is: { tokensPerInterval: 1000, interval: 'minute' }
You consume it like so:
interface Person {
name: string;
age: number;
}
const client = new GOTCApiClient(configName);
await client.get<Person>({ api: 'universal', controller: 'dbo.person' });
With querybuilder
With querybuilder:
interface Person {
name: string;
age: number;
}
const client = new GOTCApiClient(configName);
const queryBuilder = new OdataQueryBuilder<Person>();
await client.get<Person>({ api: 'universal', controller: 'dbo.person', url: queryBuilder.select('name').toQuery()});
Filter can use: eq, ne, gt, ge, lt, le, in, startswith, endswith, contains
interface Person {
name: string;
age: number;
}
const client = new GOTCApiClient(configName);
const queryBuilder = new OdataQueryBuilder<Person>();
await client.get<Person>({
api: 'universal',
controller: 'dbo.person',
url: queryBuilder
.filter((f) => f.eq('Name', 'Mathias').eq('age', 22))
.select('Name', 'Age')
.toQuery(),
});
And is default, if you want to use or, you need to do it like this:
interface Person {
name: string;
age: number;
}
const client = new GOTCApiClient(configName);
const queryBuilder = new OdataQueryBuilder<Person>();
await client.get<Person>({
api: 'universal',
controller: 'dbo.person',
url: queryBuilder
.filter((f) => f.or((o) => o.eq('Name', 'Jacob').eq('Name', 'Mathias'))
.select('Name', 'Age')
.toQuery(),
});
All request returns a GotcResponse that can be types on the api call
client.get<T = unknown, R = unknown>
client.put<T = unknown, R = unknown>
client.post<T = unknown, R = unknown>
client.delete<T = unknown, R = unknown>
The type T will be used for the querybuilder to help filter options, if not provided there will be no help building the filters, and not needed if the filterbuilder is not used.
const response = await flient.get<Person, Person[]>(
'universal',
'OPR.UniversalTableConfiguration',
(error) => handleError(error),
(builder) => builder.filter((filter) => filter.eq('name', 'Name')).toQuery()
);
The type R is the type of the data value on the GotcResponse type and can be use to specify the return type from the api.
On the above response the type of the data would be Person[]
if(response.status === 200) {
const persons = response.data;
}
export interface GotcResponse<T = any, D = any> {
data: T;
status: number;
statusText: string;
headers: AxiosResponseHeaders;
config: AxiosRequestConfig<D>;
request?: any;
}
The querybuilder is under the MIT license, the rest is not.
How to publish
npm run clean
npm run build
npm publish
In theory we should add npm run docs, but we don't.
How it was build
This is created and maintained with with tsup SUUUUUP
start:
npm install --save-dev \
@types/node \
eslint \
typescript \
tsup \
rimraf \
The scripts setup should look like:
"scripts": {
"build": "tsup",
"clean": "rimraf ./dist",
"test": "echo \"Error: no test specified\" && exit 1"
},
The tsup config should looklike
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
dts: true,
splitting: false,
sourcemap: true,
clean: true,
});
The TSconfig should look like:
{
"compilerOptions": {
"lib": [
"dom",
"dom.iterable",
"ESNext"
],
"esModuleInterop": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"outDir": "dist"
}
}