feat(apiclient): add TypeScript API client (ts_apiclient) with resource managers and package exports
This commit is contained in:
157
ts_apiclient/classes.apitoken.ts
Normal file
157
ts_apiclient/classes.apitoken.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import * as interfaces from '../ts_interfaces/index.js';
|
||||
import type { DcRouterApiClient } from './classes.dcrouterapiclient.js';
|
||||
|
||||
export class ApiToken {
|
||||
private clientRef: DcRouterApiClient;
|
||||
|
||||
// Data from IApiTokenInfo
|
||||
public id: string;
|
||||
public name: string;
|
||||
public scopes: interfaces.data.TApiTokenScope[];
|
||||
public createdAt: number;
|
||||
public expiresAt: number | null;
|
||||
public lastUsedAt: number | null;
|
||||
public enabled: boolean;
|
||||
|
||||
/** Only set on creation or roll. Not persisted on server side. */
|
||||
public tokenValue?: string;
|
||||
|
||||
constructor(clientRef: DcRouterApiClient, data: interfaces.data.IApiTokenInfo, tokenValue?: string) {
|
||||
this.clientRef = clientRef;
|
||||
this.id = data.id;
|
||||
this.name = data.name;
|
||||
this.scopes = data.scopes;
|
||||
this.createdAt = data.createdAt;
|
||||
this.expiresAt = data.expiresAt;
|
||||
this.lastUsedAt = data.lastUsedAt;
|
||||
this.enabled = data.enabled;
|
||||
this.tokenValue = tokenValue;
|
||||
}
|
||||
|
||||
public async revoke(): Promise<void> {
|
||||
const response = await this.clientRef.request<interfaces.requests.IReq_RevokeApiToken>(
|
||||
'revokeApiToken',
|
||||
this.clientRef.buildRequestPayload({ id: this.id }) as any,
|
||||
);
|
||||
if (!response.success) {
|
||||
throw new Error(response.message || 'Failed to revoke token');
|
||||
}
|
||||
}
|
||||
|
||||
public async roll(): Promise<string> {
|
||||
const response = await this.clientRef.request<interfaces.requests.IReq_RollApiToken>(
|
||||
'rollApiToken',
|
||||
this.clientRef.buildRequestPayload({ id: this.id }) as any,
|
||||
);
|
||||
if (!response.success) {
|
||||
throw new Error(response.message || 'Failed to roll token');
|
||||
}
|
||||
this.tokenValue = response.tokenValue;
|
||||
return response.tokenValue!;
|
||||
}
|
||||
|
||||
public async toggle(enabled: boolean): Promise<void> {
|
||||
const response = await this.clientRef.request<interfaces.requests.IReq_ToggleApiToken>(
|
||||
'toggleApiToken',
|
||||
this.clientRef.buildRequestPayload({ id: this.id, enabled }) as any,
|
||||
);
|
||||
if (!response.success) {
|
||||
throw new Error(response.message || 'Failed to toggle token');
|
||||
}
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
export class ApiTokenBuilder {
|
||||
private clientRef: DcRouterApiClient;
|
||||
private tokenName: string = '';
|
||||
private tokenScopes: interfaces.data.TApiTokenScope[] = [];
|
||||
private tokenExpiresInDays?: number | null;
|
||||
|
||||
constructor(clientRef: DcRouterApiClient) {
|
||||
this.clientRef = clientRef;
|
||||
}
|
||||
|
||||
public setName(name: string): this {
|
||||
this.tokenName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public setScopes(scopes: interfaces.data.TApiTokenScope[]): this {
|
||||
this.tokenScopes = scopes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public addScope(scope: interfaces.data.TApiTokenScope): this {
|
||||
if (!this.tokenScopes.includes(scope)) {
|
||||
this.tokenScopes.push(scope);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public setExpiresInDays(days: number | null): this {
|
||||
this.tokenExpiresInDays = days;
|
||||
return this;
|
||||
}
|
||||
|
||||
public async save(): Promise<ApiToken> {
|
||||
const response = await this.clientRef.request<interfaces.requests.IReq_CreateApiToken>(
|
||||
'createApiToken',
|
||||
this.clientRef.buildRequestPayload({
|
||||
name: this.tokenName,
|
||||
scopes: this.tokenScopes,
|
||||
expiresInDays: this.tokenExpiresInDays,
|
||||
}) as any,
|
||||
);
|
||||
if (!response.success) {
|
||||
throw new Error(response.message || 'Failed to create API token');
|
||||
}
|
||||
return new ApiToken(
|
||||
this.clientRef,
|
||||
{
|
||||
id: response.tokenId!,
|
||||
name: this.tokenName,
|
||||
scopes: this.tokenScopes,
|
||||
createdAt: Date.now(),
|
||||
expiresAt: this.tokenExpiresInDays
|
||||
? Date.now() + this.tokenExpiresInDays * 24 * 60 * 60 * 1000
|
||||
: null,
|
||||
lastUsedAt: null,
|
||||
enabled: true,
|
||||
},
|
||||
response.tokenValue,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class ApiTokenManager {
|
||||
private clientRef: DcRouterApiClient;
|
||||
|
||||
constructor(clientRef: DcRouterApiClient) {
|
||||
this.clientRef = clientRef;
|
||||
}
|
||||
|
||||
public async list(): Promise<ApiToken[]> {
|
||||
const response = await this.clientRef.request<interfaces.requests.IReq_ListApiTokens>(
|
||||
'listApiTokens',
|
||||
this.clientRef.buildRequestPayload() as any,
|
||||
);
|
||||
return response.tokens.map((t) => new ApiToken(this.clientRef, t));
|
||||
}
|
||||
|
||||
public async create(options: {
|
||||
name: string;
|
||||
scopes: interfaces.data.TApiTokenScope[];
|
||||
expiresInDays?: number | null;
|
||||
}): Promise<ApiToken> {
|
||||
return this.build()
|
||||
.setName(options.name)
|
||||
.setScopes(options.scopes)
|
||||
.setExpiresInDays(options.expiresInDays ?? null)
|
||||
.save();
|
||||
}
|
||||
|
||||
public build(): ApiTokenBuilder {
|
||||
return new ApiTokenBuilder(this.clientRef);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user