Skip to content

Commit

Permalink
Simplify initial configuration fix #39
Browse files Browse the repository at this point in the history
  • Loading branch information
dmstern committed Nov 26, 2018
1 parent 1892e25 commit aaebf2a
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 71 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ It's free and open source.
npm i -g npmfrog
```

Duplicate the file `.SAMPLE.npmfrogrc.json` and rename it to `.npmfrogrc.json` (either leave it in the project directory or put it in your home directory).

## Usage

```bash
npmfrog
```

At the first start up, npmFrog will create a config file in your home directory under `~/.npmfrog/config.json`. Please fill this file with with your artifactory properties.

Browse to npmFrog instance [http://localhost:8000](http://localhost:8000).

### Development
Expand Down
24 changes: 17 additions & 7 deletions server/artifactory-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,26 @@ import * as emoji from 'node-emoji';
import { PackagesResponse } from '../types/PackageResponse';
import PackageId from '../types/PackageId';
import getFiles from './fileLister';
import * as os from 'os';

import config from './config-service.js';
const repoKey = config.artifactory.repoKey;
const tmpDir = `${__dirname}/../../package-cache`;
const packageDetailCache = {};
import configService from './config-service.js';

const tmpDir = path.join(os.homedir(), '.npmfrog', 'package-cache');
const packageDetailCache = {};
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
const s = config.artifactory.https ? 's' : '';
axios.defaults.baseURL = `http${s}://${config.artifactory.host}/artifactory/api/npm/${repoKey}`;
axios.defaults.headers.common.Authorization = config.artifactory.apiKey;

configService
.getConfig()
.then(config => {
const repoKey = config.artifactory.repoKey;
const s = config.artifactory.https ? 's' : '';

axios.defaults.baseURL = `http${s}://${config.artifactory.host}/artifactory/api/npm/${repoKey}`;
axios.defaults.headers.common.Authorization = config.artifactory.apiKey;
})
.catch(error => {
console.error(error);
});

interface AdditionalCode {
readme: string;
Expand Down
42 changes: 24 additions & 18 deletions server/config-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,28 @@ import * as fs from 'fs-extra';
import Config from '../types/Config';

const homedir = os.homedir();
const configFile = 'config.json';
const sampleConfigFile = path.join(__dirname, '..', '..', '.sample.npmfrogrc.json');
const configFolder = '.npmfrog';
const sampleConfig = fs.readFileSync(sampleConfigFile);
const configPath = path.join(homedir, configFolder, configFile);

const configFile = process.env.MOCK ? '.sample.npmfrogrc.json' : '.npmfrogrc.json';
let config: Config;

try {
config = fs.readJSONSync(path.join(__dirname, '..', '..', configFile));
} catch (er1) {
try {
config = fs.readJSONSync(path.join(homedir, configFile));
} catch (er2) {
console.log(
`No config file found.
Please create a config file as described in the README.md file
or set environment variable MOCK=true to test the UI.`,
);
}
}

export default config;
export default {
async getConfig(): Promise<Config> {
try {
fs.ensureFileSync(configPath);
return fs.readJSONSync(configPath);
} catch (er2) {
console.log(`No config file found.`);
await fs.writeFile(configPath, sampleConfig);
console.log(
`Creating default configuration in ${configPath} . Please fill it with life and restart the server. :)`,
);
const config = sampleConfig.toJSON().data;
return {
artifactory: config['artifactory'],
companyScope: config['companyScope'],
};
}
},
};
27 changes: 15 additions & 12 deletions server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import * as bodyParser from 'body-parser';
import * as cors from 'cors';
import * as morgan from 'morgan';
import * as fs from 'fs-extra';
import configService from './config-service';
import artifactoryService from './artifactory-service';
import config from './config-service';

const portNumber = 30001;

Expand Down Expand Up @@ -83,18 +83,21 @@ app.get('/packageDetail/:scope/:packageName/:version/files/:path', (req, res) =>
});

app.get('/config', (req, res) => {
try {
res.send({
artifactory: {
host: config.artifactory.host,
repoKey: config.artifactory.repoKey,
https: config.artifactory.https,
},
companyScope: config.companyScope,
configService
.getConfig()
.then(config => {
res.send({
artifactory: {
host: config.artifactory.host,
repoKey: config.artifactory.repoKey,
https: config.artifactory.https,
},
companyScope: config.companyScope,
});
})
.catch(error => {
handleError(error, res, `Could not get npmFrog config from server.`);
});
} catch (error) {
handleError(error, res, `Could not get npmFrog config from server.`);
}
});

app.get('/meta', (req, res) => {
Expand Down
45 changes: 25 additions & 20 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -137,24 +137,24 @@
<v-spacer></v-spacer>
</v-toolbar>
<v-content>
<router-view/>
<v-snackbar
v-model="error.show"
bottom
right
auto-height
color="error"
:timeout="0"
<router-view/>
<v-snackbar
v-model="error.show"
bottom
right
auto-height
color="error"
:timeout="0"
>
<span class="error__message" v-html="error.msg"></span>
<v-btn
dark
flat
@click="error.show = false"
>
<span class="error__message" v-html="error.msg"></span>
<v-btn
dark
flat
@click="error.show = false"
>
Close
</v-btn>
</v-snackbar>
Close
</v-btn>
</v-snackbar>
</v-content>
</v-app>
</template>
Expand Down Expand Up @@ -271,9 +271,14 @@ export default class App extends Vue {
}
private loadPackages(): void {
DataStore.Instance.getPackages().then((packages: Package[]) => {
this.searchItems = DataStore.Instance.searchItems;
this.filterSearchItems();
DataStore.Instance.getConfig().then(config => {
if (!config.artifactory.host.startsWith('<')) {
DataStore.Instance.getPackages().then((packages: Package[]) => {
// TODO wtf?
this.searchItems = DataStore.Instance.searchItems;
this.filterSearchItems();
});
}
});
}
Expand Down
15 changes: 5 additions & 10 deletions src/services/DataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,16 @@ export default class DataStore {
}));
}

public getConfig(): Promise<Config | undefined> {
public getConfig(): Promise<Config> {
if (this.config) {
return new Promise((resolve, reject) => {
resolve(this.config);
});
}
return BackendApi.Instance.getConfig()
.then(response => {
this.config = response.data;
return this.config;
})
.catch(error => {
EventBus.$emit(Errors.SERVER_ERROR, error);
return undefined;
});
return BackendApi.Instance.getConfig().then(response => {
this.config = response.data;
return this.config;
});
}

public getMetaInfo(): Promise<IPackageJSON | undefined> {
Expand Down
32 changes: 30 additions & 2 deletions src/views/Home.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
<template>
<div class="home">
<PackageList startMsg="Loading packages..."/>
<v-alert
type="warning"
:value="data.status.toString() === '1'"
>
It looks like this is your first startup and npmFrog hasn't set up correctly.
Please open the config file <code>~/.npmfrog/config.json</code> in the server's home directory and change the defaults to your artifacory properties.
</v-alert>
<PackageList v-if="data.status.toString() === '2'" startMsg="Loading packages..."/>
</div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import PackageList from '@/components/PackageList.vue';
import DataStore from '@/services/DataStore';
import { Status } from '../../types/Config';
@Component({
components: {
PackageList,
},
})
export default class Home extends Vue {}
export default class Home extends Vue {
private data: {
status: Status;
};
constructor() {
super();
this.data = {
status: Status.loading,
};
DataStore.Instance.getConfig().then(config => {
if (config.artifactory.host.startsWith('<')) {
this.data.status = Status.firstStartUp;
} else {
this.data.status = Status.configured;
}
});
}
}
</script>
6 changes: 6 additions & 0 deletions types/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ export default interface Config {
};
companyScope: string;
}

export enum Status {
loading,
firstStartUp,
configured,
}

0 comments on commit aaebf2a

Please sign in to comment.