mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
Merge branch 'main' into versions/6.0.0
# Conflicts: # src/init/ServerInitializer.ts # src/server/BaseHttpServerFactory.ts # src/server/HttpServerFactory.ts # src/server/WebSocketServerFactory.ts # test/unit/server/BaseHttpServerFactory.test.ts
This commit is contained in:
commit
7cc0e3fbcc
2
.github/workflows/cth-test.yml
vendored
2
.github/workflows/cth-test.yml
vendored
@ -42,7 +42,7 @@ jobs:
|
||||
with:
|
||||
node-version: 16.x
|
||||
- name: Check out the project
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
ref: ${{ inputs.branch || github.ref }}
|
||||
- name: Install dependencies and run build scripts
|
||||
|
10
.github/workflows/docker.yml
vendored
10
.github/workflows/docker.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
||||
tags: ${{ steps.meta-main.outputs.tags || steps.meta-version.outputs.tags }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.3.0
|
||||
- if: startsWith(github.ref, 'refs/tags/v') || (github.ref == 'refs/heads/main')
|
||||
name: Docker meta edge and version tag
|
||||
id: meta-main
|
||||
@ -55,7 +55,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.3.0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
@ -66,7 +66,7 @@ jobs:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and export to docker
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
load: true
|
||||
@ -85,10 +85,10 @@ jobs:
|
||||
done <<< "${{ needs.docker-meta.outputs.tags }}";
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm/v7
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm/v8
|
||||
tags: ${{ needs.docker-meta.outputs.tags }}
|
||||
labels: ${{ needs.docker-meta.outputs.labels }}
|
||||
|
7
.github/workflows/main.yml
vendored
7
.github/workflows/main.yml
vendored
@ -34,12 +34,7 @@ jobs:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
typedocs-release:
|
||||
# Release typedocs on version tag, but ignore pre-releases
|
||||
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')
|
||||
uses: ./.github/workflows/typedocs.yml
|
||||
|
||||
mkdocs-release:
|
||||
# Release mkdocs on version tag, but ignore pre-releases
|
||||
# Release documentation on version tag, but ignore pre-releases
|
||||
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')
|
||||
uses: ./.github/workflows/mkdocs.yml
|
||||
|
35
.github/workflows/mkdocs.yml
vendored
35
.github/workflows/mkdocs.yml
vendored
@ -14,14 +14,14 @@ on:
|
||||
|
||||
jobs:
|
||||
mkdocs-prep:
|
||||
# Runs the markdownlinter to ensure we don't release faulty markdown.
|
||||
# Also gets the correct major version, wether the job is triggered by a version tag
|
||||
# Runs the markdown linter to ensure we don't release faulty markdown.
|
||||
# Also gets the correct major version, whether the job is triggered by a version tag
|
||||
# or a push to main to update the latest documentation.
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
major: ${{ steps.tagged_version.outputs.major || steps.current_version.ouputs.major }}
|
||||
major: ${{ steps.tagged_version.outputs.major || steps.current_version.outputs.major }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3.1.0
|
||||
- uses: actions/checkout@v3.3.0
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
@ -37,13 +37,13 @@ jobs:
|
||||
id: current_version
|
||||
run: |
|
||||
VERSION=$(git show origin/main:package.json | jq -r .version | grep -Po '^(\d+)')
|
||||
echo "::set-output name=major::$VERSION"
|
||||
echo "major=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
mkdocs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: mkdocs-prep
|
||||
steps:
|
||||
- uses: actions/checkout@v3.1.0
|
||||
- uses: actions/checkout@v3.3.0
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
@ -54,4 +54,25 @@ jobs:
|
||||
- run: git fetch origin gh-pages --depth=1
|
||||
- run: |
|
||||
cd documentation && mike deploy --push --update-aliases \
|
||||
${{ needs.mkdocs-prep.outputs.major}}.x latest
|
||||
${{ needs.mkdocs-prep.outputs.major }}.x latest
|
||||
|
||||
|
||||
typedocs:
|
||||
# Build typedocs and publish them to the GH page.
|
||||
# `mike deploy` overwrites the entire folder for a version so these need to be (re)built afterwards.
|
||||
needs: [mkdocs-prep, mkdocs]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
- run: npm ci --ignore-scripts
|
||||
- name: Generate typedocs
|
||||
run: npm run typedocs
|
||||
- name: Deploy typedocs
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs
|
||||
destination_dir: ${{ needs.mkdocs-prep.outputs.major }}.x/docs
|
||||
|
10
.github/workflows/npm-test.yml
vendored
10
.github/workflows/npm-test.yml
vendored
@ -7,7 +7,7 @@ jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.1.0
|
||||
- uses: actions/checkout@v3.3.0
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
@ -38,7 +38,7 @@ jobs:
|
||||
- name: Ensure line endings are consistent
|
||||
run: git config --global core.autocrlf input
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.3.0
|
||||
- name: Install dependencies and run build scripts
|
||||
run: npm ci
|
||||
- name: Type-check tests
|
||||
@ -81,7 +81,7 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.3.0
|
||||
- name: Install dependencies and run build scripts
|
||||
run: npm ci
|
||||
- name: Run integration tests
|
||||
@ -105,7 +105,7 @@ jobs:
|
||||
- name: Ensure line endings are consistent
|
||||
run: git config --global core.autocrlf input
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.3.0
|
||||
- name: Install dependencies and run build scripts
|
||||
run: npm ci
|
||||
- name: Run integration tests
|
||||
@ -127,7 +127,7 @@ jobs:
|
||||
with:
|
||||
node-version: '16.x'
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.3.0
|
||||
- name: Install dependencies and run build scripts
|
||||
run: npm ci
|
||||
- name: Run deploy tests
|
||||
|
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v7
|
||||
with:
|
||||
debug-only: true
|
||||
stale-issue-label: 🏚️ abandoned
|
||||
|
25
.github/workflows/typedocs.yml
vendored
25
.github/workflows/typedocs.yml
vendored
@ -1,25 +0,0 @@
|
||||
name: Typedocs
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
typedocs:
|
||||
# Build typedocs and publish them to the GH page
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.1.0
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
- run: npm ci --ignore-scripts
|
||||
- name: Generate typedocs
|
||||
run: npm run typedocs
|
||||
- name: Get tagged version
|
||||
id: version
|
||||
uses: battila7/get-version-action@v2
|
||||
- name: Deploy typedocs
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs
|
||||
destination_dir: ${{ steps.version.outputs.major }}.x/docs
|
954
CHANGELOG.md
954
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
47
README.md
47
README.md
@ -115,26 +115,27 @@ testing applications in different setups,
|
||||
or developing new parts for the server
|
||||
without needing to change its base code.
|
||||
|
||||
### ⏱️ Parameters
|
||||
### ⏱ Parameters
|
||||
|
||||
An easy way to customize the server is
|
||||
by passing parameters to the server command.
|
||||
These parameters give you direct access
|
||||
to some commonly used settings:
|
||||
|
||||
| parameter name | default value | description |
|
||||
|------------------------|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--port, -p` | `3000` | The TCP port on which the server should listen. |
|
||||
| `--baseUrl, -b` | `http://localhost:$PORT/` | The base URL used internally to generate URLs. Change this if your server does not run on `http://localhost:$PORT/`. |
|
||||
| `--loggingLevel, -l` | `info` | The detail level of logging; useful for debugging problems. Use `debug` for full information. |
|
||||
| `--config, -c` | `@css:config/default.json` | The configuration(s) for the server. The default only stores data in memory; to persist to your filesystem, use `@css:config/file.json` |
|
||||
| `--rootFilePath, -f` | `./` | Root folder where the server stores data, when using a file-based configuration. |
|
||||
| `--sparqlEndpoint, -s` | | URL of the SPARQL endpoint, when using a quadstore-based configuration. |
|
||||
| `--showStackTrace, -t` | false | Enables detailed logging on error output. |
|
||||
| `--podConfigJson` | `./pod-config.json` | Path to the file that keeps track of dynamic Pod configurations. Only relevant when using `@css:config/dynamic.json`. |
|
||||
| `--seededPodConfigJson`| | Path to the file that keeps track of seeded Pod configurations. |
|
||||
| `--mainModulePath, -m` | | Path from where Components.js will start its lookup when initializing configurations. |
|
||||
| `--workers, -w` | `1` | Run in multithreaded mode using workers. Special values are `-1` (scale to `num_cores-1`), `0` (scale to `num_cores`) and 1 (singlethreaded). |
|
||||
| parameter name | default value | description |
|
||||
|-------------------------|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--port, -p` | `3000` | The TCP port on which the server should listen. |
|
||||
| `--baseUrl, -b` | `http://localhost:$PORT/` | The base URL used internally to generate URLs. Change this if your server does not run on `http://localhost:$PORT/`. |
|
||||
| `--socket` | | The Unix Domain Socket on which the server should listen. `--baseUrl` must be set if this option is provided |
|
||||
| `--loggingLevel, -l` | `info` | The detail level of logging; useful for debugging problems. Use `debug` for full information. |
|
||||
| `--config, -c` | `@css:config/default.json` | The configuration(s) for the server. The default only stores data in memory; to persist to your filesystem, use `@css:config/file.json` |
|
||||
| `--rootFilePath, -f` | `./` | Root folder where the server stores data, when using a file-based configuration. |
|
||||
| `--sparqlEndpoint, -s` | | URL of the SPARQL endpoint, when using a quadstore-based configuration. |
|
||||
| `--showStackTrace, -t` | false | Enables detailed logging on error output. |
|
||||
| `--podConfigJson` | `./pod-config.json` | Path to the file that keeps track of dynamic Pod configurations. Only relevant when using `@css:config/dynamic.json`. |
|
||||
| `--seededPodConfigJson` | | Path to the file that keeps track of seeded Pod configurations. |
|
||||
| `--mainModulePath, -m` | | Path from where Components.js will start its lookup when initializing configurations. |
|
||||
| `--workers, -w` | `1` | Run in multithreaded mode using workers. Special values are `-1` (scale to `num_cores-1`), `0` (scale to `num_cores`) and 1 (singlethreaded). |
|
||||
|
||||
### 🔀 Multithreading
|
||||
|
||||
@ -142,7 +143,7 @@ The Community Solid Server can be started in multithreaded mode with any config.
|
||||
that are threadsafe though. If a non-threadsafe component is used in multithreaded mode, the server will describe with
|
||||
an error which class is the culprit.
|
||||
|
||||
```node
|
||||
```shell
|
||||
# Running multithreaded with autoscaling to number of logical cores minus 1
|
||||
npm start -- -c config/file.json -w -1
|
||||
```
|
||||
@ -174,13 +175,10 @@ Recipes for configuring the server can be found at [CommunitySolidServer/recipes
|
||||
The server allows writing and plugging in custom modules
|
||||
without altering its base source code.
|
||||
|
||||
The [📗 API documentation](https://communitysolidserver.github.io/CommunitySolidServer/latest/docs) and
|
||||
the [📐 architectural diagram](https://rubenverborgh.github.io/solid-server-architecture/solid-architecture-v1-3-0.pdf)
|
||||
The [📗 API documentation](https://communitysolidserver.github.io/CommunitySolidServer/latest/5.x/docs) and
|
||||
the [📓 user documentation](https://communitysolidserver.github.io/CommunitySolidServer/)
|
||||
can help you find your way.
|
||||
|
||||
If you want to help out with server development,
|
||||
have a look at the [📓 user documentation](https://communitysolidserver.github.io/CommunitySolidServer/) and
|
||||
[🛠️ good first issues](https://github.com/CommunitySolidServer/CommunitySolidServer/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22).
|
||||
There is also a repository of [📚 comprehensive tutorials](https://github.com/CommunitySolidServer/tutorials/)
|
||||
|
||||
## 📜 License
|
||||
|
||||
@ -189,13 +187,6 @@ is copyrighted by [Inrupt Inc.](https://inrupt.com/)
|
||||
and [imec](https://www.imec-int.com/)
|
||||
and available under the [MIT License](https://github.com/CommunitySolidServer/CommunitySolidServer/blob/main/LICENSE.md).
|
||||
|
||||
Core contributors are
|
||||
[Joachim Van Herwegen](https://github.com/joachimvh),
|
||||
[Ruben Verborgh](https://github.com/RubenVerborgh),
|
||||
[Ruben Taelman](https://github.com/rubensworks),
|
||||
and
|
||||
[Matthieu Bosquet](https://github.com/matthieubosquet).
|
||||
|
||||
## 🎤 Feedback and questions
|
||||
|
||||
Don't hesitate to [start a discussion](https://github.com/CommunitySolidServer/CommunitySolidServer/discussions)
|
||||
|
@ -96,6 +96,7 @@ These changes are relevant if you wrote custom modules for the server that depen
|
||||
- Regex-based configurations now have ordered entries and use the first match found.
|
||||
- When starting the server through code, it is now possible to provide CLI value bindings as well in `AppRunner`.
|
||||
- Support for Node v12 was dropped.
|
||||
- The server configuration settings can be set from the package.json or .community-solid-server.config.json/.js files.
|
||||
|
||||
### Data migration
|
||||
|
||||
|
5
SECURITY.md
Normal file
5
SECURITY.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report and discuss security vulnerabilities go to <https://github.com/CommunitySolidServer/CommunitySolidServer/security/advisories>
|
@ -1,3 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
const { AppRunner } = require('..');
|
||||
|
||||
// Attaching a logger to the uncaughtExceptionMonitor event,
|
||||
// such that the default uncaughtException behavior still occurs.
|
||||
process.on('uncaughtExceptionMonitor', (err, origin) => {
|
||||
console.error(`Process is halting due to an ${origin} with error ${err.message}`);
|
||||
});
|
||||
|
||||
new AppRunner().runCliSync(process);
|
||||
|
@ -6,7 +6,8 @@
|
||||
"@id": "urn:solid-server:default:ServerInitializer",
|
||||
"@type": "ServerInitializer",
|
||||
"serverFactory": { "@id": "urn:solid-server:default:ServerFactory" },
|
||||
"port": { "@id": "urn:solid-server:default:variable:port" }
|
||||
"port": { "@id": "urn:solid-server:default:variable:port" },
|
||||
"socketPath": { "@id": "urn:solid-server:default:variable:socket" }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -56,6 +56,15 @@
|
||||
"describe": "The TCP port on which the server runs."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "YargsParameter",
|
||||
"name": "socket",
|
||||
"options": {
|
||||
"requiresArg": true,
|
||||
"type": "string",
|
||||
"describe": "The path to the Unix Domain Socket on which the server runs. This overrides the port argument."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "YargsParameter",
|
||||
"name": "rootFilePath",
|
||||
|
@ -28,6 +28,14 @@
|
||||
"defaultValue": 3000
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedShorthandResolver:_resolvers_key": "urn:solid-server:default:variable:socket",
|
||||
"CombinedShorthandResolver:_resolvers_value": {
|
||||
"@type": "KeyExtractor",
|
||||
"key": "socket",
|
||||
"defaultValue" : ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"CombinedShorthandResolver:_resolvers_key": "urn:solid-server:default:variable:rootFilePath",
|
||||
"CombinedShorthandResolver:_resolvers_value": {
|
||||
|
@ -23,6 +23,7 @@
|
||||
"openid": [ "azp" ],
|
||||
"webid": [ "webid" ]
|
||||
},
|
||||
"clockTolerance": 120,
|
||||
"cookies": {
|
||||
"long": { "signed": true, "maxAge": 86400000 },
|
||||
"short": { "signed": true }
|
||||
|
@ -7,6 +7,11 @@
|
||||
"@id": "urn:solid-server:default:variable:port",
|
||||
"@type": "Variable"
|
||||
},
|
||||
{
|
||||
"comment": "Unix Domain Socket of the server.",
|
||||
"@id": "urn:solid-server:default:variable:socket",
|
||||
"@type": "Variable"
|
||||
},
|
||||
{
|
||||
"comment": "Needs to be set to the base URL of the server for authentication and authorization to function.",
|
||||
"@id": "urn:solid-server:default:variable:baseUrl",
|
||||
|
@ -34,12 +34,17 @@ the [changelog](https://github.com/CommunitySolidServer/CommunitySolidServer/blo
|
||||
* [How to use the Identity Provider](usage/identity-provider.md)
|
||||
* [How to automate authentication](usage/client-credentials.md)
|
||||
* [How to automatically seed pods on startup](usage/seeding-pods.md)
|
||||
* [Using the CSS as a development server in another project](usage/dev-configuration.md)
|
||||
|
||||
## What the internals look like
|
||||
|
||||
* [How the server uses dependency injection](architecture/dependency-injection.md)
|
||||
* [What the architecture looks like](architecture/overview.md)
|
||||
|
||||
## Comprehensive guides and tutorials
|
||||
|
||||
* [The CSS tutorial repository](https://github.com/CommunitySolidServer/tutorials/)
|
||||
|
||||
## Making changes
|
||||
|
||||
* [How to make changes to the repository](contributing/making-changes.md)
|
||||
|
49
documentation/markdown/usage/dev-configuration.md
Normal file
49
documentation/markdown/usage/dev-configuration.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Configuring the CSS as a development server in another project
|
||||
|
||||
It can be useful to use the CSS as local server to develop Solid applications against.
|
||||
As an alternative to using CLI arguments, or environment variables, the CSS can be configured in the `package.json` as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "test",
|
||||
"version": "0.0.0",
|
||||
"private": "true",
|
||||
"config": {
|
||||
"community-solid-server": {
|
||||
"port": 3001,
|
||||
"loggingLevel": "error"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"dev:pod": "community-solid-server"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@solid/community-server": "^6.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
These parameters will then be used when the `community-solid-server`
|
||||
command is executed as an npm script (as shown in the example above).
|
||||
Or whenever the `community-solid-server` command is executed in the same
|
||||
folder as the `package.json`.
|
||||
|
||||
Alternatively, the configuration parameters may be placed in a configuration file named
|
||||
`.community-solid-server.config.json` as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"port": 3001,
|
||||
"loggingLevel": "error"
|
||||
}
|
||||
```
|
||||
|
||||
The config may also be written in JavaScript with the config as the default export
|
||||
such as the following `.community-solid-server.config.js`:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
port: 3001,
|
||||
loggingLevel: "error"
|
||||
};
|
||||
```
|
122
package-lock.json
generated
122
package-lock.json
generated
@ -38,7 +38,7 @@
|
||||
"arrayify-stream": "^2.0.0",
|
||||
"async-lock": "^1.3.2",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"componentsjs": "^5.3.0",
|
||||
"componentsjs": "^5.3.2",
|
||||
"cors": "^2.8.5",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"ejs": "^3.1.8",
|
||||
@ -6136,9 +6136,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/componentsjs": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/componentsjs/-/componentsjs-5.3.0.tgz",
|
||||
"integrity": "sha512-eteUmYCezs4a/ZBVxk3graGPlNNrdilSrmsWOSWOYO41KTqe054Q5zSdpetNNchhOUwPbIcdP29JuuBdAd2/fQ==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/componentsjs/-/componentsjs-5.3.2.tgz",
|
||||
"integrity": "sha512-wqXaHjrnT4UDQT8Eaou/Itd55OWE7wasBivPJ0qfSlRMi5zRAwp3+sEgGO7F5T7hs0rMsrGTnkWWcoSHmrM/8A==",
|
||||
"dependencies": {
|
||||
"@rdfjs/types": "*",
|
||||
"@types/minimist": "^1.2.0",
|
||||
@ -6702,9 +6702,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cookiejar": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
|
||||
"integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==",
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
|
||||
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cookies": {
|
||||
@ -7143,9 +7143,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dezalgo": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
|
||||
"integrity": "sha512-K7i4zNfT2kgQz3GylDw40ot9GAE47sFZ9EXHFSPP6zONLgH6kWXE0KWJchkbQJLBkRazq4APwZ4OwiFFlT95OQ==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
|
||||
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"asap": "^2.0.0",
|
||||
@ -8782,32 +8782,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/formidable": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz",
|
||||
"integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.1.tgz",
|
||||
"integrity": "sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dezalgo": "1.0.3",
|
||||
"hexoid": "1.0.0",
|
||||
"once": "1.4.0",
|
||||
"qs": "6.9.3"
|
||||
"dezalgo": "^1.0.4",
|
||||
"hexoid": "^1.0.0",
|
||||
"once": "^1.4.0",
|
||||
"qs": "^6.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/tunnckoCore/commissions"
|
||||
}
|
||||
},
|
||||
"node_modules/formidable/node_modules/qs": {
|
||||
"version": "6.9.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
|
||||
"integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
@ -11077,9 +11065,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
|
||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
@ -13718,9 +13706,9 @@
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"node_modules/simple-git": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.12.0.tgz",
|
||||
"integrity": "sha512-cy1RSRFHGZSrlYa3MnUuNVOXLUdifEZD2X8+AZjg8mKCdRvtCFSga6acq5N2g0ggb8lH3jBi369MrFZ+Y6sfsA==",
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.16.0.tgz",
|
||||
"integrity": "sha512-zuWYsOLEhbJRWVxpjdiXl6eyAyGo/KzVW+KFhhw9MqEEJttcq+32jTWSGyxTdf9e/YCohxRE+9xpWFj9FdiJNw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@kwsites/file-exists": "^1.1.1",
|
||||
@ -14592,9 +14580,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths/node_modules/json5": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.0"
|
||||
@ -20402,9 +20390,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"componentsjs": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/componentsjs/-/componentsjs-5.3.0.tgz",
|
||||
"integrity": "sha512-eteUmYCezs4a/ZBVxk3graGPlNNrdilSrmsWOSWOYO41KTqe054Q5zSdpetNNchhOUwPbIcdP29JuuBdAd2/fQ==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/componentsjs/-/componentsjs-5.3.2.tgz",
|
||||
"integrity": "sha512-wqXaHjrnT4UDQT8Eaou/Itd55OWE7wasBivPJ0qfSlRMi5zRAwp3+sEgGO7F5T7hs0rMsrGTnkWWcoSHmrM/8A==",
|
||||
"requires": {
|
||||
"@rdfjs/types": "*",
|
||||
"@types/minimist": "^1.2.0",
|
||||
@ -20854,9 +20842,9 @@
|
||||
}
|
||||
},
|
||||
"cookiejar": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
|
||||
"integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==",
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
|
||||
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
|
||||
"dev": true
|
||||
},
|
||||
"cookies": {
|
||||
@ -21184,9 +21172,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"dezalgo": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
|
||||
"integrity": "sha512-K7i4zNfT2kgQz3GylDw40ot9GAE47sFZ9EXHFSPP6zONLgH6kWXE0KWJchkbQJLBkRazq4APwZ4OwiFFlT95OQ==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
|
||||
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asap": "^2.0.0",
|
||||
@ -22426,23 +22414,15 @@
|
||||
}
|
||||
},
|
||||
"formidable": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz",
|
||||
"integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.1.tgz",
|
||||
"integrity": "sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dezalgo": "1.0.3",
|
||||
"hexoid": "1.0.0",
|
||||
"once": "1.4.0",
|
||||
"qs": "6.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"qs": {
|
||||
"version": "6.9.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
|
||||
"integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==",
|
||||
"dev": true
|
||||
}
|
||||
"dezalgo": "^1.0.4",
|
||||
"hexoid": "^1.0.0",
|
||||
"once": "^1.4.0",
|
||||
"qs": "^6.11.0"
|
||||
}
|
||||
},
|
||||
"fresh": {
|
||||
@ -24134,9 +24114,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"json5": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
|
||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||
"dev": true
|
||||
},
|
||||
"jsonc-parser": {
|
||||
@ -26166,9 +26146,9 @@
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"simple-git": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.12.0.tgz",
|
||||
"integrity": "sha512-cy1RSRFHGZSrlYa3MnUuNVOXLUdifEZD2X8+AZjg8mKCdRvtCFSga6acq5N2g0ggb8lH3jBi369MrFZ+Y6sfsA==",
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.16.0.tgz",
|
||||
"integrity": "sha512-zuWYsOLEhbJRWVxpjdiXl6eyAyGo/KzVW+KFhhw9MqEEJttcq+32jTWSGyxTdf9e/YCohxRE+9xpWFj9FdiJNw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@kwsites/file-exists": "^1.1.1",
|
||||
@ -26853,9 +26833,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"json5": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.0"
|
||||
|
@ -83,7 +83,7 @@
|
||||
"commit-and-tag-version": {
|
||||
"scripts": {
|
||||
"postbump": "ts-node ./scripts/upgradeConfig.ts",
|
||||
"postchangelog": "ts-node ./scripts/formatChangelog.ts"
|
||||
"postchangelog": "ts-node ./scripts/formatChangelog.ts && markdownlint-cli2-fix"
|
||||
},
|
||||
"writerOpts": {
|
||||
"commitsSort": false
|
||||
@ -128,7 +128,7 @@
|
||||
"arrayify-stream": "^2.0.0",
|
||||
"async-lock": "^1.3.2",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"componentsjs": "^5.3.0",
|
||||
"componentsjs": "^5.3.2",
|
||||
"cors": "^2.8.5",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"ejs": "^3.1.8",
|
||||
|
@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env ts-node
|
||||
|
||||
/* eslint-disable no-console */
|
||||
import { readFile, writeFile } from 'fs-extra';
|
||||
|
||||
@ -8,18 +9,16 @@ import { readFile, writeFile } from 'fs-extra';
|
||||
* to the changelog.
|
||||
* Current automatic changes:
|
||||
* - Change all version titles to H2 ("### [vX.Y.Z]" to "## [vX.Y.Z]")
|
||||
* - Capitalize all list entries
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param from - Regular expression to search for
|
||||
* @param to - String to replace to
|
||||
* @param filePath - File to search/replace
|
||||
* @returns Promise
|
||||
* Capitalize all list entries
|
||||
* @param input - String to search/replace
|
||||
* @returns Promise with output string
|
||||
*/
|
||||
async function replaceInFile(from: RegExp, to: string, filePath: string): Promise<void> {
|
||||
const data = await readFile(filePath, 'utf8');
|
||||
const result = data.replace(from, to);
|
||||
return writeFile(filePath, result, 'utf8');
|
||||
async function capitalizeListEntries(input: string): Promise<string> {
|
||||
return input.replace(/^(\W*\* [a-z])/gmu, (match): string => match.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,4 +29,15 @@ function endProcess(error: Error): never {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
replaceInFile(/### \[/gu, '## [', 'CHANGELOG.md').catch(endProcess);
|
||||
/**
|
||||
* Main function for changelog formatting
|
||||
* @param filePath - Path to the changelog file
|
||||
* @returns Promise
|
||||
*/
|
||||
async function formatChangelog(filePath: string): Promise<void> {
|
||||
let changelog = await readFile(filePath, 'utf8');
|
||||
changelog = await capitalizeListEntries(changelog);
|
||||
return writeFile(filePath, changelog, 'utf8');
|
||||
}
|
||||
|
||||
formatChangelog('CHANGELOG.md').catch(endProcess);
|
||||
|
@ -1,13 +1,15 @@
|
||||
/* eslint-disable unicorn/no-process-exit */
|
||||
import { existsSync } from 'fs';
|
||||
import type { WriteStream } from 'tty';
|
||||
import type { IComponentsManagerBuilderOptions } from 'componentsjs';
|
||||
import { ComponentsManager } from 'componentsjs';
|
||||
import { readJSON } from 'fs-extra';
|
||||
import yargs from 'yargs';
|
||||
import { LOG_LEVELS } from '../logging/LogLevel';
|
||||
import { getLoggerFor } from '../logging/LogUtil';
|
||||
import { createErrorMessage, isError } from '../util/errors/ErrorUtil';
|
||||
import { InternalServerError } from '../util/errors/InternalServerError';
|
||||
import { resolveModulePath, resolveAssetPath } from '../util/PathUtil';
|
||||
import { resolveModulePath, resolveAssetPath, joinFilePath } from '../util/PathUtil';
|
||||
import type { App } from './App';
|
||||
import type { CliExtractor } from './cli/CliExtractor';
|
||||
import type { CliResolver } from './CliResolver';
|
||||
@ -135,7 +137,7 @@ export class AppRunner {
|
||||
*/
|
||||
public async createCli(argv: CliArgv = process.argv): Promise<App> {
|
||||
// Parse only the core CLI arguments needed to load the configuration
|
||||
const yargv = yargs(argv.slice(2))
|
||||
let yargv = yargs(argv.slice(2))
|
||||
.usage('node ./bin/server.js [args]')
|
||||
.options(CORE_CLI_PARAMETERS)
|
||||
// We disable help here as it would only show the core parameters
|
||||
@ -143,6 +145,12 @@ export class AppRunner {
|
||||
// We also read from environment variables
|
||||
.env(ENV_VAR_PREFIX);
|
||||
|
||||
const settings = await this.getPackageSettings();
|
||||
|
||||
if (typeof settings !== 'undefined') {
|
||||
yargv = yargv.default<object>(settings);
|
||||
}
|
||||
|
||||
const params = await yargv.parse();
|
||||
|
||||
const loaderProperties = {
|
||||
@ -165,12 +173,45 @@ export class AppRunner {
|
||||
}
|
||||
|
||||
// Build the CLI components and use them to generate values for the Components.js variables
|
||||
const variables = await this.cliToVariables(componentsManager, argv);
|
||||
const variables = await this.cliToVariables(componentsManager, argv, settings);
|
||||
|
||||
// Build and start the actual server application using the generated variable values
|
||||
return await this.createApp(componentsManager, variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves settings from package.json or configuration file when
|
||||
* part of an npm project.
|
||||
* @returns The settings defined in the configuration file
|
||||
*/
|
||||
public async getPackageSettings(): Promise<undefined | Record<string, unknown>> {
|
||||
// Only try and retrieve config file settings if there is a package.json in the
|
||||
// scope of the current directory
|
||||
const packageJsonPath = joinFilePath(process.cwd(), 'package.json');
|
||||
if (!existsSync(packageJsonPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First see if there is a dedicated .json configuration file
|
||||
const cssConfigPath = joinFilePath(process.cwd(), '.community-solid-server.config.json');
|
||||
if (existsSync(cssConfigPath)) {
|
||||
return readJSON(cssConfigPath);
|
||||
}
|
||||
|
||||
// Next see if there is a dedicated .js file
|
||||
const cssConfigPathJs = joinFilePath(process.cwd(), '.community-solid-server.config.js');
|
||||
if (existsSync(cssConfigPathJs)) {
|
||||
return import(cssConfigPathJs);
|
||||
}
|
||||
|
||||
// Finally try and read from the config.community-solid-server
|
||||
// field in the root package.json
|
||||
const pkg = await readJSON(packageJsonPath);
|
||||
if (typeof pkg.config?.['community-solid-server'] === 'object') {
|
||||
return pkg.config['community-solid-server'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Components Manager that will be used for instantiating.
|
||||
*/
|
||||
@ -189,11 +230,14 @@ export class AppRunner {
|
||||
* Handles the first Components.js instantiation.
|
||||
* Uses it to extract the CLI shorthand values and use those to create variable bindings.
|
||||
*/
|
||||
private async cliToVariables(componentsManager: ComponentsManager<CliResolver>, argv: CliArgv):
|
||||
Promise<VariableBindings> {
|
||||
private async cliToVariables(
|
||||
componentsManager: ComponentsManager<CliResolver>,
|
||||
argv: CliArgv,
|
||||
settings?: Record<string, unknown>,
|
||||
): Promise<VariableBindings> {
|
||||
const cliResolver = await this.createCliResolver(componentsManager);
|
||||
const shorthand = await this.extractShorthand(cliResolver.cliExtractor, argv);
|
||||
return await this.resolveShorthand(cliResolver.shorthandResolver, shorthand);
|
||||
return await this.resolveShorthand(cliResolver.shorthandResolver, { ...settings, ...shorthand });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,22 +14,32 @@ export class ServerInitializer extends Initializer implements Finalizable {
|
||||
protected readonly logger = getLoggerFor(this);
|
||||
|
||||
private readonly serverFactory: HttpServerFactory;
|
||||
private readonly port: number;
|
||||
private readonly port?: number;
|
||||
private readonly socketPath?: string;
|
||||
|
||||
private server?: Server;
|
||||
|
||||
public constructor(serverFactory: HttpServerFactory, port: number) {
|
||||
public constructor(serverFactory: HttpServerFactory, port?: number, socketPath?: string) {
|
||||
super();
|
||||
this.serverFactory = serverFactory;
|
||||
this.port = port;
|
||||
this.socketPath = socketPath;
|
||||
if (!port && !socketPath) {
|
||||
throw new Error('Either Port or Socket arguments must be set');
|
||||
}
|
||||
}
|
||||
|
||||
public async handle(): Promise<void> {
|
||||
this.server = await this.serverFactory.createServer();
|
||||
|
||||
const url = new URL(`http${isHttpsServer(this.server) ? 's' : ''}://localhost:${this.port}/`).href;
|
||||
this.logger.info(`Listening to server at ${url}`);
|
||||
this.server.listen(this.port);
|
||||
if (this.socketPath) {
|
||||
this.logger.info(`Listening to server at ${this.server.address()}`);
|
||||
this.server.listen(this.socketPath);
|
||||
} else {
|
||||
const url = new URL(`http${isHttpsServer(this.server) ? 's' : ''}://localhost:${this.port}/`).href;
|
||||
this.logger.info(`Listening to server at ${url}`);
|
||||
this.server.listen(this.port);
|
||||
}
|
||||
}
|
||||
|
||||
public async finalize(): Promise<void> {
|
||||
|
@ -18,6 +18,9 @@ export class BaseUrlExtractor extends ShorthandExtractor {
|
||||
if (typeof args.baseUrl === 'string') {
|
||||
return ensureTrailingSlash(args.baseUrl);
|
||||
}
|
||||
if (typeof args.socket === 'string') {
|
||||
throw new Error('BaseUrl argument should be provided when using Unix Domain Sockets.');
|
||||
}
|
||||
const port = args.port ?? this.defaultPort;
|
||||
return `http://localhost:${port}/`;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ export function getDefaultVariables(port: number, baseUrl?: string): Record<stri
|
||||
return {
|
||||
'urn:solid-server:default:variable:baseUrl': baseUrl ?? `http://localhost:${port}/`,
|
||||
'urn:solid-server:default:variable:port': port,
|
||||
'urn:solid-server:default:variable:socket': null,
|
||||
'urn:solid-server:default:variable:loggingLevel': 'off',
|
||||
'urn:solid-server:default:variable:showStackTrace': true,
|
||||
'urn:solid-server:default:variable:seededPodConfigJson': null,
|
||||
|
@ -7,20 +7,42 @@ import type { ShorthandResolver } from '../../../src/init/variables/ShorthandRes
|
||||
import { joinFilePath } from '../../../src/util/PathUtil';
|
||||
import { flushPromises } from '../../util/Util';
|
||||
|
||||
const defaultParameters = {
|
||||
let defaultParameters: Record<string, any> = {
|
||||
port: 3000,
|
||||
logLevel: 'info',
|
||||
};
|
||||
|
||||
const cliExtractor: jest.Mocked<CliExtractor> = {
|
||||
handleSafe: jest.fn().mockResolvedValue(defaultParameters),
|
||||
handleSafe: jest.fn((): Record<string, any> => defaultParameters),
|
||||
} as any;
|
||||
|
||||
const defaultVariables = {
|
||||
let defaultVariables: Record<string, any> = {
|
||||
'urn:solid-server:default:variable:port': 3000,
|
||||
'urn:solid-server:default:variable:loggingLevel': 'info',
|
||||
};
|
||||
|
||||
const shorthandKeys: Record<string, string> = {
|
||||
port: 'urn:solid-server:default:variable:port',
|
||||
logLevel: 'urn:solid-server:default:variable:loggingLevel',
|
||||
};
|
||||
|
||||
const shorthandResolver: jest.Mocked<ShorthandResolver> = {
|
||||
handleSafe: jest.fn().mockResolvedValue(defaultVariables),
|
||||
handleSafe: jest.fn((args: Record<string, any>): Record<string, any> => {
|
||||
const variables: Record<string, any> = {};
|
||||
|
||||
for (const key in args) {
|
||||
if (key in shorthandKeys) {
|
||||
variables[shorthandKeys[key]] = args[key];
|
||||
|
||||
// We ignore the default key as this is introduced by the way
|
||||
// we are mocking the module
|
||||
} else if (key !== 'default') {
|
||||
throw new Error(`Unexpected key ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
return variables;
|
||||
}),
|
||||
} as any;
|
||||
|
||||
const mockLogger = {
|
||||
@ -74,11 +96,61 @@ jest.mock('componentsjs', (): any => ({
|
||||
},
|
||||
}));
|
||||
|
||||
let files: Record<string, any> = {};
|
||||
|
||||
const alternateParameters = {
|
||||
port: 3101,
|
||||
logLevel: 'error',
|
||||
};
|
||||
|
||||
const packageJSONbase = {
|
||||
name: 'test',
|
||||
version: '0.0.0',
|
||||
private: true,
|
||||
};
|
||||
|
||||
const packageJSON = {
|
||||
...packageJSONbase,
|
||||
config: {
|
||||
'community-solid-server': alternateParameters,
|
||||
},
|
||||
};
|
||||
|
||||
jest.mock('fs', (): Partial<Record<string, jest.Mock>> => ({
|
||||
cwd: jest.fn((): string => __dirname),
|
||||
existsSync: jest.fn((pth: string): boolean => typeof pth === 'string' && pth in files),
|
||||
}));
|
||||
|
||||
jest.mock('fs-extra', (): Partial<Record<string, jest.Mock>> => ({
|
||||
readJSON: jest.fn(async(pth: string): Promise<any> => files[pth]),
|
||||
pathExists: jest.fn(async(pth: string): Promise<boolean> => typeof pth === 'string' && pth in files),
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
'/var/cwd/.community-solid-server.config.js',
|
||||
(): any => alternateParameters,
|
||||
{ virtual: true },
|
||||
);
|
||||
|
||||
jest.spyOn(process, 'cwd').mockReturnValue('/var/cwd');
|
||||
const write = jest.spyOn(process.stderr, 'write').mockImplementation(jest.fn());
|
||||
const exit = jest.spyOn(process, 'exit').mockImplementation(jest.fn() as any);
|
||||
|
||||
describe('AppRunner', (): void => {
|
||||
beforeEach((): void => {
|
||||
files = {};
|
||||
|
||||
defaultParameters = {
|
||||
port: 3000,
|
||||
logLevel: 'info',
|
||||
};
|
||||
|
||||
defaultVariables = {
|
||||
'urn:solid-server:default:variable:port': 3000,
|
||||
'urn:solid-server:default:variable:loggingLevel': 'info',
|
||||
};
|
||||
});
|
||||
|
||||
afterEach((): void => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
@ -547,6 +619,100 @@ describe('AppRunner', (): void => {
|
||||
}
|
||||
});
|
||||
|
||||
it('runs with no parameters.', async(): Promise<void> => {
|
||||
defaultParameters = {};
|
||||
defaultVariables = {};
|
||||
|
||||
await expect(new AppRunner().runCli()).resolves.toBeUndefined();
|
||||
expect(manager.instantiate).toHaveBeenNthCalledWith(
|
||||
2, 'urn:solid-server:default:App', { variables: {}},
|
||||
);
|
||||
});
|
||||
|
||||
it('runs honouring package.json configuration.', async(): Promise<void> => {
|
||||
files = { '/var/cwd/package.json': packageJSON };
|
||||
defaultParameters = {};
|
||||
defaultVariables = {};
|
||||
|
||||
await expect(new AppRunner().runCli()).resolves.toBeUndefined();
|
||||
expect(manager.instantiate).toHaveBeenNthCalledWith(
|
||||
2, 'urn:solid-server:default:App', { variables: {
|
||||
'urn:solid-server:default:variable:port': 3101,
|
||||
'urn:solid-server:default:variable:loggingLevel': 'error',
|
||||
}},
|
||||
);
|
||||
});
|
||||
|
||||
it('runs honouring package.json configuration with empty config.', async(): Promise<void> => {
|
||||
files = { '/var/cwd/package.json': packageJSONbase };
|
||||
defaultParameters = {};
|
||||
defaultVariables = {};
|
||||
|
||||
await expect(new AppRunner().runCli()).resolves.toBeUndefined();
|
||||
expect(manager.instantiate).toHaveBeenNthCalledWith(
|
||||
2, 'urn:solid-server:default:App', { variables: {}},
|
||||
);
|
||||
});
|
||||
|
||||
it('runs honouring .community-solid-server.config.json if package.json is present.', async(): Promise<void> => {
|
||||
files = {
|
||||
'/var/cwd/.community-solid-server.config.json': alternateParameters,
|
||||
'/var/cwd/package.json': packageJSONbase,
|
||||
};
|
||||
defaultParameters = {};
|
||||
defaultVariables = {};
|
||||
|
||||
await expect(new AppRunner().runCli()).resolves.toBeUndefined();
|
||||
expect(manager.instantiate).toHaveBeenNthCalledWith(
|
||||
2, 'urn:solid-server:default:App', { variables: {
|
||||
'urn:solid-server:default:variable:port': 3101,
|
||||
'urn:solid-server:default:variable:loggingLevel': 'error',
|
||||
}},
|
||||
);
|
||||
});
|
||||
|
||||
it('runs honouring .community-solid-server.config.js if package.json is present.', async(): Promise<void> => {
|
||||
files = {
|
||||
'/var/cwd/.community-solid-server.config.js': alternateParameters,
|
||||
'/var/cwd/package.json': packageJSONbase,
|
||||
};
|
||||
|
||||
defaultParameters = {};
|
||||
defaultVariables = {};
|
||||
|
||||
await expect(new AppRunner().runCli()).resolves.toBeUndefined();
|
||||
expect(manager.instantiate).toHaveBeenNthCalledWith(
|
||||
2, 'urn:solid-server:default:App', { variables: {
|
||||
'urn:solid-server:default:variable:port': 3101,
|
||||
'urn:solid-server:default:variable:loggingLevel': 'error',
|
||||
}},
|
||||
);
|
||||
});
|
||||
|
||||
it('runs ignoring .community-solid-server.config.json if no package.json present.', async(): Promise<void> => {
|
||||
files = { '/var/cwd/.community-solid-server.config.json': alternateParameters };
|
||||
defaultParameters = {};
|
||||
defaultVariables = {};
|
||||
|
||||
await expect(new AppRunner().runCli()).resolves.toBeUndefined();
|
||||
expect(manager.instantiate).toHaveBeenNthCalledWith(
|
||||
2, 'urn:solid-server:default:App', { variables: {}},
|
||||
);
|
||||
});
|
||||
|
||||
it('runs ignoring .community-solid-server.config.js if no package.json present.', async(): Promise<void> => {
|
||||
files = {
|
||||
'/var/cwd/.community-solid-server.config.js': `module.exports = ${JSON.stringify(alternateParameters)}`,
|
||||
};
|
||||
defaultParameters = {};
|
||||
defaultVariables = {};
|
||||
|
||||
await expect(new AppRunner().runCli()).resolves.toBeUndefined();
|
||||
expect(manager.instantiate).toHaveBeenNthCalledWith(
|
||||
2, 'urn:solid-server:default:App', { variables: {}},
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error if the server could not start.', async(): Promise<void> => {
|
||||
app.start.mockRejectedValueOnce(new Error('Fatal'));
|
||||
|
||||
|
@ -20,6 +20,7 @@ describe('ServerInitializer', (): void => {
|
||||
(getLoggerFor as jest.MockedFn<() => Logger>).mockReturnValue(logger);
|
||||
|
||||
server = {
|
||||
address: jest.fn().mockResolvedValue('address'),
|
||||
listen: jest.fn(),
|
||||
close: jest.fn((fn: () => void): void => fn()),
|
||||
} as any;
|
||||
@ -49,6 +50,18 @@ describe('ServerInitializer', (): void => {
|
||||
expect(logger.info).toHaveBeenLastCalledWith(`Listening to server at https://localhost:3000/`);
|
||||
});
|
||||
|
||||
it('listens to the specified Unix Domain Socket.', async(): Promise<void> => {
|
||||
initializer = new ServerInitializer(serverFactory, undefined, '/tmp/css.sock');
|
||||
await initializer.handle();
|
||||
expect(server.listen).toHaveBeenCalledWith('/tmp/css.sock');
|
||||
});
|
||||
|
||||
it('throws when neither port or socket are set.', async(): Promise<void> => {
|
||||
expect((): void => {
|
||||
initializer = new ServerInitializer(serverFactory, undefined, undefined);
|
||||
}).toThrow('Either Port or Socket arguments must be set');
|
||||
});
|
||||
|
||||
it('can stop the server.', async(): Promise<void> => {
|
||||
await initializer.handle();
|
||||
await expect(initializer.finalize()).resolves.toBeUndefined();
|
||||
|
@ -16,6 +16,11 @@ describe('A BaseUrlExtractor', (): void => {
|
||||
await expect(computer.handle({ port: 3333 })).resolves.toBe('http://localhost:3333/');
|
||||
});
|
||||
|
||||
it('throws when a Unix Socket Path is provided without a baseUrl.', async(): Promise<void> => {
|
||||
await expect(computer.handle({ socket: '/tmp/css.sock' })).rejects
|
||||
.toThrow('BaseUrl argument should be provided when using Unix Domain Sockets.');
|
||||
});
|
||||
|
||||
it('defaults to port 3000.', async(): Promise<void> => {
|
||||
await expect(computer.handle({})).resolves.toBe('http://localhost:3000/');
|
||||
});
|
||||
|
@ -37,6 +37,11 @@ const portNames = [
|
||||
'BaseServerFactory',
|
||||
] as const;
|
||||
|
||||
const socketNames = [
|
||||
// Unit
|
||||
'BaseHttpServerFactory',
|
||||
];
|
||||
|
||||
export function getPort(name: typeof portNames[number]): number {
|
||||
const idx = portNames.indexOf(name);
|
||||
// Just in case something doesn't listen to the typings
|
||||
@ -46,6 +51,15 @@ export function getPort(name: typeof portNames[number]): number {
|
||||
return 6000 + idx;
|
||||
}
|
||||
|
||||
export function getSocket(name: typeof socketNames[number]): string {
|
||||
const idx = socketNames.indexOf(name);
|
||||
// Just in case something doesn't listen to the typings
|
||||
if (idx < 0) {
|
||||
throw new Error(`Unknown socket name ${name}`);
|
||||
}
|
||||
return `css${idx}.sock`;
|
||||
}
|
||||
|
||||
export function describeIf(envFlag: string): Describe {
|
||||
const flag = `TEST_${envFlag.toUpperCase()}`;
|
||||
const enabled = !/^(|0|false)$/iu.test(process.env[flag] ?? '');
|
||||
|
Loading…
x
Reference in New Issue
Block a user