mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Allow dynamically adding CLI parameters in configs
This commit is contained in:
parent
e6519992bf
commit
bedab907f9
@ -5,6 +5,9 @@
|
||||
- The server can be started with a new parameter to automatically generate accounts and pods,
|
||||
for more info see [here](guides/seeding-pods.md).
|
||||
- A new `RedirectingHttpHandler` class has been added which can be used to redirect certain URLs.
|
||||
- A new default configuration `config/https-file-cli.json`
|
||||
that can set the HTTPS parameters through the CLI has been added.
|
||||
This is also an example of how to add CLI parameters through a custom configuration.
|
||||
|
||||
### Configuration changes
|
||||
You might need to make changes to your v3 configuration if you use a custom config.
|
||||
@ -18,6 +21,8 @@ The following changes pertain to the imports in the default configs:
|
||||
The following changes are relevant for v3 custom configs that replaced certain features.
|
||||
- The key/value storage configs in `config/storage/key-value/*` have been changed to reduce config duplication.
|
||||
All storages there that were only relevant for 1 class have been moved to the config of that class.
|
||||
- Due to a parameter rename in `CombinedSettingsResolver`,
|
||||
`config/app/variables/resolver/resolver.json` has been updated.
|
||||
|
||||
### Interface changes
|
||||
These changes are relevant if you wrote custom modules for the server that depend on existing interfaces.
|
||||
@ -27,6 +32,7 @@ These changes are relevant if you wrote custom modules for the server that depen
|
||||
and has been moved to a separate `ResourceSet` interface.
|
||||
- Several `ModesExtractor`s `PermissionBasedAuthorizer` now take a `ResourceSet` as constructor parameter.
|
||||
- `RepresentationMetadata` no longer accepts strings for predicates in any of its functions.
|
||||
- `CombinedSettingsResolver` parameter `computers` has been renamed to `resolvers`.
|
||||
|
||||
## v3.0.0
|
||||
### New features
|
||||
|
@ -5,63 +5,63 @@
|
||||
"comment": "Converts an input key/value object into an object mapping values to Components.js variables",
|
||||
"@id": "urn:solid-server-app-setup:default:SettingsResolver",
|
||||
"@type": "CombinedSettingsResolver",
|
||||
"computers": [
|
||||
"resolvers": [
|
||||
{
|
||||
"CombinedSettingsResolver:_computers_key": "urn:solid-server:default:variable:baseUrl",
|
||||
"CombinedSettingsResolver:_computers_value": {
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:default:variable:baseUrl",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "BaseUrlExtractor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedSettingsResolver:_computers_key": "urn:solid-server:default:variable:loggingLevel",
|
||||
"CombinedSettingsResolver:_computers_value": {
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:default:variable:loggingLevel",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "KeyExtractor",
|
||||
"key": "loggingLevel",
|
||||
"defaultValue": "info"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedSettingsResolver:_computers_key": "urn:solid-server:default:variable:port",
|
||||
"CombinedSettingsResolver:_computers_value": {
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:default:variable:port",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "KeyExtractor",
|
||||
"key": "port",
|
||||
"defaultValue": 3000
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedSettingsResolver:_computers_key": "urn:solid-server:default:variable:rootFilePath",
|
||||
"CombinedSettingsResolver:_computers_value": {
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:default:variable:rootFilePath",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "AssetPathExtractor",
|
||||
"key": "rootFilePath",
|
||||
"defaultPath": "./"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedSettingsResolver:_computers_key": "urn:solid-server:default:variable:sparqlEndpoint",
|
||||
"CombinedSettingsResolver:_computers_value": {
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:default:variable:sparqlEndpoint",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "KeyExtractor",
|
||||
"key": "sparqlEndpoint"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedSettingsResolver:_computers_key": "urn:solid-server:default:variable:showStackTrace",
|
||||
"CombinedSettingsResolver:_computers_value": {
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:default:variable:showStackTrace",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "KeyExtractor",
|
||||
"key": "showStackTrace",
|
||||
"defaultValue": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedSettingsResolver:_computers_key": "urn:solid-server:default:variable:podConfigJson",
|
||||
"CombinedSettingsResolver:_computers_value": {
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:default:variable:podConfigJson",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "AssetPathExtractor",
|
||||
"key": "podConfigJson",
|
||||
"defaultPath": "./pod-config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedSettingsResolver:_computers_key": "urn:solid-server:default:variable:seededPodConfigJson",
|
||||
"CombinedSettingsResolver:_computers_value": {
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:default:variable:seededPodConfigJson",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "AssetPathExtractor",
|
||||
"key": "seededPodConfigJson"
|
||||
}
|
||||
|
109
config/https-file-cli.json
Normal file
109
config/https-file-cli.json
Normal file
@ -0,0 +1,109 @@
|
||||
{
|
||||
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^3.0.0/components/context.jsonld",
|
||||
"import": [
|
||||
"files-scs:config/app/main/default.json",
|
||||
"files-scs:config/app/init/default.json",
|
||||
"files-scs:config/app/setup/required.json",
|
||||
"files-scs:config/app/variables/default.json",
|
||||
"files-scs:config/http/handler/default.json",
|
||||
"files-scs:config/http/middleware/websockets.json",
|
||||
|
||||
"files-scs:config/http/static/default.json",
|
||||
"files-scs:config/identity/access/public.json",
|
||||
"files-scs:config/identity/email/default.json",
|
||||
"files-scs:config/identity/handler/default.json",
|
||||
"files-scs:config/identity/ownership/token.json",
|
||||
"files-scs:config/identity/pod/static.json",
|
||||
"files-scs:config/identity/registration/enabled.json",
|
||||
"files-scs:config/ldp/authentication/dpop-bearer.json",
|
||||
"files-scs:config/ldp/authorization/webacl.json",
|
||||
"files-scs:config/ldp/handler/default.json",
|
||||
"files-scs:config/ldp/metadata-parser/default.json",
|
||||
"files-scs:config/ldp/metadata-writer/default.json",
|
||||
"files-scs:config/ldp/modes/default.json",
|
||||
"files-scs:config/storage/backend/file.json",
|
||||
"files-scs:config/storage/key-value/resource-store.json",
|
||||
"files-scs:config/storage/middleware/default.json",
|
||||
"files-scs:config/util/auxiliary/acl.json",
|
||||
"files-scs:config/util/identifiers/suffix.json",
|
||||
"files-scs:config/util/index/default.json",
|
||||
"files-scs:config/util/logging/winston.json",
|
||||
"files-scs:config/util/representation-conversion/default.json",
|
||||
"files-scs:config/util/resource-locker/memory.json",
|
||||
"files-scs:config/util/variables/default.json"
|
||||
],
|
||||
"@graph": [
|
||||
{
|
||||
"comment": [
|
||||
"Adds CLI options --httpsKey and --httpsCert and uses those to start an HTTPS server.",
|
||||
"The http/server-factory import above has been omitted since that feature is set below."
|
||||
]
|
||||
},
|
||||
{
|
||||
"@id": "urn:solid-server-app-setup:default:CliExtractor",
|
||||
"@type": "YargsCliExtractor",
|
||||
"extendedParameters": {
|
||||
"httpsKey": {
|
||||
"demandOption": true,
|
||||
"requiresArg": true,
|
||||
"type": "string",
|
||||
"describe": "File path to the HTTPS key."
|
||||
},
|
||||
"httpsCert": {
|
||||
"demandOption": true,
|
||||
"requiresArg": true,
|
||||
"type": "string",
|
||||
"describe": "File path to the HTTPS certificate."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "Adds resolvers to assign the CLI values to the Components.js variables.",
|
||||
"@id": "urn:solid-server-app-setup:default:SettingsResolver",
|
||||
"@type": "CombinedSettingsResolver",
|
||||
"resolvers": [
|
||||
{
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:custom:variable:httpsKey",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "KeyExtractor",
|
||||
"key": "httpsKey"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedSettingsResolver:_resolvers_key": "urn:solid-server:custom:variable:httpsCert",
|
||||
"CombinedSettingsResolver:_resolvers_value": {
|
||||
"@type": "KeyExtractor",
|
||||
"key": "httpsCert"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": [
|
||||
"Creates an HTTPS server with the settings provided via the command line.",
|
||||
"Replaces the example import from config/http/server-factory.https-example.json."
|
||||
],
|
||||
"@id": "urn:solid-server:default:ServerFactory",
|
||||
"@type": "WebSocketServerFactory",
|
||||
"baseServerFactory": {
|
||||
"@id": "urn:solid-server:default:HttpServerFactory",
|
||||
"@type": "BaseHttpServerFactory",
|
||||
"handler": { "@id": "urn:solid-server:default:HttpHandler" },
|
||||
"options_showStackTrace": { "@id": "urn:solid-server:default:variable:showStackTrace" },
|
||||
"options_https": true,
|
||||
"options_key": {
|
||||
"@id": "urn:solid-server:custom:variable:httpsKey",
|
||||
"@type": "Variable"
|
||||
},
|
||||
"options_cert": {
|
||||
"@id": "urn:solid-server:custom:variable:httpsCert",
|
||||
"@type": "Variable"
|
||||
}
|
||||
},
|
||||
"webSocketHandler": {
|
||||
"@type": "UnsecureWebSocketsProtocol",
|
||||
"source": { "@id": "urn:solid-server:default:ResourceStore" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -31,10 +31,13 @@ export class YargsCliExtractor extends CliExtractor {
|
||||
* @param parameters - Parameters that should be parsed from the CLI. @range {json}
|
||||
* Format details can be found at https://yargs.js.org/docs/#api-reference-optionskey-opt
|
||||
* @param options - Additional options to configure yargs. @range {json}
|
||||
* @param extendedParameters - The same as @parameters. Separate variable so in Components.js
|
||||
* we can have both a default set and a user-added version. @range {json}
|
||||
*/
|
||||
public constructor(parameters: YargsArgOptions = {}, options: CliOptions = {}) {
|
||||
public constructor(parameters: YargsArgOptions = {}, options: CliOptions = {},
|
||||
extendedParameters: YargsArgOptions = {}) {
|
||||
super();
|
||||
this.yargsArgOptions = parameters;
|
||||
this.yargsArgOptions = { ...parameters, ...extendedParameters };
|
||||
this.yargvOptions = options;
|
||||
}
|
||||
|
||||
|
@ -6,16 +6,16 @@ import { SettingsResolver } from './SettingsResolver';
|
||||
* Generates variable values by running a set of {@link SettingsExtractor}s on the input.
|
||||
*/
|
||||
export class CombinedSettingsResolver extends SettingsResolver {
|
||||
public readonly computers: Record<string, SettingsExtractor>;
|
||||
public readonly resolvers: Record<string, SettingsExtractor>;
|
||||
|
||||
public constructor(computers: Record<string, SettingsExtractor>) {
|
||||
public constructor(resolvers: Record<string, SettingsExtractor>) {
|
||||
super();
|
||||
this.computers = computers;
|
||||
this.resolvers = resolvers;
|
||||
}
|
||||
|
||||
public async handle(input: Record<string, unknown>): Promise<Record<string, unknown>> {
|
||||
const vars: Record<string, any> = {};
|
||||
for (const [ name, computer ] of Object.entries(this.computers)) {
|
||||
for (const [ name, computer ] of Object.entries(this.resolvers)) {
|
||||
try {
|
||||
vars[name] = await computer.handleSafe(input);
|
||||
} catch (err: unknown) {
|
||||
|
@ -4,6 +4,7 @@ import { YargsCliExtractor } from '../../../../src/init/cli/YargsCliExtractor';
|
||||
const error = jest.spyOn(console, 'error').mockImplementation(jest.fn());
|
||||
const log = jest.spyOn(console, 'log').mockImplementation(jest.fn());
|
||||
const exit = jest.spyOn(process, 'exit').mockImplementation(jest.fn() as any);
|
||||
|
||||
describe('A YargsCliExtractor', (): void => {
|
||||
const parameters: YargsArgOptions = {
|
||||
baseUrl: { alias: 'b', requiresArg: true, type: 'string' },
|
||||
@ -41,6 +42,16 @@ describe('A YargsCliExtractor', (): void => {
|
||||
await expect(extractor.handle(argv)).resolves.toEqual(expect.objectContaining({}));
|
||||
});
|
||||
|
||||
it('combines parameters and extra parameters.', async(): Promise<void> => {
|
||||
extractor = new YargsCliExtractor(parameters, {}, { test: { alias: 't', requiresArg: true, type: 'string' }});
|
||||
const argv = [ 'node', 'script', '-b', 'http://localhost:3000/', '-p', '3000', '-t', 'test' ];
|
||||
await expect(extractor.handle(argv)).resolves.toEqual(expect.objectContaining({
|
||||
baseUrl: 'http://localhost:3000/',
|
||||
port: 3000,
|
||||
test: 'test',
|
||||
}));
|
||||
});
|
||||
|
||||
it('prints usage if defined.', async(): Promise<void> => {
|
||||
extractor = new YargsCliExtractor(parameters, { usage: 'node ./bin/server.js [args]' });
|
||||
const argv = [ 'node', 'script', '--help' ];
|
||||
|
@ -5,22 +5,22 @@ describe('A CombinedSettingsResolver', (): void => {
|
||||
const values = { test: 'data' };
|
||||
const varPort = 'urn:solid-server:default:variable:port';
|
||||
const varLog = 'urn:solid-server:default:variable:loggingLevel';
|
||||
let computerPort: jest.Mocked<SettingsExtractor>;
|
||||
let computerLog: jest.Mocked<SettingsExtractor>;
|
||||
let resolverPort: jest.Mocked<SettingsExtractor>;
|
||||
let resolverLog: jest.Mocked<SettingsExtractor>;
|
||||
let resolver: CombinedSettingsResolver;
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
computerPort = {
|
||||
resolverPort = {
|
||||
handleSafe: jest.fn().mockResolvedValue(3000),
|
||||
} as any;
|
||||
|
||||
computerLog = {
|
||||
resolverLog = {
|
||||
handleSafe: jest.fn().mockResolvedValue('info'),
|
||||
} as any;
|
||||
|
||||
resolver = new CombinedSettingsResolver({
|
||||
[varPort]: computerPort,
|
||||
[varLog]: computerLog,
|
||||
[varPort]: resolverPort,
|
||||
[varLog]: resolverLog,
|
||||
});
|
||||
});
|
||||
|
||||
@ -32,7 +32,7 @@ describe('A CombinedSettingsResolver', (): void => {
|
||||
});
|
||||
|
||||
it('rethrows the error if something goes wrong.', async(): Promise<void> => {
|
||||
computerPort.handleSafe.mockRejectedValueOnce(new Error('bad data'));
|
||||
resolverPort.handleSafe.mockRejectedValueOnce(new Error('bad data'));
|
||||
await expect(resolver.handle(values)).rejects.toThrow(`Error in computing value for variable ${varPort}: bad data`);
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user