Skip to content

Commit 97814d4

Browse files
authored
Merge pull request #869 from solid/feature/server-info
Feature/server-info
2 parents 7319937 + 6e22f1a commit 97814d4

File tree

18 files changed

+208
-136
lines changed

18 files changed

+208
-136
lines changed

bin/lib/init.js

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,9 @@ module.exports = function (program) {
3131
// Prompt to the user
3232
inquirer.prompt(questions)
3333
.then((answers) => {
34-
// setting email
35-
if (answers.useEmail) {
36-
answers.email = {
37-
host: answers['email-host'],
38-
port: answers['email-port'],
39-
secure: true,
40-
auth: {
41-
user: answers['email-auth-user'],
42-
pass: answers['email-auth-pass']
43-
}
44-
}
45-
delete answers['email-host']
46-
delete answers['email-port']
47-
delete answers['email-auth-user']
48-
delete answers['email-auth-pass']
49-
}
50-
51-
// clean answers
52-
Object.keys(answers).forEach((answer) => {
53-
if (answer.startsWith('use')) {
54-
delete answers[answer]
55-
}
56-
})
34+
manipulateEmailSection(answers)
35+
manipulateServerSection(answers)
36+
cleanupAnswers(answers)
5737

5838
// write config file
5939
const config = JSON.stringify(camelize(answers), null, ' ')
@@ -71,3 +51,44 @@ module.exports = function (program) {
7151
})
7252
})
7353
}
54+
55+
function cleanupAnswers (answers) {
56+
// clean answers
57+
Object.keys(answers).forEach((answer) => {
58+
if (answer.startsWith('use')) {
59+
delete answers[answer]
60+
}
61+
})
62+
}
63+
64+
function manipulateEmailSection (answers) {
65+
// setting email
66+
if (answers.useEmail) {
67+
answers.email = {
68+
host: answers['email-host'],
69+
port: answers['email-port'],
70+
secure: true,
71+
auth: {
72+
user: answers['email-auth-user'],
73+
pass: answers['email-auth-pass']
74+
}
75+
}
76+
delete answers['email-host']
77+
delete answers['email-port']
78+
delete answers['email-auth-user']
79+
delete answers['email-auth-pass']
80+
}
81+
}
82+
83+
function manipulateServerSection (answers) {
84+
answers.server = {
85+
name: answers['server-name'],
86+
description: answers['server-description'],
87+
logo: answers['server-logo']
88+
}
89+
Object.keys(answers).forEach((answer) => {
90+
if (answer.startsWith('server-')) {
91+
delete answers[answer]
92+
}
93+
})
94+
}

bin/lib/options.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const fs = require('fs')
22
const path = require('path')
33
const validUrl = require('valid-url')
4+
const { URL } = require('url')
45

56
module.exports = [
67
// {
@@ -317,6 +318,22 @@ module.exports = [
317318
}
318319
return true
319320
}
321+
},
322+
{
323+
name: 'server-name',
324+
help: 'A name for your server (not required, but will be presented on your server\'s frontpage)',
325+
prompt: true,
326+
default: answers => new URL(answers.serverUri).hostname
327+
},
328+
{
329+
name: 'server-description',
330+
help: 'A description of your server (not required)',
331+
prompt: true
332+
},
333+
{
334+
name: 'server-logo',
335+
help: 'A logo that represents you, your brand, or your server (not required)',
336+
prompt: true
320337
}
321338
]
322339

common/img/.gitkeep

Whitespace-only changes.

config.json-default

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,10 @@
99
"sslKey": "./privkey.pem",
1010
"sslCert": "./fullchain.pem",
1111
"multiuser": true,
12-
"corsProxy": "/proxy"
12+
"corsProxy": "/proxy",
13+
"server": {
14+
"name": "",
15+
"description": "",
16+
"logo": ""
17+
}
1318
}

default-templates/server/index.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@ <h1>Welcome to the Solid Prototype</h1>
3131
You are logged in as
3232
<a href="#" id="profileLink"></a>.
3333
</p>
34+
35+
<section>
36+
{{#if serverLogo}}
37+
<img src="{{serverLogo}}" />
38+
{{/if}}
39+
<h2>Server info</h2>
40+
<dl>
41+
<dt>Name</dt>
42+
<dd>{{serverName}}</dd>
43+
{{#if serverDescription}}
44+
<dt>Description</dt>
45+
<dd>{{serverDescription}}</dd>
46+
{{/if}}
47+
<dt>Details</dt>
48+
<dd>Running on <a href="https://solid.mit.edu/">Solid {{serverVersion}}</a> (<a href="https://solid.inrupt.com/docs">Documentation</a>)</dd>
49+
</dl>
50+
</section>
3451
</div>
3552
<script src="/common/js/solid-auth-client.bundle.js"></script>
3653
<script>

lib/common/fs-utils.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module.exports.copyTemplateDir = copyTemplateDir
2+
module.exports.processFile = processFile
3+
4+
const fs = require('fs-extra')
5+
6+
async function copyTemplateDir (templatePath, targetPath) {
7+
return new Promise((resolve, reject) => {
8+
fs.copy(templatePath, targetPath, (error) => {
9+
if (error) { return reject(error) }
10+
11+
resolve()
12+
})
13+
})
14+
}
15+
16+
async function processFile (filePath, manipulateSourceFn) {
17+
return new Promise((resolve, reject) => {
18+
fs.readFile(filePath, 'utf8', (error, rawSource) => {
19+
if (error) {
20+
return reject(error)
21+
}
22+
23+
const output = manipulateSourceFn(rawSource)
24+
25+
fs.writeFile(filePath, output, (error) => {
26+
if (error) {
27+
return reject(error)
28+
}
29+
resolve()
30+
})
31+
})
32+
})
33+
}

lib/common/template-utils.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module.exports.processHandlebarFile = processHandlebarFile
2+
3+
const Handlebars = require('handlebars')
4+
const debug = require('../debug').errors
5+
const { processFile } = require('./fs-utils')
6+
7+
/**
8+
* Reads a file, processes it (performing template substitution), and saves
9+
* back the processed result.
10+
*
11+
* @param filePath {string}
12+
* @param substitutions {Object}
13+
*
14+
* @return {Promise}
15+
*/
16+
async function processHandlebarFile (filePath, substitutions) {
17+
return processFile(filePath, (rawSource) => processHandlebarTemplate(rawSource, substitutions))
18+
}
19+
20+
/**
21+
* Performs a Handlebars string template substitution, and returns the
22+
* resulting string.
23+
*
24+
* @see https://www.npmjs.com/package/handlebars
25+
*
26+
* @param source {string} e.g. 'Hello, {{name}}'
27+
*
28+
* @return {string} Result, e.g. 'Hello, Alice'
29+
*/
30+
function processHandlebarTemplate (source, substitutions) {
31+
try {
32+
const template = Handlebars.compile(source)
33+
return template(substitutions)
34+
} catch (error) {
35+
debug(`Error processing template: ${error}`)
36+
return source
37+
}
38+
}

lib/models/account-template.js

Lines changed: 4 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
'use strict'
22

3-
const fs = require('fs-extra')
43
const path = require('path')
54
const mime = require('mime-types')
65
const recursiveRead = require('recursive-readdir')
7-
const Handlebars = require('handlebars')
6+
const fsUtils = require('../common/fs-utils')
7+
const templateUtils = require('../common/template-utils')
88

99
const RDF_MIME_TYPES = require('../ldp').RDF_MIME_TYPES
1010
const TEMPLATE_EXTENSIONS = [ '.acl', '.meta', '.json', '.hbs', '.handlebars' ]
@@ -62,13 +62,7 @@ class AccountTemplate {
6262
* @return {Promise}
6363
*/
6464
static copyTemplateDir (templatePath, accountPath) {
65-
return new Promise((resolve, reject) => {
66-
fs.copy(templatePath, accountPath, (error) => {
67-
if (error) { return reject(error) }
68-
69-
resolve()
70-
})
71-
})
65+
return fsUtils.copyTemplateDir(templatePath, accountPath)
7266
}
7367

7468
/**
@@ -130,58 +124,7 @@ class AccountTemplate {
130124
*/
131125
processAccount (accountPath) {
132126
return this.readTemplateFiles(accountPath)
133-
.then(files => {
134-
return Promise.all(
135-
files.map((path) => { return this.processFile(path) })
136-
)
137-
})
138-
}
139-
140-
/**
141-
* Reads a file, processes it (performing template substitution), and saves
142-
* back the processed result.
143-
*
144-
* @param filePath {string}
145-
*
146-
* @return {Promise}
147-
*/
148-
processFile (filePath) {
149-
return new Promise((resolve, reject) => {
150-
fs.readFile(filePath, 'utf8', (error, rawSource) => {
151-
if (error) { return reject(error) }
152-
153-
let output = this.processTemplate(rawSource)
154-
155-
fs.writeFile(filePath, output, (error) => {
156-
if (error) { return reject(error) }
157-
resolve()
158-
})
159-
})
160-
})
161-
}
162-
163-
/**
164-
* Performs a Handlebars string template substitution, and returns the
165-
* resulting string.
166-
*
167-
* @see https://www.npmjs.com/package/handlebars
168-
*
169-
* @param source {string} e.g. 'Hello, {{name}}'
170-
*
171-
* @return {string} Result, e.g. 'Hello, Alice'
172-
*/
173-
processTemplate (source) {
174-
let template, result
175-
176-
try {
177-
template = Handlebars.compile(source)
178-
result = template(this.substitutions)
179-
} catch (error) {
180-
console.log('Error processing template: ', error)
181-
return source
182-
}
183-
184-
return result
127+
.then(files => Promise.all(files.map(path => templateUtils.processHandlebarFile(path, this.substitutions))))
185128
}
186129

187130
/**

lib/server-config.js

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
'use strict'
2+
23
/**
34
* Server config initialization utilities
45
*/
56

67
const fs = require('fs-extra')
78
const path = require('path')
9+
const templateUtils = require('./common/template-utils')
10+
const fsUtils = require('./common/fs-utils')
811

912
/**
1013
* Ensures that a directory has been copied / initialized. Used to ensure that
@@ -34,28 +37,24 @@ function ensureDirCopyExists (fromDir, toDir) {
3437
* typically has links to account signup and login, and can be overridden by
3538
* the server operator.
3639
*
37-
* @param argv {Function} Express.js app object
40+
* @param argv {Object} Express.js app object
3841
*/
39-
function ensureWelcomePage (argv) {
40-
let { multiuser, templates } = argv
41-
let rootDir = path.resolve(argv.root)
42-
let serverRootDir
43-
44-
if (multiuser) {
45-
serverRootDir = path.join(rootDir, argv.host.hostname)
46-
} else {
47-
serverRootDir = rootDir
48-
}
49-
50-
let defaultIndexPage = path.join(templates.server, 'index.html')
51-
let existingIndexPage = path.join(serverRootDir, 'index.html')
52-
let defaultIndexPageAcl = path.join(templates.server, 'index.html.acl')
53-
let existingIndexPageAcl = path.join(serverRootDir, 'index.html.acl')
42+
async function ensureWelcomePage (argv) {
43+
const { multiuser, templates, server, host } = argv
44+
const rootDir = path.resolve(argv.root)
45+
const serverRootDir = multiuser ? path.join(rootDir, argv.host.hostname) : rootDir
46+
const existingIndexPage = path.join(serverRootDir, 'index.html')
47+
const packageData = require('../package.json')
5448

5549
if (!fs.existsSync(existingIndexPage)) {
5650
fs.mkdirp(serverRootDir)
57-
fs.copySync(defaultIndexPage, existingIndexPage)
58-
fs.copySync(defaultIndexPageAcl, existingIndexPageAcl)
51+
await fsUtils.copyTemplateDir(templates.server, serverRootDir)
52+
await templateUtils.processHandlebarFile(existingIndexPage, {
53+
serverName: server ? server.name : host.hostname,
54+
serverDescription: server ? server.description : '',
55+
serverLogo: server ? server.logo : '',
56+
serverVersion: packageData.version
57+
})
5958
}
6059
}
6160

lib/utils.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module.exports.stripLineEndings = stripLineEndings
1414
module.exports.fullUrlForReq = fullUrlForReq
1515
module.exports.routeResolvedFile = routeResolvedFile
1616

17-
const fs = require('fs')
17+
const fs = require('fs-extra')
1818
const path = require('path')
1919
const $rdf = require('rdflib')
2020
const from = require('from2')
@@ -149,7 +149,7 @@ function parse (data, baseUri, contentType, callback) {
149149

150150
function serialize (graph, baseUri, contentType, callback) {
151151
try {
152-
// target, kb, base, contentType, callback
152+
// target, kb, base, contentType, callback
153153
$rdf.serialize(null, graph, baseUri, contentType, function (err, result) {
154154
if (err) {
155155
console.log(err)
@@ -171,9 +171,9 @@ function serialize (graph, baseUri, contentType, callback) {
171171
function translate (stream, baseUri, from, to, callback) {
172172
// Handle Turtle Accept header
173173
if (to === 'text/turtle' ||
174-
to === 'text/n3' ||
175-
to === 'application/turtle' ||
176-
to === 'application/n3') {
174+
to === 'text/n3' ||
175+
to === 'application/turtle' ||
176+
to === 'application/n3') {
177177
to = 'text/turtle'
178178
}
179179

0 commit comments

Comments
 (0)