mirror of https://github.com/ErsatzTV/ErsatzTV.git
Browse Source
* add version controller * use axios to get version * allow typescript * use version api servicepull/707/head
13 changed files with 1323 additions and 123 deletions
@ -0,0 +1,20 @@ |
|||||||
|
using System.Reflection; |
||||||
|
using Microsoft.AspNetCore.Mvc; |
||||||
|
|
||||||
|
namespace ErsatzTV.Controllers.Api; |
||||||
|
|
||||||
|
[ApiController] |
||||||
|
public class VersionController |
||||||
|
{ |
||||||
|
private static readonly string Version; |
||||||
|
|
||||||
|
static VersionController() |
||||||
|
{ |
||||||
|
Version = Assembly.GetEntryAssembly()? |
||||||
|
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()? |
||||||
|
.InformationalVersion ?? "unknown"; |
||||||
|
} |
||||||
|
|
||||||
|
[HttpGet("/api/version")] |
||||||
|
public string GetVersion() => Version; |
||||||
|
} |
||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@ |
|||||||
import Vue from 'vue'; |
import Vue from 'vue'; |
||||||
import Vuetify from 'vuetify/lib/framework'; |
import Vuetify from 'vuetify'; |
||||||
import colors from 'vuetify/lib/util/colors'; |
import colors from 'vuetify/lib/util/colors'; |
||||||
|
|
||||||
Vue.use(Vuetify); |
Vue.use(Vuetify); |
||||||
@ -0,0 +1,71 @@ |
|||||||
|
import type { AxiosError, AxiosInstance, AxiosResponse } from 'axios'; |
||||||
|
import axios from 'axios'; |
||||||
|
|
||||||
|
export function isAxiosError(value: any): value is AxiosError { |
||||||
|
return typeof value?.response === 'object'; |
||||||
|
} |
||||||
|
|
||||||
|
export abstract class AbstractApiService { |
||||||
|
protected readonly http: AxiosInstance; |
||||||
|
|
||||||
|
protected constructor( |
||||||
|
protected readonly path?: string, |
||||||
|
protected readonly baseURL: string = '/' |
||||||
|
) { |
||||||
|
if (path) { |
||||||
|
this.baseURL += path; |
||||||
|
} |
||||||
|
this.http = axios.create({ |
||||||
|
baseURL |
||||||
|
// ... further stuff, e.g. `withCredentials: true`
|
||||||
|
}); |
||||||
|
this.http.defaults.headers.common['Accept'] = |
||||||
|
'application/json;charset=UTF-8'; |
||||||
|
this.http.defaults.headers.common['Content-Type'] = |
||||||
|
'application/json;charset=UTF-8'; |
||||||
|
} |
||||||
|
|
||||||
|
protected createParams(record: Record<string, any>): URLSearchParams { |
||||||
|
const params: URLSearchParams = new URLSearchParams(); |
||||||
|
for (const key in record) { |
||||||
|
if (Object.prototype.hasOwnProperty.call(record, key)) { |
||||||
|
const value: any = record[key]; |
||||||
|
if (value !== null && value !== undefined) { |
||||||
|
params.append(key, value); |
||||||
|
} else { |
||||||
|
console.debug( |
||||||
|
`Param key '${key}' was null or undefined and will be ignored` |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return params; |
||||||
|
} |
||||||
|
|
||||||
|
protected handleResponse<T>(response: AxiosResponse<T>): T { |
||||||
|
return response.data; |
||||||
|
} |
||||||
|
|
||||||
|
protected handleError(error: unknown): never { |
||||||
|
if (error instanceof Error) { |
||||||
|
if (isAxiosError(error)) { |
||||||
|
if (error.response) { |
||||||
|
console.log(error.response.data); |
||||||
|
console.log(error.response.status); |
||||||
|
console.log(error.response.headers); |
||||||
|
throw error; |
||||||
|
} else if (error.request) { |
||||||
|
// The request was made but no response was received
|
||||||
|
// `error.request` is an instance of XMLHttpRequest in the browser
|
||||||
|
console.log(error.request); |
||||||
|
throw new Error(error as any); |
||||||
|
} |
||||||
|
} else { |
||||||
|
// Something happened in setting up the request that triggered an Error
|
||||||
|
console.log('Error', error.message); |
||||||
|
throw new Error(error.message); |
||||||
|
} |
||||||
|
} |
||||||
|
throw new Error(error as any); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,16 @@ |
|||||||
|
import { AbstractApiService } from './AbstractApiService'; |
||||||
|
|
||||||
|
class VersionApiService extends AbstractApiService { |
||||||
|
public constructor() { |
||||||
|
super('/api/version'); |
||||||
|
} |
||||||
|
|
||||||
|
public version(): Promise<string> { |
||||||
|
return this.http |
||||||
|
.get('') |
||||||
|
.then(this.handleResponse) |
||||||
|
.catch(this.handleError.bind(this)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export const versionApiService: VersionApiService = new VersionApiService(); |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
import Vue, { VNode } from 'vue'; |
||||||
|
|
||||||
|
declare global { |
||||||
|
namespace JSX { |
||||||
|
interface Element extends VNode {} |
||||||
|
interface ElementClass extends Vue {} |
||||||
|
interface IntrinsicElements { |
||||||
|
[elem: string]: any; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
declare module '*.vue' { |
||||||
|
import Vue from 'vue'; |
||||||
|
export default Vue; |
||||||
|
} |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"target": "esnext", |
||||||
|
"module": "esnext", |
||||||
|
"strict": true, |
||||||
|
"allowJs": true, |
||||||
|
"jsx": "preserve", |
||||||
|
"moduleResolution": "node", |
||||||
|
"skipLibCheck": true, |
||||||
|
"esModuleInterop": true, |
||||||
|
"allowSyntheticDefaultImports": true, |
||||||
|
"forceConsistentCasingInFileNames": true, |
||||||
|
"useDefineForClassFields": true, |
||||||
|
"sourceMap": true, |
||||||
|
"baseUrl": ".", |
||||||
|
"types": [ |
||||||
|
"webpack-env", |
||||||
|
"vuetify" |
||||||
|
], |
||||||
|
"paths": { |
||||||
|
"@/*": [ |
||||||
|
"src/*" |
||||||
|
] |
||||||
|
}, |
||||||
|
"lib": [ |
||||||
|
"esnext", |
||||||
|
"dom", |
||||||
|
"dom.iterable", |
||||||
|
"scripthost" |
||||||
|
] |
||||||
|
}, |
||||||
|
"include": [ |
||||||
|
"src/**/*.ts", |
||||||
|
"src/**/*.tsx", |
||||||
|
"src/**/*.vue", |
||||||
|
"tests/**/*.ts", |
||||||
|
"tests/**/*.tsx" |
||||||
|
], |
||||||
|
"exclude": [ |
||||||
|
"node_modules" |
||||||
|
] |
||||||
|
} |
||||||
Loading…
Reference in new issue