refactor to read more from package.json

This commit is contained in:
undergroundwires
2020-09-22 20:41:12 +01:00
parent 19a092dd31
commit 784a67afff
30 changed files with 374 additions and 158 deletions

View File

@@ -1,4 +1,4 @@
import { OperatingSystem } from '../OperatingSystem';
import { OperatingSystem } from '@/domain/OperatingSystem';
import { DetectorBuilder } from './DetectorBuilder';
import { IBrowserOsDetector } from './IBrowserOsDetector';

View File

@@ -1,5 +1,5 @@
import { IBrowserOsDetector } from './IBrowserOsDetector';
import { OperatingSystem } from '../OperatingSystem';
import { OperatingSystem } from '@/domain/OperatingSystem';
export class DetectorBuilder {
private readonly existingPartsInUserAgent = new Array<string>();

View File

@@ -1,4 +1,4 @@
import { OperatingSystem } from '../OperatingSystem';
import { OperatingSystem } from '@/domain/OperatingSystem';
export interface IBrowserOsDetector {
detect(userAgent: string): OperatingSystem;

View File

@@ -1,7 +1,7 @@
import { BrowserOsDetector } from './BrowserOs/BrowserOsDetector';
import { IBrowserOsDetector } from './BrowserOs/IBrowserOsDetector';
import { IEnvironment } from './IEnvironment';
import { OperatingSystem } from './OperatingSystem';
import { OperatingSystem } from '@/domain/OperatingSystem';
interface IEnvironmentVariables {
readonly window: Window & typeof globalThis;

View File

@@ -1,4 +1,4 @@
import { OperatingSystem } from './OperatingSystem';
import { OperatingSystem } from '@/domain/OperatingSystem';
export interface IEnvironment {
isDesktop: boolean;

View File

@@ -1,24 +1,35 @@
import { Category } from '@/domain/Category';
import { Application } from '@/domain/Application';
import { IApplication } from '@/domain/IApplication';
import { IProjectInformation } from '@/domain/IProjectInformation';
import { ApplicationYaml } from 'js-yaml-loader!./../application.yaml';
import { parseCategory } from './CategoryParser';
import { ProjectInformation } from '../../domain/ProjectInformation';
export function parseApplication(content: ApplicationYaml): IApplication {
export function parseApplication(content: ApplicationYaml, env: NodeJS.ProcessEnv = process.env): IApplication {
validate(content);
const categories = new Array<Category>();
for (const action of content.actions) {
const category = parseCategory(action);
categories.push(category);
}
const info = readAppInformation(env);
const app = new Application(
content.name,
content.repositoryUrl,
process.env.VUE_APP_VERSION,
info,
categories);
return app;
}
function readAppInformation(environment): IProjectInformation {
return new ProjectInformation(
environment.VUE_APP_NAME,
environment.VUE_APP_VERSION,
environment.VUE_APP_REPOSITORY_URL,
environment.VUE_APP_HOMEPAGE_URL,
);
}
function validate(content: ApplicationYaml): void {
if (!content) {
throw new Error('application is null or undefined');

View File

@@ -39,7 +39,7 @@ export class ApplicationState implements IApplicationState {
/** Initially selected scripts */
public readonly defaultScripts: Script[]) {
this.selection = new UserSelection(app, defaultScripts.map((script) => new SelectedScript(script, false)));
this.code = new ApplicationCode(this.selection, app.version);
this.code = new ApplicationCode(this.selection, app.info.version);
this.filter = new UserFilter(app);
}
}

View File

@@ -1,6 +1,4 @@
# Structure documented in "./application.yaml.d.ts" (as code)
name: privacy.sexy
repositoryUrl: https://github.com/undergroundwires/privacy.sexy
actions:
-
category: Privacy cleanup

View File

@@ -19,8 +19,6 @@ declare module 'js-yaml-loader!*' {
}
export interface ApplicationYaml {
name: string;
repositoryUrl: string;
actions: ReadonlyArray<YamlCategory>;
}

View File

@@ -2,6 +2,7 @@ import { IEntity } from '../infrastructure/Entity/IEntity';
import { ICategory } from './ICategory';
import { IScript } from './IScript';
import { IApplication } from './IApplication';
import { IProjectInformation } from './IProjectInformation';
export class Application implements IApplication {
public get totalScripts(): number { return this.flattened.allScripts.length; }
@@ -10,13 +11,11 @@ export class Application implements IApplication {
private readonly flattened: IFlattenedApplication;
constructor(
public readonly name: string,
public readonly repositoryUrl: string,
public readonly version: string,
public readonly info: IProjectInformation,
public readonly actions: ReadonlyArray<ICategory>) {
if (!name) { throw Error('Application has no name'); }
if (!repositoryUrl) { throw Error('Application has no repository url'); }
if (!version) { throw Error('Version cannot be empty'); }
if (!info) {
throw new Error('info is undefined');
}
this.flattened = flatten(actions);
ensureValid(this.flattened);
ensureNoDuplicates(this.flattened.allCategories);

View File

@@ -1,10 +1,9 @@
import { IScript } from '@/domain/IScript';
import { ICategory } from '@/domain/ICategory';
import { IProjectInformation } from './IProjectInformation';
export interface IApplication {
readonly name: string;
readonly repositoryUrl: string;
readonly version: string;
readonly info: IProjectInformation;
readonly totalScripts: number;
readonly totalCategories: number;
readonly actions: ReadonlyArray<ICategory>;

View File

@@ -0,0 +1,11 @@
import { OperatingSystem } from './OperatingSystem';
export interface IProjectInformation {
readonly name: string;
readonly version: string;
readonly repositoryUrl: string;
readonly homepage: string;
readonly feedbackUrl: string;
readonly releaseUrl: string;
readonly repositoryWebUrl: string;
getDownloadUrl(os: OperatingSystem): string;
}

View File

@@ -0,0 +1,55 @@
import { IProjectInformation } from './IProjectInformation';
import { OperatingSystem } from './OperatingSystem';
export class ProjectInformation implements IProjectInformation {
public readonly repositoryWebUrl: string;
constructor(
public readonly name: string,
public readonly version: string,
public readonly repositoryUrl: string,
public readonly homepage: string,
) {
if (!name) {
throw new Error('name is undefined');
}
if (!version || +version <= 0) {
throw new Error('version should be higher than zero');
}
if (!repositoryUrl) {
throw new Error('repositoryUrl is undefined');
}
if (!homepage) {
throw new Error('homepage is undefined');
}
this.repositoryWebUrl = getWebUrl(this.repositoryUrl);
}
public getDownloadUrl(os: OperatingSystem): string {
return `${this.repositoryWebUrl}/releases/download/${this.version}/${getFileName(os, this.version)}`;
}
public get feedbackUrl(): string {
return `${this.repositoryWebUrl}/issues`;
}
public get releaseUrl(): string {
return `${this.repositoryWebUrl}/releases/tag/${this.version}`;
}
}
function getWebUrl(gitUrl: string) {
if (gitUrl.endsWith('.git')) {
return gitUrl.substring(0, gitUrl.length - 4);
}
return gitUrl;
}
function getFileName(os: OperatingSystem, version: string): string {
switch (os) {
case OperatingSystem.Linux:
return `privacy.sexy-${version}.AppImage`;
case OperatingSystem.macOS:
return `privacy.sexy-${version}.dmg`;
case OperatingSystem.Windows:
return `privacy.sexy-Setup-${version}.exe`;
default:
throw new Error(`Unsupported os: ${OperatingSystem[os]}`);
}
}

View File

@@ -74,7 +74,7 @@
public async mounted() {
const state = await this.getCurrentStateAsync();
this.repositoryUrl = state.app.repositoryUrl;
this.repositoryUrl = state.app.info.repositoryWebUrl;
state.filter.filterRemoved.on(() => {
this.isSearching = false;
});

View File

@@ -17,7 +17,7 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { Environment } from '@/application/Environment/Environment';
import { OperatingSystem } from '@/application/Environment/OperatingSystem';
import { OperatingSystem } from '@/domain/OperatingSystem';
import DownloadUrlListItem from './DownloadUrlListItem.vue';
@Component({

View File

@@ -12,7 +12,7 @@
import { Component, Prop, Watch } from 'vue-property-decorator';
import { StatefulVue } from '@/presentation/StatefulVue';
import { Environment } from '@/application/Environment/Environment';
import { OperatingSystem } from '@/application/Environment/OperatingSystem';
import { OperatingSystem } from '@/domain/OperatingSystem';
@Component
export default class DownloadUrlListItem extends StatefulVue {
@@ -39,7 +39,7 @@ export default class DownloadUrlListItem extends StatefulVue {
private async getDownloadUrlAsync(os: OperatingSystem): Promise<string> {
const state = await this.getCurrentStateAsync();
return `${state.app.repositoryUrl}/releases/download/${state.app.version}/${getFileName(os, state.app.version)}`;
return state.app.info.getDownloadUrl(os);
}
}
@@ -62,18 +62,6 @@ function getOperatingSystemName(os: OperatingSystem): string {
}
}
function getFileName(os: OperatingSystem, version: string): string {
switch (os) {
case OperatingSystem.Linux:
return `privacy.sexy-${version}.AppImage`;
case OperatingSystem.macOS:
return `privacy.sexy-${version}.dmg`;
case OperatingSystem.Windows:
return `privacy.sexy-Setup-${version}.exe`;
default:
throw new Error(`Unsupported os: ${OperatingSystem[os]}`);
}
}
</script>
<style scoped lang="scss">

View File

@@ -48,8 +48,8 @@ export default class TheFooter extends StatefulVue {
public async mounted() {
const state = await this.getCurrentStateAsync();
this.repositoryUrl = state.app.repositoryUrl;
this.feedbackUrl = `${state.app.repositoryUrl}/issues`;
this.repositoryUrl = state.app.info.repositoryWebUrl;
this.feedbackUrl = state.app.info.feedbackUrl;
}
}
</script>

View File

@@ -4,7 +4,7 @@
<div class="footer__section">
<span v-if="isDesktop" class="footer__section__item">
<font-awesome-icon class="icon" :icon="['fas', 'globe']" />
<span>Online version at <a href="https://privacy.sexy" target="_blank">https://privacy.sexy</a></span>
<span>Online version at <a :href="homepageUrl" target="_blank">{{ homepageUrl }}</a></span>
</span>
<span v-else class="footer__section__item">
<DownloadUrlList />
@@ -66,6 +66,7 @@ export default class TheFooter extends StatefulVue {
public repositoryUrl: string = '';
public releaseUrl: string = '';
public feedbackUrl: string = '';
public homepageUrl: string = '';
constructor() {
super();
@@ -74,12 +75,15 @@ export default class TheFooter extends StatefulVue {
public async mounted() {
const state = await this.getCurrentStateAsync();
this.version = state.app.version;
this.repositoryUrl = state.app.repositoryUrl;
this.releaseUrl = `${state.app.repositoryUrl}/releases/tag/${state.app.version}`;
this.feedbackUrl = `${state.app.repositoryUrl}/issues`;
const info = state.app.info;
this.version = info.version;
this.homepageUrl = info.homepage;
this.repositoryUrl = info.repositoryWebUrl;
this.releaseUrl = info.releaseUrl;
this.feedbackUrl = info.feedbackUrl;
}
}
</script>
<style scoped lang="scss">

View File

@@ -16,7 +16,7 @@ export default class TheHeader extends StatefulVue {
public async mounted() {
const state = await this.getCurrentStateAsync();
this.title = state.app.name;
this.title = state.app.info.name;
}
}
</script>