scaleway-sync-firewall
Version:
Synchronize Scaleway Security Groups
143 lines (119 loc) • 3.62 kB
text/typescript
import Axios, { AxiosInstance } from 'axios';
import { Metadata, ModelDocument, ScalewayZone } from './interfaces/Scaleway';
function baseUrl(zone: ScalewayZone, ...to: string[]) {
const path = to.join('/').replace(/\/{2,}/, '/');
return `https://cp-${zone}.scaleway.com/${path.replace(/^\/+|\/$/, '')}`;
}
/**
* Abstract Model foundation class.
*/
class Model<T extends ModelDocument> {
/**
* Fetch the given resource by path.
*/
public static find(zone: ScalewayZone, id: string) {
return this.client(zone).get(id).then(({ data }) => data);
}
/**
* Fetch a single resource by ID.
*/
// @ts-ignore
public static get<T>(this: T, zone: ScalewayZone, id: string): Promise<InstanceType<T>> {
// @ts-ignore
return this.find(zone, id).then((response) => new this(response[this.subKey], zone));
}
/**
* Axios client for this Model.
*/
protected static client(zone: ScalewayZone) {
return Axios.create({
baseURL: baseUrl(zone, this.path),
headers: {
'X-Auth-Token': process.env.AUTH_TOKEN,
}
})
};
/**
* Model service path.
*/
public static path: string;
/**
* Sub-response key for this model.
* Responses include the key name of the model instead of just the model data.
*/
public static readonly subKey: string;
/**
* Data entry.
*/
public entry: T;
/**
* Scaleway region/zone.
*/
public zone: ScalewayZone;
/**
* Path for the current resource.
*/
protected path?: string;
/**
* Model instance metadata.
*/
protected meta: Metadata;
/**
* Axios client for this Model instance.
*/
public get client(): AxiosInstance {
// @ts-ignore
const client = this.constructor.client(this.zone);
// @ts-ignore
client.defaults.baseURL = baseUrl(this.zone, this.constructor.path, this.path!);
return client;
}
/**
* Model constructor.
*/
constructor(entry: T, zone: ScalewayZone, meta?: Metadata) {
this.entry = entry;
this.zone = zone;
this.meta = meta || {};
}
/**
* Delete the current resource.
*/
public delete() {
return this.client.delete('/');
}
/**
* Patch the current resource.
*/
public patch(data: Partial<T>) {
return this.client.put('/', {
...this.entry,
...data,
});
}
/**
* Create a new resource using the current model entry.
*/
public create() {
const payload = {...this.entry};
delete payload.id;
return this.client.post('../', payload);
}
/**
* Register a has-many relationship between the current and given model.
*/
protected hasMany<T extends typeof Model>(model: T, zone: ScalewayZone, path: string, meta?: Metadata): Promise<Array<InstanceType<T>>> {
return model.find(zone, path).then((documents) => {
return documents[model.subKey].map((document: any) => new model(document, zone, meta));
});
}
}
/**
* Prepare a Model class for the given service path.
*/
export default function <T extends ModelDocument>(baseServicePath: string) {
abstract class PreparedModel extends Model<T> {
public static path = baseServicePath;
}
return PreparedModel;
};