refactor: Replace linting configurations

The previous package was outdated, preventing us from updating TS.
This one also lints YAML and JSON,
and applies many more rules to the test files,
explaining all the changes in this PR.
This commit is contained in:
Joachim Van Herwegen 2023-10-27 11:28:57 +02:00
parent 58daeb684f
commit 6248ed0938
327 changed files with 6424 additions and 3375 deletions

View File

@ -1,160 +0,0 @@
/* eslint-disable @typescript-eslint/naming-convention */
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
tsconfigRootDir: __dirname,
project: [ './tsconfig.json', './test/tsconfig.json', './scripts/tsconfig.json' ],
},
// Ignoring js files (such as this one) since they seem to conflict with rules that require typing info
ignorePatterns: [ '*.js' ],
globals: {
AsyncIterable: 'readonly',
BufferEncoding: 'readonly',
NodeJS: 'readonly',
RequestInit: 'readonly',
},
plugins: [
'tsdoc',
'import',
'unused-imports',
],
extends: [
'es/node',
'eslint:recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
],
settings: {
'import/resolver': {
typescript: {
// Always try to resolve types under `<root>@types` directory
// even it doesn't contain any source code, like `@types/rdf-js`
alwaysTryTypes: true,
},
},
},
rules: {
// There are valid typing reasons to have one or the other
'@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/lines-between-class-members': [ 'error', { exceptAfterSingleLine: true }],
// We almost exclusively do dynamic deletes
'@typescript-eslint/no-dynamic-delete': 'off',
'@typescript-eslint/no-empty-interface': 'off',
// Breaks with default void in AsyncHandler 2nd generic
'@typescript-eslint/no-invalid-void-type': 'off',
// Problems with optional parameters
'@typescript-eslint/no-unnecessary-condition': 'off',
"@typescript-eslint/no-unused-vars": [ "error", { "ignoreRestSiblings": true } ],
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/promise-function-async': [ 'error', { checkArrowFunctions: false } ],
'@typescript-eslint/space-before-function-paren': [ 'error', 'never' ],
'@typescript-eslint/unbound-method': 'off',
'@typescript-eslint/unified-signatures': 'off',
// Conflicts with functions from interfaces that sometimes don't require `this`
'class-methods-use-this': 'off',
'comma-dangle': [ 'error', 'always-multiline' ],
'dot-location': [ 'error', 'property' ],
'eslint-comments/disable-enable-pair': 'off',
// Allow declaring overloads in TypeScript (https://eslint.org/docs/rules/func-style)
'func-style': [ 'error', 'declaration' ],
'generator-star-spacing': [ 'error', 'after' ],
// Conflicts with padded-blocks
'lines-around-comment': 'off',
'lines-between-class-members': [ 'error', 'always', { exceptAfterSingleLine: true }],
'max-len': [ 'error', { code: 120, ignoreUrls: true }],
// Used for RDF constants
'new-cap': 'off',
// Necessary in constructor overloading
'no-param-reassign': 'off',
// Checked by @typescript-eslint/no-redeclare
'no-redeclare': 'off',
// Conflicts with external libraries
'no-underscore-dangle': 'off',
// Already checked by @typescript-eslint/no-unused-vars
'no-unused-vars': 'off',
'padding-line-between-statements': 'off',
// Forcing destructuring on existing variables causes clunky code
'prefer-destructuring': 'off',
'prefer-named-capture-group': 'off',
// Already generated by TypeScript
strict: 'off',
'tsdoc/syntax': 'error',
'unicorn/catch-error-name': 'off',
// Can cause some clunky situations if it forces us to assign to an existing variable
'unicorn/consistent-destructuring': 'off',
'unicorn/import-index': 'off',
'unicorn/import-style': 'off',
// The next 2 would prevent some functional programming paradigms
'unicorn/no-array-callback-reference': 'off',
'unicorn/no-fn-reference-in-iterator': 'off',
// Triggers on all functions called `find`, not just on arrays
'unicorn/no-array-method-this-argument':'off',
'unicorn/no-object-as-default-parameter': 'off',
'unicorn/numeric-separators-style': 'off',
// At function only supported in Node v16.6.0
'unicorn/prefer-at': 'off',
// Does not make sense for more complex cases
'unicorn/prefer-object-from-entries': 'off',
// Only supported in Node v15
'unicorn/prefer-string-replace-all' : 'off',
// Can get ugly with large single statements
'unicorn/prefer-ternary': 'off',
'yield-star-spacing': [ 'error', 'after' ],
// Need to use the typescript version of this rule to support overloading
"no-dupe-class-members": "off",
"@typescript-eslint/no-dupe-class-members": ["error"],
// Naming conventions
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'default',
format: [ 'camelCase' ],
leadingUnderscore: 'forbid',
trailingUnderscore: 'forbid',
},
{
selector: 'variable',
format: [ 'camelCase', 'UPPER_CASE' ],
leadingUnderscore: 'forbid',
trailingUnderscore: 'forbid',
},
{
selector: 'typeLike',
format: [ 'PascalCase' ],
},
{
selector: [ 'typeParameter' ],
format: [ 'PascalCase' ],
prefix: [ 'T' ],
},
],
// Import
'@typescript-eslint/consistent-type-imports': [ 'error', { prefer: 'type-imports' }],
// Disabled in favor of eslint-plugin-import
'sort-imports': 'off',
'import/order': [ 'error', {
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
}],
'import/no-duplicates': 'error',
'import/no-extraneous-dependencies': 'error',
'import/no-named-as-default': 'off',
// Doesn't work with type imports
'no-duplicate-imports': 'off',
'unused-imports/no-unused-imports-ts': 'error',
},
overrides: [
{
files: '*.js',
parser: 'espree',
},
],
};

View File

@ -1,14 +1,14 @@
'use strict';
const options = require('../.markdownlint-cli2.cjs');
"use strict";
module.exports = {
globs: [ "**/*.md" ],
globs: [ '**/*.md' ],
config: {
// Re-use the base config
...options.config,
// Allow first line to not be top level heading
MD041: false
}
MD041: false,
},
};

View File

@ -1,33 +1,33 @@
version: 2
updates:
- package-ecosystem: "github-actions"
- package-ecosystem: github-actions
directory: /
schedule:
interval: "daily"
time: "02:13"
timezone: "Europe/Brussels"
interval: daily
time: '02:13'
timezone: Europe/Brussels
labels:
- "⚙️ dependencies"
- package-ecosystem: "npm"
- ⚙️ dependencies
- package-ecosystem: npm
directory: /
schedule:
interval: "daily"
time: "03:35"
timezone: "Europe/Brussels"
target-branch: "versions/next-major"
interval: daily
time: '03:35'
timezone: Europe/Brussels
target-branch: versions/next-major
ignore:
# Ignore minor and patch version updates
- dependency-name: "*"
update-types: ["version-update:semver-minor", "version-update:semver-patch"]
- dependency-name: '*'
update-types: ['version-update:semver-minor', 'version-update:semver-patch']
# Sticking with Husky 4.x
- dependency-name: "husky"
- dependency-name: husky
labels:
- "⚙️ dependencies"
- package-ecosystem: "docker"
- ⚙️ dependencies
- package-ecosystem: docker
directory: /
schedule:
interval: "daily"
time: "04:22"
timezone: "Europe/Brussels"
interval: daily
time: '04:22'
timezone: Europe/Brussels
labels:
- "⚙️ dependencies"
- ⚙️ dependencies

View File

@ -52,7 +52,7 @@ jobs:
- name: Create the necessary folders
run: mkdir -p reports/css
- name: Pull the conformance harness docker
run: "docker pull solidproject/conformance-test-harness:${{ inputs.version }}"
run: 'docker pull solidproject/conformance-test-harness:${{ inputs.version }}'
- name: Wait until the server has started
run: >
curl --output /dev/null --silent --head --fail --retry 30

View File

@ -11,10 +11,10 @@ on:
jobs:
docker-meta:
# Generates the metadata (labels and tags) for the docker containers
# - push to main results in the edge tag
# - version tag results in edge, latest and semver, major, major.minor tags
# - push to versions/ results in the next tag
# Generates the metadata (labels and tags) for the docker containers
# - push to main results in the edge tag
# - version tag results in edge, latest and semver, major, major.minor tags
# - push to versions/ results in the next tag
runs-on: ubuntu-latest
outputs:
labels: ${{ steps.meta-main.outputs.labels || steps.meta-version.outputs.labels }}
@ -49,8 +49,8 @@ jobs:
github-token: ${{ secrets.github_token }}
docker:
# Builds, tests and pushes docker containers
# Containers are built for both linux/amd64 and linux/arm/v7 platforms
# Builds, tests and pushes docker containers
# Containers are built for both linux/amd64 and linux/arm/v7 platforms
needs: docker-meta
runs-on: ubuntu-latest
steps:
@ -73,7 +73,7 @@ jobs:
tags: ${{ needs.docker-meta.outputs.tags }}
labels: ${{ needs.docker-meta.outputs.labels }}
- name: "Test all docker-built image tags"
- name: Test all docker-built image tags
shell: bash
# Loop over all generated image:tag names and docker run them.
# If they aren't built previously, the command will error.

View File

@ -2,7 +2,7 @@ name: CI
on:
push:
branches:
- 'main'
- main
- 'versions/*'
tags:
- 'v*'
@ -14,11 +14,11 @@ concurrency:
jobs:
npm-test:
# Run the tests in every case
# Run the tests in every case
uses: ./.github/workflows/npm-test.yml
cth-test:
# Run the Conformance Test Harness on PRs targeting main or versions/
# Run the Conformance Test Harness on PRs targeting main or versions/
if: github.event_name == 'pull_request' && ( github.base_ref == 'main' || startsWith( github.base_ref, 'versions/' ) )
uses: ./.github/workflows/cth-test.yml
with:
@ -26,7 +26,7 @@ jobs:
version: 1.1.14 # The latest version that CSS is confirmed to pass
docker:
# Build docker containers on version tag, push to main and push to versions/
# Build docker containers on version tag, push to main and push to versions/
needs: npm-test
if: startsWith(github.ref, 'refs/tags/v') || (github.ref == 'refs/heads/main') || startsWith(github.ref, 'refs/heads/versions/')
uses: ./.github/workflows/docker.yml
@ -35,6 +35,6 @@ jobs:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
mkdocs-release:
# Release documentation 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

View File

@ -2,21 +2,21 @@ name: Documentation
on:
workflow_call:
# Additional trigger to deploy changes to the documentation/ folder
# on push to main, ignoring tags so we don't trigger twice upon release
# Additional trigger to deploy changes to the documentation/ folder
# on push to main, ignoring tags so we don't trigger twice upon release
push:
branches:
- main
paths:
- documentation/**
tags-ignore:
- "*"
- '*'
jobs:
mkdocs-prep:
# 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 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.outputs.major }}
@ -24,7 +24,7 @@ jobs:
- uses: actions/checkout@v4.1.1
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: 16.x
- run: npm ci --ignore-scripts
- name: Lint documentation markdown
run: npm run lint:markdown -- documentation/**/*.md
@ -55,7 +55,6 @@ jobs:
- run: |
cd documentation && mike deploy --push --update-aliases \
${{ needs.mkdocs-prep.outputs.major }}.x latest
typedocs:
# Build typedocs and publish them to the GH page.
@ -66,7 +65,7 @@ jobs:
- uses: actions/checkout@v4.1.1
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: 16.x
- run: npm ci --ignore-scripts
- name: Generate typedocs
run: npm run typedocs
@ -75,4 +74,4 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs
destination_dir: ${{ needs.mkdocs-prep.outputs.major }}.x/docs
destination_dir: ${{ needs.mkdocs-prep.outputs.major }}.x/docs

View File

@ -10,12 +10,12 @@ jobs:
- uses: actions/checkout@v4.1.1
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: 16.x
- run: npm ci --ignore-scripts
- run: npm run lint
test-unit:
# Run unit tests on windows and linux
# Run unit tests on windows and linux
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
@ -24,9 +24,9 @@ jobs:
- windows-latest
node-version:
- '18.0'
- '18.x'
- 18.x
- '20.0'
- '20.x'
- 20.x
timeout-minutes: 15
steps:
- name: Use Node.js ${{ matrix.node-version }}
@ -51,13 +51,13 @@ jobs:
parallel: true
test-integration:
# Run integration tests on linux (full suite, with external dependencies)
# Run integration tests on linux (full suite, with external dependencies)
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- '18.x'
- '20.x'
- 18.x
- 20.x
env:
TEST_DOCKER: true
services:
@ -85,13 +85,13 @@ jobs:
run: npm run test:integration
test-integration-windows:
# Run integration tests on windows (no external dependencies)
# Run integration tests on windows (no external dependencies)
runs-on: windows-latest
strategy:
matrix:
node-version:
- '18.x'
- '20.x'
- 18.x
- 20.x
timeout-minutes: 20
steps:
- name: Use Node.js ${{ matrix.node-version }}
@ -108,7 +108,7 @@ jobs:
run: npm run test:integration
test-configs:
# Test startup of CSS with all configs inside the config/ folder
# Test startup of CSS with all configs inside the config/ folder
runs-on: ubuntu-latest
services:
sparql-endpoint:
@ -121,7 +121,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: 16.x
- name: Check out repository
uses: actions/checkout@v4.1.1
- name: Install dependencies and run build scripts
@ -130,7 +130,7 @@ jobs:
run: npm run test:deploy
coveralls:
# Consolidate test coverage reports from all unit tests
# Consolidate test coverage reports from all unit tests
needs: test-unit
runs-on: ubuntu-latest
steps:

View File

@ -11,8 +11,8 @@ jobs:
fail-fast: false
matrix:
branch:
- 'main'
- 'versions/next-major'
- main
- versions/next-major
uses: ./.github/workflows/cth-test.yml
with:
branch: ${{ matrix.branch }}

View File

@ -1,4 +1,4 @@
name: 'Stale issues and PRs'
name: Stale issues and PRs
on:
schedule:
- cron: '30 1 * * *'
@ -24,6 +24,6 @@ jobs:
days-before-close: 30
days-before-pr-stale: -1
operations-per-run: 700
exempt-issue-labels: "🐛 bug,☀️ enhancement,📚 documentation, feature,🐌 performance,
test,📝 task,:ant: worker threads,👩🏾‍💻 developer experience"
exempt-issue-labels: '🐛 bug,☀️ enhancement,📚 documentation, feature,🐌 performance,
test,📝 task,:ant: worker threads,👩🏾‍💻 developer experience'
exempt-all-assignees: true

View File

@ -1,34 +1,34 @@
"use strict";
'use strict';
module.exports = {
ignores: [ "node_modules/", "LICENSE.md", ".github/" ],
ignores: [ 'node_modules/', 'LICENSE.md', '.github/' ],
globs: [ "**/*.md" ],
globs: [ '**/*.md' ],
config: {
// Enable all markdownlint rules
default: true,
// Set list indent level to 4 which mkdocs / Python-Markdown requires
MD007: { "indent": 4 },
MD007: { indent: 4 },
// Enable line length check but exclude tables and code blocks
MD013: {
line_length: 120,
tables: false,
code_blocks: false
code_blocks: false,
},
// Allow multiple subheadings with the same content
// across different section (#1 ##A ##B #2 ##A ##B)
MD024: {
allow_different_nesting: true
allow_different_nesting: true,
},
// Set Ordered list item prefix to "ordered" (use 1. 2. 3. not 1. 1. 1.)
MD029: { "style": "ordered" },
MD029: { style: 'ordered' },
// Allow inline HTML
MD033: false,
}
},
};

View File

@ -1,15 +1,15 @@
{
"types": [
{"type": "feat", "section": "Features"},
{"type": "fix", "section": "Fixes"},
{"type": "chore", "section": "Chores"},
{"type": "chore(deps)", "section": "Dependency updates"},
{"type": "docs", "section": "Documentation"},
{"type": "style", "section": "Styling"},
{"type": "refactor", "section": "Refactors"},
{"type": "perf", "section": "Performance"},
{"type": "test", "section": "Testing"}
],
"header": "<!-- markdownlint-disable MD013 -->\n# Changelog\n\nAll notable changes to this project will be documented in this file.",
"releaseCommitMessageFormat": "chore(release): Release version {{currentTag}} of the npm package"
"types": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Fixes" },
{ "type": "chore", "section": "Chores" },
{ "type": "chore(deps)", "section": "Dependency updates" },
{ "type": "docs", "section": "Documentation" },
{ "type": "style", "section": "Styling" },
{ "type": "refactor", "section": "Refactors" },
{ "type": "perf", "section": "Performance" },
{ "type": "test", "section": "Testing" }
],
"header": "<!-- markdownlint-disable MD013 -->\n# Changelog\n\nAll notable changes to this project will be documented in this file.",
"releaseCommitMessageFormat": "chore(release): Release version {{currentTag}} of the npm package"
}

View File

@ -4,7 +4,9 @@ const { AppRunner } = require('..');
// Attaching a logger to the uncaughtExceptionMonitor event,
// such that the default uncaughtException behavior still occurs.
process.on('uncaughtExceptionMonitor', (err, origin) => {
// eslint-disable-next-line no-console
console.error(`Process is halting due to an ${origin} with error ${err.message}`);
});
// eslint-disable-next-line no-sync
new AppRunner().runCliSync(process);

View File

@ -1,10 +1,10 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
extends: [ '@commitlint/config-conventional' ],
rules: {
'subject-case': [
2,
'never',
['start-case', 'kebab-case', 'snake-case'],
[ 'start-case', 'kebab-case', 'snake-case' ],
],
}
},
};

View File

@ -28,13 +28,13 @@ you could import `ldp/metadata-parser/default.json`
and then add the following in your root config:
```json
{
"@id": "urn:solid-server:default:MetadataParser",
"@type": "ParallelHandler",
"handlers": [
{ "@type": "MyNewParser" }
]
}
{
"@id": "urn:solid-server:default:MetadataParser",
"@type": "ParallelHandler",
"handlers": [
{ "@type": "MyNewParser" }
]
}
```
This will add the new parser to the list of metadata parsers.
@ -54,13 +54,13 @@ you would have to not import anything from `ldp/metadata-parser` folder,
but instead have the following in your root config:
```json
{
"@id": "urn:solid-server:default:MetadataParser",
"@type": "ParallelHandler",
"handlers": [
{ "@type": "SlugParser" }
]
}
{
"@id": "urn:solid-server:default:MetadataParser",
"@type": "ParallelHandler",
"handlers": [
{ "@type": "SlugParser" }
]
}
```
Don't forget that in some cases you would also have to copy some imports!

View File

@ -30,9 +30,9 @@
"source": {
"comment": "These initializers will all be executed sequentially when starting the server.",
"@id": "urn:solid-server:default:PrimarySequenceInitializer",
"@type":"SequenceHandler",
"@type": "SequenceHandler",
"handlers": [
{ "@id": "urn:solid-server:default:CleanupInitializer"},
{ "@id": "urn:solid-server:default:CleanupInitializer" },
{ "@id": "urn:solid-server:default:MigrationInitializer" },
{ "@id": "urn:solid-server:default:BaseUrlVerifier" },
{ "@id": "urn:solid-server:default:PrimaryParallelInitializer" },
@ -61,7 +61,7 @@
{
"comment": "Initializers that need to cleanup or do anything else before something writes to the backend should be added here.",
"@id": "urn:solid-server:default:CleanupInitializer",
"@type":"SequenceHandler",
"@type": "SequenceHandler",
"handlers": [
]
}

View File

@ -21,7 +21,7 @@
"@id": "urn:solid-server:default:ClusterManager",
"@type": "ClusterManager",
"workers": { "@id": "urn:solid-server:default:variable:workers" }
}
}
},
{
"comment": "This is going to contain the list of finalizers that need to be called. These should be added in the configs where such classes are configured.",
@ -37,7 +37,7 @@
{
"comment": "Finalizers that need to cleanup once no more data will be written to the backend should be added here.",
"@id": "urn:solid-server:default:CleanupFinalizer",
"@type":"SequenceHandler",
"@type": "SequenceHandler",
"handlers": [
]
}

View File

@ -33,7 +33,7 @@
"CombinedShorthandResolver:_resolvers_value": {
"@type": "KeyExtractor",
"key": "socket",
"defaultValue" : ""
"defaultValue": ""
}
},
{

View File

@ -20,7 +20,7 @@
"comment": "The ListeningActivityHandler is added to the list of Initializers so Components.js finds and instantiates it.",
"@id": "urn:solid-server:default:PrimaryParallelInitializer",
"@type": "ParallelHandler",
"handlers": [ { "@id": "urn:solid-server:default:ListeningActivityHandler" } ]
"handlers": [{ "@id": "urn:solid-server:default:ListeningActivityHandler" }]
}
]
}

View File

@ -2,7 +2,7 @@
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
"@graph": [
{
"comment": "Sets all the relevant Solid-OIDC parameters.",
"comment": "Sets all the relevant Solid-OIDC parameters.",
"@id": "urn:solid-server:default:IdentityProviderFactory",
"@type": "IdentityProviderFactory",
"promptFactory": {

View File

@ -53,4 +53,3 @@
}
]
}

View File

@ -49,4 +49,3 @@
}
]
}

View File

@ -44,7 +44,7 @@
"comment": "Adds the API version to the JSON response.",
"@id": "urn:solid-server:default:VersionHandler",
"@type": "VersionHandler",
"source" : { "@id": "urn:solid-server:default:CookieInteractionHandler" }
"source": { "@id": "urn:solid-server:default:CookieInteractionHandler" }
},
{
"comment": "Updates the cookie values as necessary.",
@ -67,13 +67,13 @@
"controls": []
}
}],
"source" : { "@id": "urn:solid-server:default:LocationInteractionHandler" }
"source": { "@id": "urn:solid-server:default:LocationInteractionHandler" }
},
{
"comment": "Converts 3xx redirects to 200 JSON responses for consumption by browser scripts.",
"@id": "urn:solid-server:default:LocationInteractionHandler",
"@type": "LocationInteractionHandler",
"source" : { "@id": "urn:solid-server:default:InteractionRouteHandler" }
"source": { "@id": "urn:solid-server:default:InteractionRouteHandler" }
},
{
"comment": "Contains all JsonInteractionHandlers that can potentially handle the input request.",

View File

@ -32,8 +32,8 @@
"@id": "urn:solid-server:default:PasswordControlHandler",
"@type": "ControlHandler",
"controls": [{
"ControlHandler:_controls_key": "create",
"ControlHandler:_controls_value": { "@id": "urn:solid-server:default:AccountPasswordRoute" }
"ControlHandler:_controls_key": "create",
"ControlHandler:_controls_value": { "@id": "urn:solid-server:default:AccountPasswordRoute" }
}]
},
@ -41,10 +41,10 @@
"@id": "urn:solid-server:default:HtmlViewHandler",
"@type": "HtmlViewHandler",
"templates": [{
"@id": "urn:solid-server:default:CreatePasswordHtml",
"@type": "HtmlViewEntry",
"filePath": "@css:templates/identity/password/create.html.ejs",
"route": { "@id": "urn:solid-server:default:AccountPasswordRoute" }
"@id": "urn:solid-server:default:CreatePasswordHtml",
"@type": "HtmlViewEntry",
"filePath": "@css:templates/identity/password/create.html.ejs",
"route": { "@id": "urn:solid-server:default:AccountPasswordRoute" }
}]
},
{

View File

@ -59,8 +59,8 @@
"@id": "urn:solid-server:default:PasswordHtmlControlHandler",
"@type": "ControlHandler",
"controls": [{
"ControlHandler:_controls_key": "forgot",
"ControlHandler:_controls_value": { "@id": "urn:solid-server:default:ForgotPasswordRoute" }
"ControlHandler:_controls_key": "forgot",
"ControlHandler:_controls_value": { "@id": "urn:solid-server:default:ForgotPasswordRoute" }
}]
}
}

View File

@ -10,7 +10,7 @@
"@type": "BasePodIdRoute",
"base": { "@id": "urn:solid-server:default:AccountPodRoute" }
},
"source":{
"source": {
"@type": "ViewInteractionHandler",
"source": {
"@id": "urn:solid-server:default:PodResourceHandler",
@ -21,7 +21,6 @@
}
},
{
"@id": "urn:solid-server:default:MetadataWriter",
"@type": "ParallelHandler",

View File

@ -25,7 +25,7 @@
"@id": "urn:solid-server:default:TemplateEngine"
},
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" },
"store": { "@id": "urn:solid-server:default:ResourceStore"}
"store": { "@id": "urn:solid-server:default:ResourceStore" }
}
}
]

View File

@ -12,12 +12,12 @@
},
{
"@type": "PostOperationHandler",
"store": { "@id": "urn:solid-server:default:ResourceStore" }
"store": { "@id": "urn:solid-server:default:ResourceStore" }
},
{
"@type": "PutOperationHandler",
"store": { "@id": "urn:solid-server:default:ResourceStore" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
},
{
"@type": "DeleteOperationHandler",

View File

@ -13,7 +13,7 @@
"cookieMap": [
{
"CookieParser:_cookieMap_key": { "@id": "urn:solid-server:default:value:accountCookieName" },
"CookieParser:_cookieMap_value": "urn:npm:solid:community-server:http:accountCookie",
"CookieParser:_cookieMap_value": "urn:npm:solid:community-server:http:accountCookie"
}
]
}

View File

@ -7,7 +7,7 @@
"@type": "AuxiliaryLinkMetadataWriter",
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"specificStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" },
"relationType" : "describedby"
"relationType": "describedby"
}
]
}

View File

@ -5,12 +5,12 @@
"comment": "Caches the requested modes based on the incoming operation.",
"@id": "urn:solid-server:default:ModesExtractor",
"@type": "CachedHandler",
"source" : {
"source": {
"comment": "Checks if an operation on a resource requires permissions on intermediate resources (such as newly created parent containers).",
"@type": "IntermediateCreateExtractor",
"resourceSet": { "@id": "urn:solid-server:default:CachedResourceSet" },
"strategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"source": { "@id": "urn:solid-server:default:HttpModesExtractor" },
"source": { "@id": "urn:solid-server:default:HttpModesExtractor" }
}
},
{

View File

@ -74,12 +74,12 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:FileDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
},
{
"@id": "urn:solid-server:default:SparqlResourceStore",
"@type": "RepresentationConvertingStore",
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" },
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" },
"options_inConverter": { "@id": "urn:solid-server:default:RepresentationConverter" },
"options_inPreferences_type": {
"RepresentationConvertingStore:_options_inPreferences_type_key": "internal/quads",
@ -90,7 +90,7 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:SparqlDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
}
}
]

View File

@ -20,7 +20,7 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:FileDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
}
}
]

View File

@ -11,7 +11,7 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:FileDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
}
]
}

View File

@ -13,7 +13,7 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:FileDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
},
{
"comment": "Add content-length parser to the MetadataParser.",

View File

@ -13,7 +13,7 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:FileDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
},
{
"comment": "Add content-length parser to the MetadataParser.",

View File

@ -51,7 +51,7 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:FileDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
},
{
"@id": "urn:solid-server:default:MemoryResourceStore",
@ -59,13 +59,13 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:MemoryDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
},
{
"comment": "SparqlDataAccessor only accepts quad objects so data to that route needs to be converted",
"@id": "urn:solid-server:default:SparqlResourceStore",
"@type": "RepresentationConvertingStore",
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" },
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" },
"options_inConverter": { "@id": "urn:solid-server:default:RepresentationConverter" },
"options_inPreferences_type": {
"RepresentationConvertingStore:_options_inPreferences_type_key": "internal/quads",
@ -76,7 +76,7 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:SparqlDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
}
}
]

View File

@ -11,7 +11,7 @@
"identifierStrategy": { "@id": "urn:solid-server:default:IdentifierStrategy" },
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"accessor": { "@id": "urn:solid-server:default:SparqlDataAccessor" },
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" }
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" }
},
{
"comment": "This makes it so all incoming data is converted to quad objects.",

View File

@ -5,7 +5,7 @@
"comment": "Converts all outgoing resources based on the preferences.",
"@id": "urn:solid-server:default:ResourceStore_Converting",
"@type": "RepresentationConvertingStore",
"metadataStrategy":{ "@id": "urn:solid-server:default:MetadataStrategy" },
"metadataStrategy": { "@id": "urn:solid-server:default:MetadataStrategy" },
"options_inConverter": { "@id": "urn:solid-server:default:RepresentationConverter" },
"options_outConverter": { "@id": "urn:solid-server:default:UiEnabledConverter" }
}

View File

@ -36,7 +36,7 @@
"@id": "urn:solid-server:default:PatchHandler_RDFStore",
"@type": "WaterfallHandler",
"handlers": [
{ "@id": "urn:solid-server:default:PatchHandler_ImmutableMetadata"},
{ "@id": "urn:solid-server:default:PatchHandler_ImmutableMetadata" },
{ "@id": "urn:solid-server:default:PatchHandler_RDF" }
]
},

View File

@ -24,7 +24,7 @@
"@type": "AuxiliaryLinkMetadataWriter",
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"specificStrategy": { "@id": "urn:solid-server:default:AclStrategy" },
"relationType" : "acl"
"relationType": "acl"
},
{
"@id": "urn:solid-server:default:MetadataWriter",

View File

@ -24,7 +24,7 @@
"@type": "AuxiliaryLinkMetadataWriter",
"auxiliaryStrategy": { "@id": "urn:solid-server:default:AuxiliaryStrategy" },
"specificStrategy": { "@id": "urn:solid-server:default:AcrStrategy" },
"relationType" : "acl"
"relationType": "acl"
},
{
"@id": "urn:solid-server:default:MetadataWriter",

View File

@ -132,10 +132,10 @@ You can also send a POST request to this resource with a `webId` and `remove: tr
```json
{
"baseUrl": "http://localhost:3000/my-pod/",
"baseUrl": "http://localhost:3000/my-pod/",
"owners": [
{
"webId": "http://localhost:3000/my-pod/profile/card#me",
{
"webId": "http://localhost:3000/my-pod/profile/card#me",
"visible": false
}
]

View File

@ -44,6 +44,6 @@ such as the following `.community-solid-server.config.js`:
```js
module.exports = {
port: 3001,
loggingLevel: "error"
loggingLevel: 'error'
};
```

View File

@ -71,7 +71,7 @@ at `http://localhost:3000/.notifications/WebSocketChannel2023/`:
```json
{
"@context": ["https://www.w3.org/ns/solid/notification/v1"],
"@context": [ "https://www.w3.org/ns/solid/notification/v1" ],
"type": "http://www.w3.org/ns/solid/notifications#WebSocketChannel2023",
"topic": "http://localhost:3000/foo"
}

View File

@ -1,12 +1,12 @@
docs_dir: markdown
theme:
name: 'material'
name: material
custom_dir: overrides
icon:
repo: fontawesome/brands/github
palette:
- media: "(prefers-color-scheme: light)"
- media: '(prefers-color-scheme: light)'
scheme: default
toggle:
icon: material/weather-night
@ -15,7 +15,7 @@ theme:
accent: deep orange
# Palette toggle for dark mode
- media: "(prefers-color-scheme: dark)"
- media: '(prefers-color-scheme: dark)'
scheme: slate
toggle:
icon: material/weather-sunny
@ -28,12 +28,12 @@ theme:
- navigation.top
- navigation.indexes
site_name: 'Community Solid Server'
site_name: Community Solid Server
site_url: https://communitysolidserver.github.io/CommunitySolidServer
repo_url: https://github.com/CommunitySolidServer/CommunitySolidServer
repo_name: CommunitySolidServer
edit_uri: ""
edit_uri: ''
plugins:
- search
@ -76,40 +76,40 @@ extra:
nav:
- Welcome:
- README.md
- README.md
- Usage:
- Example request: usage/example-requests.md
- Metadata: usage/metadata.md
- Identity provider:
- Overview: usage/identity-provider.md
- JSON API: usage/account/json-api.md
- New login method: usage/account/login-method.md
- Data migration: usage/account/migration.md
- Client credentials: usage/client-credentials.md
- Seeding pods: usage/seeding-pods.md
- Notifications: usage/notifications.md
- Development server: usage/dev-configuration.md
- Example request: usage/example-requests.md
- Metadata: usage/metadata.md
- Identity provider:
- Overview: usage/identity-provider.md
- JSON API: usage/account/json-api.md
- New login method: usage/account/login-method.md
- Data migration: usage/account/migration.md
- Client credentials: usage/client-credentials.md
- Seeding pods: usage/seeding-pods.md
- Notifications: usage/notifications.md
- Development server: usage/dev-configuration.md
- Architecture:
- Overview: architecture/overview.md
- Dependency injection: architecture/dependency-injection.md
- Core: architecture/core.md
- Features:
- Command line arguments: architecture/features/cli.md
- Server initialization: architecture/features/initialization.md
- HTTP requests: architecture/features/http-handler.md
- Solid protocol:
- Overview: architecture/features/protocol/overview.md
- Parsing: architecture/features/protocol/parsing.md
- Authorization: architecture/features/protocol/authorization.md
- Resource Store: architecture/features/protocol/resource-store.md
- Account management:
- Overview: architecture/features/accounts/overview.md
- Controls: architecture/features/accounts/controls.md
- Routes: architecture/features/accounts/routes.md
- Notifications: architecture/features/notifications.md
- Overview: architecture/overview.md
- Dependency injection: architecture/dependency-injection.md
- Core: architecture/core.md
- Features:
- Command line arguments: architecture/features/cli.md
- Server initialization: architecture/features/initialization.md
- HTTP requests: architecture/features/http-handler.md
- Solid protocol:
- Overview: architecture/features/protocol/overview.md
- Parsing: architecture/features/protocol/parsing.md
- Authorization: architecture/features/protocol/authorization.md
- Resource Store: architecture/features/protocol/resource-store.md
- Account management:
- Overview: architecture/features/accounts/overview.md
- Controls: architecture/features/accounts/controls.md
- Routes: architecture/features/accounts/routes.md
- Notifications: architecture/features/notifications.md
- Contributing:
- Pull requests: contributing/making-changes.md
- Releases: contributing/release.md
- Pull requests: contributing/making-changes.md
- Releases: contributing/release.md
- API: ./docs/" target="_blank
# To write documentation locally, execute the next line and browse to http://localhost:8000

255
eslint.config.js Normal file
View File

@ -0,0 +1,255 @@
const antfu = require('@antfu/eslint-config').default;
const jest = require('eslint-plugin-jest');
// Copied from https://github.com/antfu/eslint-config/blob/main/src/configs/typescript.ts
// Doing it like this, so we can make sure these only try to trigger on *.ts files,
// preventing issues with the *.js files.
const typeAwareRules = {
'dot-notation': 'off',
'no-implied-eval': 'off',
'no-throw-literal': 'off',
'ts/await-thenable': 'error',
'ts/dot-notation': [ 'error', { allowKeywords: true }],
'ts/no-floating-promises': 'error',
'ts/no-for-in-array': 'error',
'ts/no-implied-eval': 'error',
'ts/no-misused-promises': 'error',
'ts/no-throw-literal': 'error',
'ts/no-unnecessary-type-assertion': 'error',
'ts/no-unsafe-argument': 'error',
'ts/no-unsafe-assignment': 'error',
'ts/no-unsafe-call': 'error',
'ts/no-unsafe-member-access': 'error',
'ts/no-unsafe-return': 'error',
'ts/restrict-plus-operands': 'error',
'ts/restrict-template-expressions': 'error',
'ts/unbound-method': 'error',
};
module.exports = antfu(
{},
{
// Don't want to lint test assets, or TS snippets in markdown files
ignores: [ 'test/assets/*', '**/*.md/**/*.ts' ],
},
{
rules: {
'max-len': 'off',
'unicorn/filename-case': [ 'error', {
cases: {
camelCase: false,
pascalCase: false,
kebabCase: true,
snakeCase: false,
},
}],
},
},
{
// By default, antfu also triggers type rules on *.js files which causes all kinds of issues for us
files: [ '**/*.ts' ],
languageOptions: {
parserOptions: {
tsconfigRootDir: __dirname,
project: [ './tsconfig.json', './scripts/tsconfig.json', './test/tsconfig.json' ],
},
},
rules: {
...typeAwareRules,
'ts/naming-convention': [
'error',
{
selector: 'default',
format: [ 'camelCase' ],
leadingUnderscore: 'forbid',
trailingUnderscore: 'forbid',
},
{
selector: 'import',
format: null,
},
{
selector: 'variable',
format: [ 'camelCase', 'UPPER_CASE' ],
leadingUnderscore: 'forbid',
trailingUnderscore: 'forbid',
},
{
selector: 'typeLike',
format: [ 'PascalCase' ],
},
{
selector: [ 'typeParameter' ],
format: [ 'PascalCase' ],
prefix: [ 'T' ],
},
],
'ts/no-floating-promises': [ 'error', { ignoreVoid: false }],
'ts/promise-function-async': 'error',
// These are not type specific, but we only care for TS files
'max-len': [ 'error', { code: 120, ignoreUrls: true }],
'unicorn/filename-case': [ 'error', {
cases: {
camelCase: true,
pascalCase: true,
kebabCase: false,
snakeCase: false,
},
}],
},
},
{
rules: {
// Might want to enable this one but has a drastic impact on the already existing code
'antfu/consistent-list-newline': 'off',
curly: [ 'error', 'all' ],
'function-paren-newline': [ 'error', 'consistent' ],
'jsdoc/no-multi-asterisks': [ 'error', { allowWhitespace: true }],
// Need to override `allow` value
'no-console': [ 'error', { allow: [ '' ]}],
'no-constructor-return': 'error',
'no-sync': [ 'error', { allowAtRootLevel: false }],
'node/prefer-global/buffer': 'off',
'node/prefer-global/process': 'off',
'require-unicode-regexp': 'error',
'sort-imports': [
'error',
{
allowSeparatedGroups: false,
ignoreCase: true,
ignoreDeclarationSort: true,
ignoreMemberSort: false,
memberSyntaxSortOrder: [ 'none', 'all', 'multiple', 'single' ],
},
],
'style/array-bracket-spacing': [ 'error', 'always', {
singleValue: true,
objectsInArrays: false,
arraysInArrays: false,
}],
// Conflicts with style/object-curly-spacing
'style/block-spacing': 'off',
'style/brace-style': [ 'error', '1tbs', { allowSingleLine: false }],
'style/member-delimiter-style': [ 'error', {
multiline: { delimiter: 'semi', requireLast: true },
singleline: { delimiter: 'semi', requireLast: false },
}],
'style/no-extra-parens': [ 'error', 'all', {
conditionalAssign: false,
enforceForArrowConditionals: false,
ignoreJSX: 'all',
nestedBinaryExpressions: false,
returnAssign: false,
}],
'style/object-curly-spacing': [ 'error', 'always', {
objectsInObjects: false,
arraysInObjects: false,
}],
'style/operator-linebreak': [ 'error', 'after' ],
'style/semi': [ 'error', 'always' ],
'style/space-before-function-paren': [ 'error', 'never' ],
'style/quote-props': [ 'error', 'as-needed', {
keywords: false,
unnecessary: true,
numbers: false,
}],
'style/yield-star-spacing': [ 'error', 'after' ],
'test/prefer-lowercase-title': 'off',
'ts/consistent-indexed-object-style': [ 'error', 'record' ],
'ts/consistent-type-definitions': 'off',
'ts/method-signature-style': 'error',
'ts/no-extraneous-class': [ 'error', {
allowConstructorOnly: false,
allowEmpty: false,
allowStaticOnly: false,
}],
'unicorn/consistent-function-scoping': 'error',
'unicorn/expiring-todo-comments': [ 'error', {
ignoreDatesOnPullRequests: false,
terms: [ 'todo' ],
allowWarningComments: false,
}],
'unicorn/no-process-exit': 'error',
'unicorn/no-useless-undefined': 'error',
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-node-protocol': 'off',
'unicorn/prefer-spread': 'error',
'unicorn/require-array-join-separator': 'error',
'unused-imports/no-unused-vars': [
'error',
{ args: 'after-used', vars: 'all', ignoreRestSiblings: true },
],
},
},
{
// Specifically for tests
// See https://github.com/jest-community/eslint-plugin-jest/issues/1408
plugins: {
jest,
},
files: [ 'test/**/*.ts' ],
rules: {
...jest.configs.all.rules,
// Rule is not smart enough to check called function in the test
'jest/expect-expect': 'off',
'jest/valid-title': [ 'error', {
mustNotMatch: {
describe: /\.$/u.source,
},
mustMatch: {
it: /\.$/u.source,
},
}],
// Default rules that are overkill
'jest/no-hooks': 'off',
'jest/max-expects': 'off',
'jest/prefer-expect-assertions': 'off',
'jest/prefer-lowercase-title': 'off',
'jest/prefer-strict-equal': 'off',
// Default rules that might be useful but would require too many files to be changed right now
'jest/no-conditional-in-test': 'off',
'jest/prefer-mock-promise-shorthand': 'off',
'jest/prefer-expect-resolves': 'off',
'jest/prefer-spy-on': 'off',
'jest/require-hook': 'off',
'jest/require-to-throw-message': 'off',
'ts/naming-convention': 'off',
'ts/no-unsafe-argument': 'off',
'ts/no-unsafe-assignment': 'off',
'ts/no-unsafe-call': 'off',
'ts/no-unsafe-member-access': 'off',
'ts/no-unsafe-return': 'off',
'ts/unbound-method': 'off',
// Incorrectly detects usage of undefined in "toHaveBeenLastCalledWith" checks
'unicorn/no-useless-undefined': 'off',
},
},
{
// JSON rules
files: [ '**/*.json' ],
rules: {
'jsonc/array-bracket-spacing': [ 'error', 'always', {
singleValue: true,
objectsInArrays: false,
arraysInArrays: false,
}],
},
},
{
// This is necessary to prevent filename checks caused by JSON being present in a README.
files: [ '**/README.md/**' ],
rules: {
'unicorn/filename-case': 'off',
},
},
);

View File

@ -46,15 +46,15 @@ const esModules = [
module.exports = {
transform: {
'^.+\\.ts$': [ 'ts-jest', {
tsconfig: '<rootDir>/test/tsconfig.json',
diagnostics: false,
isolatedModules: true,
tsconfig: '<rootDir>/test/tsconfig.json',
diagnostics: false,
isolatedModules: true,
}],
// This transformer converts ESM packages to CJS
'^.+node_modules.+\\.js$': 'jest-esm-transformer-2',
},
// By default, node_modules are not transformed, but we want to transform the ESM packages
transformIgnorePatterns: [`/node_modules/(?!(${esModules.join('|')})/)`],
transformIgnorePatterns: [ `/node_modules/(?!(${esModules.join('|')})/)` ],
testRegex: '/test/(unit|integration)/.*\\.test\\.ts$',
moduleFileExtensions: [
'ts',
@ -72,6 +72,6 @@ module.exports = {
// Slower machines had problems calling the WebSocket integration callbacks on time
testTimeout: 60000,
reporters: ci ? ['default', 'github-actions'] : ['default'],
...(ci && jestGithubRunnerSpecs()),
reporters: ci ? [ 'default', 'github-actions' ] : [ 'default' ],
...ci && jestGithubRunnerSpecs(),
};

7761
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,13 +2,29 @@
"name": "@solid/community-server",
"version": "7.0.1",
"description": "Community Solid Server: an open and modular implementation of the Solid specifications",
"license": "MIT",
"homepage": "https://github.com/CommunitySolidServer/CommunitySolidServer#readme",
"repository": "git@github.com:CommunitySolidServer/CommunitySolidServer.git",
"bugs": {
"url": "https://github.com/CommunitySolidServer/CommunitySolidServer/issues"
},
"keywords": [
"solid",
"linked-data",
"rdf",
"ldp"
],
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"bin": {
"community-solid-server": "bin/server.js"
},
"files": [
"bin",
"config",
"dist",
"templates"
],
"engines": {
"node": ">=18.0"
},
@ -23,16 +39,6 @@
"https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/dist/": "dist/",
"https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/templates/config/": "templates/config/"
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"bin": {
"community-solid-server": "bin/server.js"
},
"repository": "git@github.com:CommunitySolidServer/CommunitySolidServer.git",
"bugs": {
"url": "https://github.com/CommunitySolidServer/CommunitySolidServer/issues"
},
"homepage": "https://github.com/CommunitySolidServer/CommunitySolidServer#readme",
"scripts": {
"build": "npm run build:ts && npm run build:components",
"build:components": "componentsjs-generator -s src -c dist/components -r css -i .componentsignore",
@ -47,8 +53,8 @@
"docker:stop": "./test/docker/docker-stop.sh",
"typedocs": "typedoc --customCss ./documentation/typedoc.css",
"jest": "jest --coverageReporters text-summary --",
"lint": "npm run lint:ts && npm run lint:markdown",
"lint:ts": "eslint . --cache --ignore-path .gitignore --max-warnings 0",
"lint": "npm run lint:eslint && npm run lint:markdown",
"lint:eslint": "eslint . --cache --max-warnings 0",
"lint:markdown": "markdownlint-cli2",
"lint:markdown:fix": "markdownlint-cli2-fix",
"prepare": "npm run build",
@ -66,30 +72,6 @@
"validate": "componentsjs-compile-config urn:solid-server:default:Initializer -c config/default.json -f > /dev/null",
"watch": "nodemon --watch \"dist/**/*.js\" --exec npm start"
},
"husky": {
"hooks": {
"pre-commit": "npm run build && npm run lint && npm run test:unit && npm run test:integration",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"commit-and-tag-version": {
"scripts": {
"postbump": "ts-node ./scripts/upgradeConfig.ts",
"postchangelog": "ts-node ./scripts/formatChangelog.ts && markdownlint-cli2-fix"
},
"writerOpts": {
"commitsSort": false
},
"skip": {
"tag": true
}
},
"files": [
"bin",
"dist",
"config",
"templates"
],
"dependencies": {
"@comunica/context-entries": "^2.8.2",
"@comunica/query-sparql": "^2.9.0",
@ -105,7 +87,7 @@
"@types/fs-extra": "^11.0.2",
"@types/lodash.orderby": "^4.6.7",
"@types/mime-types": "^2.1.2",
"@types/n3": "^1.16.2",
"@types/n3": "^1.16.3",
"@types/node": "^18.18.4",
"@types/nodemailer": "^6.4.11",
"@types/oidc-provider": "^8.4.0",
@ -161,28 +143,18 @@
"yup": "^1.3.2"
},
"devDependencies": {
"@antfu/eslint-config": "^1.0.0-beta.27",
"@commitlint/cli": "^17.7.2",
"@commitlint/config-conventional": "^17.7.0",
"@inrupt/solid-client-authn-core": "^1.17.3",
"@inrupt/solid-client-authn-node": "^1.17.3",
"@microsoft/tsdoc-config": "^0.16.2",
"@tsconfig/node18": "^18.2.2",
"@types/jest": "^29.5.5",
"@types/set-cookie-parser": "^2.4.4",
"@types/supertest": "^2.0.14",
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0",
"commit-and-tag-version": "^11.3.0",
"componentsjs-generator": "^3.1.2",
"eslint": "^8.21.0",
"eslint-config-es": "4.1.0",
"eslint-import-resolver-typescript": "^3.2.5",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-tsdoc": "^0.2.14",
"eslint-plugin-unicorn": "^37.0.1",
"eslint-plugin-unused-imports": "^2.0.0",
"eslint-plugin-jest": "^27.4.3",
"husky": "^4.3.8",
"jest": "^29.7.0",
"jest-esm-transformer-2": "^1.0.0",
@ -197,5 +169,23 @@
"ts-node": "^10.9.1",
"typedoc": "^0.25.2",
"typescript": "^5.0.4"
},
"husky": {
"hooks": {
"pre-commit": "npm run build && npm run lint && npm run test:unit && npm run test:integration",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"commit-and-tag-version": {
"scripts": {
"postbump": "ts-node ./scripts/upgradeConfig.ts",
"postchangelog": "ts-node ./scripts/formatChangelog.ts && markdownlint-cli2-fix"
},
"writerOpts": {
"commitsSort": false
},
"skip": {
"tag": true
}
}
}

View File

@ -18,8 +18,10 @@ import { version } from '../package.json';
* and then pushes commit and tag.
*/
async function commitAndTag(): Promise<void> {
// eslint-disable-next-line ts/naming-convention
await simpleGit().commit([], 'CHANGELOG.md', { '--amend': null, '--no-edit': null, '--no-verify': null });
await simpleGit().addAnnotatedTag(`v${version}`, `Release Version ${version}`);
// eslint-disable-next-line ts/naming-convention
await simpleGit().push({ '--follow-tags': null });
}

View File

@ -1,9 +1,9 @@
{
"extends": "../tsconfig.json",
"include": [
"."
],
"compilerOptions": {
"resolveJsonModule": true
}
},
"include": [
"."
]
}

View File

@ -60,16 +60,16 @@ async function getFilePaths(path: string, regex: RegExp): Promise<string[]> {
* that file are included in the release commit).
*/
async function upgradeConfig(): Promise<void> {
const pkg = await readPackageJson();
const major = pkg.version.split('.')[0];
const pkg = await readPackageJson() as Record<string, unknown>;
const major = (pkg.version as string).split('.')[0];
console.log(`Changing ${pkg['lsd:module']} references to ${major}.0.0\n`);
console.log(`Changing ${pkg['lsd:module'] as string} references to ${major}.0.0\n`);
const configs = await getFilePaths('config/', /.+\.json/u);
configs.push(...await getFilePaths('test/integration/config/', /.+\.json/u));
configs.push(...await getFilePaths('templates/config/', /.+\.json/u));
const escapedName = escapeStringRegexp(pkg['lsd:module']);
const escapedName = escapeStringRegexp(pkg['lsd:module'] as string);
const regex = new RegExp(`(${escapedName}/)${/\^\d+\.\d+\.\d+/u.source}`, 'gmu');
for (const config of configs) {
@ -77,6 +77,7 @@ async function upgradeConfig(): Promise<void> {
}
await replaceComponentVersion('package.json', regex, `${major}.0.0`);
// eslint-disable-next-line ts/naming-convention
await simpleGit().commit(`chore(release): Update configs to v${major}.0.0`, configs, { '--no-verify': null });
}

View File

@ -1,7 +1,7 @@
import type {
IAccessControl,
IAccessControlResource,
IAccessControlledResource,
IAccessControlResource,
IAccessMode,
IMatcher,
IPolicy,

View File

@ -1,7 +1,7 @@
import { IdentifierMap } from '../util/map/IdentifierMap';
import type { PermissionReaderInput } from './PermissionReader';
import { PermissionReader } from './PermissionReader';
import type { PermissionSet, PermissionMap } from './permissions/Permissions';
import type { PermissionMap, PermissionSet } from './permissions/Permissions';
/**
* PermissionReader which sets all permissions to true or false

View File

@ -8,7 +8,7 @@ import type { PermissionReaderInput } from './PermissionReader';
import { PermissionReader } from './PermissionReader';
import { AclMode } from './permissions/AclPermissionSet';
import type { AclPermissionSet } from './permissions/AclPermissionSet';
import type { AccessMap, AccessMode, PermissionSet, PermissionMap } from './permissions/Permissions';
import type { AccessMap, AccessMode, PermissionMap, PermissionSet } from './permissions/Permissions';
/**
* Determines the permission for authorization resources (such as ACL or ACR).

View File

@ -6,7 +6,7 @@ import type { MapEntry } from '../util/map/MapUtil';
import { modify } from '../util/map/MapUtil';
import type { PermissionReaderInput } from './PermissionReader';
import { PermissionReader } from './PermissionReader';
import type { PermissionMap, PermissionSet, AccessMap } from './permissions/Permissions';
import type { AccessMap, PermissionMap, PermissionSet } from './permissions/Permissions';
import { AccessMode } from './permissions/Permissions';
/**

View File

@ -58,7 +58,6 @@ export class WebAclReader extends PermissionReader {
/**
* Checks if an agent is allowed to execute the requested actions.
* Will throw an error if this is not the case.
* @param input - Relevant data needed to check if access can be granted.
*/
public async handle({ credentials, requestedModes }: PermissionReaderInput): Promise<PermissionMap> {
// Determine the required access modes

View File

@ -16,7 +16,7 @@ import type { ResourceIdentifier } from './representation/ResourceIdentifier';
const VERSION = 'solid-0.1';
// eslint-disable-next-line @typescript-eslint/naming-convention
// eslint-disable-next-line ts/naming-convention
const WebSocketListenerEmitter = createGenericEventEmitterClass<GenericEventEmitter<'closed', () => void>>();
/**

View File

@ -9,6 +9,7 @@ import { guardedStreamFrom, readableToString } from '../../../util/StreamUtil';
import type { SparqlUpdatePatch } from '../../representation/SparqlUpdatePatch';
import type { BodyParserArgs } from './BodyParser';
import { BodyParser } from './BodyParser';
/**
* {@link BodyParser} that supports `application/sparql-update` content.
* Will convert the incoming update string to algebra in a {@link SparqlUpdatePatch}.

View File

@ -79,4 +79,3 @@ export class LinkRelObject {
}
}
}

View File

@ -3,9 +3,9 @@ import type { AcceptHeader } from '../../../util/Header';
import {
parseAccept,
parseAcceptCharset,
parseAcceptDateTime,
parseAcceptEncoding,
parseAcceptLanguage,
parseAcceptDateTime,
} from '../../../util/HeaderUtil';
import type { RepresentationPreferences } from '../../representation/RepresentationPreferences';
import { PreferenceParser } from './PreferenceParser';

View File

@ -5,7 +5,7 @@ import { guardStream } from '../../util/GuardedStream';
import { guardedStreamFrom } from '../../util/StreamUtil';
import type { Representation } from './Representation';
import type { MetadataIdentifier, MetadataRecord } from './RepresentationMetadata';
import { RepresentationMetadata, isRepresentationMetadata } from './RepresentationMetadata';
import { isRepresentationMetadata, RepresentationMetadata } from './RepresentationMetadata';
/**
* Class with various constructors to facilitate creating a representation.
@ -108,6 +108,8 @@ export class BasicRepresentation implements Representation {
metadataRest = undefined;
}
if (!isRepresentationMetadata(metadata) || typeof metadataRest === 'string') {
// This combination will always match with a valid overload
// eslint-disable-next-line ts/no-unsafe-argument
metadata = new RepresentationMetadata(metadata as any, metadataRest as any);
}
this.metadata = metadata;

View File

@ -2,8 +2,8 @@ import { DataFactory, Store } from 'n3';
import type { BlankNode, DefaultGraph, Literal, NamedNode, Quad, Term } from 'rdf-js';
import { getLoggerFor } from '../../logging/LogUtil';
import { ContentType, SIMPLE_MEDIA_RANGE } from '../../util/Header';
import { toNamedTerm, toObjectTerm, isTerm, toLiteral } from '../../util/TermUtil';
import { CONTENT_TYPE_TERM, CONTENT_LENGTH_TERM, XSD, SOLID_META, RDFS } from '../../util/Vocabularies';
import { isTerm, toLiteral, toNamedTerm, toObjectTerm } from '../../util/TermUtil';
import { CONTENT_LENGTH_TERM, CONTENT_TYPE_TERM, RDFS, SOLID_META, XSD } from '../../util/Vocabularies';
import type { ResourceIdentifier } from './ResourceIdentifier';
import { isResourceIdentifier } from './ResourceIdentifier';
@ -16,7 +16,7 @@ export type MetadataGraph = NamedNode | BlankNode | DefaultGraph | string;
* Determines whether the object is a `RepresentationMetadata`.
*/
export function isRepresentationMetadata(object: any): object is RepresentationMetadata {
return typeof object?.setMetadata === 'function';
return typeof (object as RepresentationMetadata)?.setMetadata === 'function';
}
// Caches named node conversions
@ -283,7 +283,8 @@ export class RepresentationMetadata {
): boolean {
// This works with N3.js but at the time of writing the typings have not been updated yet.
// If you see this line of code check if the typings are already correct and update this if so.
return (this.store.has as any)(this.id, predicate, object, graph);
// eslint-disable-next-line ts/no-unsafe-call
return (this.store.has as any)(this.id, predicate, object, graph) as boolean;
}
/**
@ -426,8 +427,8 @@ export class RepresentationMetadata {
}
/**
* Shorthand for the CONTENT_LENGTH predicate.
*/
* Shorthand for the CONTENT_LENGTH predicate.
*/
public get contentLength(): number | undefined {
const length = this.get(CONTENT_LENGTH_TERM);
return length?.value ? Number(length.value) : undefined;

View File

@ -1,16 +1,16 @@
/**
* Represents preferred values along a single content negotiation dimension.
*
* The number represents how preferred this value is from 0 to 1.
* Follows the quality values rule from RFC 7231:
* "The weight is normalized to a real number in the range 0 through 1,
* where 0.001 is the least preferred and 1 is the most preferred; a
* value of 0 means "not acceptable"."
*
* Because of an open issue in Components.js we cannot use `Record<string, number>` right now.
* https://github.com/LinkedSoftwareDependencies/Components-Generator.js/issues/103
*/
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
* Represents preferred values along a single content negotiation dimension.
*
* The number represents how preferred this value is from 0 to 1.
* Follows the quality values rule from RFC 7231:
* "The weight is normalized to a real number in the range 0 through 1,
* where 0.001 is the least preferred and 1 is the most preferred; a
* value of 0 means "not acceptable"."
*
* Because of an open issue in Components.js we cannot use `Record<string, number>` right now.
* https://github.com/LinkedSoftwareDependencies/Components-Generator.js/issues/103
*/
// eslint-disable-next-line ts/consistent-indexed-object-style
export type ValuePreferences = {[key: string ]: number };
/**

View File

@ -11,6 +11,6 @@ export interface ResourceIdentifier {
/**
* Determines whether the object is a {@link ResourceIdentifier}.
*/
export function isResourceIdentifier(object: any): object is ResourceIdentifier {
return object && (typeof object.path === 'string');
export function isResourceIdentifier(object: unknown): object is ResourceIdentifier {
return Boolean(object) && (typeof (object as ResourceIdentifier).path === 'string');
}

View File

@ -7,7 +7,7 @@ import { createErrorMessage } from '../util/errors/ErrorUtil';
import { SOLID_HTTP } from '../util/Vocabularies';
import type { ProviderFactory } from './configuration/ProviderFactory';
import type { CookieStore } from './interaction/account/util/CookieStore';
import type { InteractionHandler, Interaction } from './interaction/InteractionHandler';
import type { Interaction, InteractionHandler } from './interaction/InteractionHandler';
export interface IdentityProviderHttpHandlerArgs {
/**

View File

@ -10,11 +10,8 @@ import type { CanBePromise } from '../../templates/types/oidc-provider';
* This can be detected via the env variables: https://jestjs.io/docs/environment-variables.
* There have been reports of `JEST_WORKER_ID` being undefined, so to be sure we check both.
*/
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
export function importOidcProvider(): CanBePromise<typeof import('../../templates/types/oidc-provider')> {
// eslint-disable-next-line no-process-env
if (process.env.JEST_WORKER_ID ?? process.env.NODE_ENV === 'test') {
// eslint-disable-next-line no-undef
return jest.requireActual('oidc-provider');
}
return import('oidc-provider');

View File

@ -28,7 +28,7 @@ export class OidcHttpHandler extends HttpHandler {
this.logger.debug(`Sending request to oidc-provider: ${request.url}`);
// Even though the typings do not indicate this, this is a Promise that needs to be awaited.
// Otherwise, the `BaseHttpServerFactory` will write a 404 before the OIDC library could handle the response.
// eslint-disable-next-line @typescript-eslint/await-thenable
// eslint-disable-next-line ts/await-thenable
await provider.callback()(request, response);
}
}

View File

@ -1,7 +1,7 @@
import { createPublicKey } from 'crypto';
import type { KeyObject } from 'crypto';
import { exportJWK, generateKeyPair, importJWK } from 'jose';
import type { JWKS, AsymmetricSigningAlgorithm } from '../../../templates/types/oidc-provider';
import type { AsymmetricSigningAlgorithm, JWKS } from '../../../templates/types/oidc-provider';
import type { KeyValueStorage } from '../../storage/keyvalue/KeyValueStorage';
import type { AlgJwk, JwkGenerator } from './JwkGenerator';

View File

@ -1,16 +1,14 @@
/* eslint-disable @typescript-eslint/naming-convention, tsdoc/syntax */
// import/no-unresolved can't handle jose imports
// tsdoc/syntax can't handle {json} parameter
/* eslint-disable ts/naming-convention */
import { randomBytes } from 'crypto';
import type { Account,
Adapter,
AsymmetricSigningAlgorithm,
Configuration,
ErrorOut,
errors,
KoaContextWithOIDC,
ResourceServer,
UnknownObject,
errors } from '../../../templates/types/oidc-provider';
UnknownObject } from '../../../templates/types/oidc-provider';
import type Provider from '../../../templates/types/oidc-provider';
import type { ErrorHandler } from '../../http/output/error/ErrorHandler';
import type { ResponseWriter } from '../../http/output/ResponseWriter';
@ -56,9 +54,9 @@ export interface IdentityProviderFactoryArgs {
*/
clientCredentialsStore: ClientCredentialsStore;
/**
* Storage used to store cookie keys so they can be re-used in case of multithreading.
* Storage used to store cookie keys, so they can be re-used in case of multithreading.
*/
storage: KeyValueStorage<string, unknown>;
storage: KeyValueStorage<string, string[]>;
/**
* Generates the JWK used for signing and decryption.
*/
@ -82,7 +80,7 @@ const COOKIES_KEY = 'cookie-secret';
/**
* Creates an OIDC Provider based on the provided configuration and parameters.
* The provider will be cached and returned on subsequent calls.
* Cookie and JWT keys will be stored in an internal storage so they can be re-used over multiple threads.
* Cookie and JWT keys will be stored in an internal storage, so they can be re-used over multiple threads.
* Necessary claims for Solid OIDC interactions will be added.
* Routes will be updated based on the `baseUrl` and `oidcPath`.
*/
@ -96,7 +94,7 @@ export class IdentityProviderFactory implements ProviderFactory {
private readonly oidcPath: string;
private readonly interactionRoute: InteractionRoute;
private readonly clientCredentialsStore: ClientCredentialsStore;
private readonly storage: KeyValueStorage<string, unknown>;
private readonly storage: KeyValueStorage<string, string[]>;
private readonly jwkGenerator: JwkGenerator;
private readonly showStackTrace: boolean;
private readonly errorHandler: ErrorHandler;
@ -156,6 +154,7 @@ export class IdentityProviderFactory implements ProviderFactory {
await this.promptFactory.handleSafe(policy);
config.interactions!.policy = policy;
// eslint-disable-next-line new-cap
const provider = new oidcImport.default(this.baseUrl, config);
// Allow provider to interpret reverse proxy headers.
@ -187,12 +186,12 @@ export class IdentityProviderFactory implements ProviderFactory {
const accepts = ctx.accepts.bind(ctx);
// Using `any` typings to make sure we support all different versions of `ctx.accepts`
ctx.accepts = (...types: any[]): any => {
ctx.accepts = (...types): any => {
// Make sure we only override our specific case
if (types.length === 2 && types[0] === 'json' && types[1] === 'html') {
return 'html';
}
return accepts(...types);
return accepts(...types as string[]);
};
return next();
@ -205,7 +204,7 @@ export class IdentityProviderFactory implements ProviderFactory {
*/
private async initConfig(key: AlgJwk): Promise<Configuration> {
// Create a deep copy
const config: Configuration = JSON.parse(JSON.stringify(this.config));
const config = JSON.parse(JSON.stringify(this.config)) as Configuration;
// Indicates which Adapter should be used for storing oidc data
// The adapter function MUST be a named function.
@ -254,10 +253,10 @@ export class IdentityProviderFactory implements ProviderFactory {
/**
* Checks if the given token is an access token.
* The AccessToken interface is not exported so we have to access it like this.
* The AccessToken interface is not exported, so we have to access it like this.
*/
private isAccessToken(token: any): token is KoaContextWithOIDC['oidc']['accessToken'] {
return token.kind === 'AccessToken';
return (token as KoaContextWithOIDC['oidc']['accessToken'])?.kind === 'AccessToken';
}
/**

View File

@ -36,9 +36,9 @@ export class LockingInteractionHandler extends InteractionHandler {
const identifier = { path: this.accountRoute.getPath({ accountId }) };
if (READ_METHODS.has(operation.method)) {
return this.locker.withReadLock(identifier, (): Promise<Representation> => this.source.handle(input));
return this.locker.withReadLock(identifier, async(): Promise<Representation> => this.source.handle(input));
}
return this.locker.withWriteLock(identifier, (): Promise<Representation> => this.source.handle(input));
return this.locker.withWriteLock(identifier, async(): Promise<Representation> => this.source.handle(input));
}
}

View File

@ -1,6 +1,4 @@
/* eslint-disable tsdoc/syntax */
import type { Json, JsonRepresentation } from './InteractionUtil';
// Tsdoc/syntax cannot handle `@range`
import { JsonInteractionHandler } from './JsonInteractionHandler';
/**

View File

@ -11,7 +11,7 @@ import Dict = NodeJS.Dict;
// which would break the pod creation causing us to have an incomplete pod.
export const URL_SCHEMA = string().trim().optional().test({
name: 'url',
message: (value): string => `"${value.value}" is not a valid URL`,
message: (value: { value: string }): string => `"${value.value}" is not a valid URL`,
test(value): boolean {
if (!value) {
return true;
@ -61,6 +61,7 @@ export function parseSchema<T extends ObjectSchema<any>>(schema: T): Pick<Schema
export async function validateWithError<T extends ObjectSchema<any>>(schema: T, data: unknown,
options?: ValidateOptions<any>): Promise<T['__outputType']> {
try {
// eslint-disable-next-line ts/no-unsafe-return
return await schema.validate(data, options);
} catch (error: unknown) {
throw new BadRequestHttpError(createErrorMessage(error));

View File

@ -5,7 +5,7 @@ export const ACCOUNT_SETTINGS_REMEMBER_LOGIN = 'rememberLogin';
export type AccountSettings = { [ACCOUNT_SETTINGS_REMEMBER_LOGIN]?: boolean };
/* eslint-disable @typescript-eslint/method-signature-style */
/* eslint-disable ts/method-signature-style */
/**
* Used to store account data.
*/

View File

@ -3,7 +3,7 @@ import { getLoggerFor } from '../../../../logging/LogUtil';
import type { ValueType } from '../../../../storage/keyvalue/IndexedStorage';
import { createErrorMessage } from '../../../../util/errors/ErrorUtil';
import { InternalServerError } from '../../../../util/errors/InternalServerError';
import type { AccountStore, AccountSettings } from './AccountStore';
import type { AccountSettings, AccountStore } from './AccountStore';
import { ACCOUNT_SETTINGS_REMEMBER_LOGIN } from './AccountStore';
import type { AccountLoginStorage } from './LoginStorage';
import { ACCOUNT_TYPE } from './LoginStorage';
@ -24,7 +24,7 @@ export class BaseAccountStore extends Initializer implements AccountStore {
public constructor(storage: AccountLoginStorage<any>) {
super();
this.storage = storage;
this.storage = storage as typeof this.storage;
}
// Initialize the type definitions

View File

@ -1,9 +1,9 @@
import { getLoggerFor } from '../../../../logging/LogUtil';
import type { CreateTypeObject,
TypeObject,
StringKey,
IndexedQuery,
IndexedStorage,
IndexTypeCollection, IndexedQuery, ValueType } from '../../../../storage/keyvalue/IndexedStorage';
IndexTypeCollection,
StringKey, TypeObject, ValueType } from '../../../../storage/keyvalue/IndexedStorage';
import { BadRequestHttpError } from '../../../../util/errors/BadRequestHttpError';
import { NotFoundHttpError } from '../../../../util/errors/NotFoundHttpError';
import type { LoginStorage } from './LoginStorage';
@ -145,6 +145,7 @@ export class BaseLoginAccountStorage<T extends IndexTypeCollection<T>> implement
* it doesn't have a login method when the timer runs out.
*/
protected createAccountTimeout(id: string): void {
// eslint-disable-next-line ts/no-misused-promises
const timer = setTimeout(async(): Promise<void> => {
const account = await this.storage.get(ACCOUNT_TYPE, id);
if (account && account[LOGIN_COUNT] === 0) {
@ -181,7 +182,7 @@ export class BaseLoginAccountStorage<T extends IndexTypeCollection<T>> implement
/**
* Removes the field that keeps track of the login counts, to hide this from the output.
*/
protected cleanOutput<TVal extends Record<string, unknown> | undefined>(value: TVal): TVal {
protected cleanOutput<TVal extends Record<string, unknown> | undefined>(this: void, value: TVal): TVal {
if (value) {
delete value[LOGIN_COUNT];
}

View File

@ -1,6 +1,6 @@
import type { ValueTypeDescription,
IndexedStorage,
StringKey, IndexTypeCollection } from '../../../../storage/keyvalue/IndexedStorage';
import type { IndexedStorage,
IndexTypeCollection,
StringKey, ValueTypeDescription } from '../../../../storage/keyvalue/IndexedStorage';
export const ACCOUNT_TYPE = 'account';

View File

@ -1,7 +1,7 @@
import type { Adapter, AdapterPayload } from '../../../../templates/types/oidc-provider';
import { getLoggerFor } from '../../../logging/LogUtil';
import type { AdapterFactory } from '../../storage/AdapterFactory';
import { PassthroughAdapterFactory, PassthroughAdapter } from '../../storage/PassthroughAdapterFactory';
import { PassthroughAdapter, PassthroughAdapterFactory } from '../../storage/PassthroughAdapterFactory';
import type { WebIdStore } from '../webid/util/WebIdStore';
import type { ClientCredentialsStore } from './util/ClientCredentialsStore';
@ -44,7 +44,7 @@ export class ClientCredentialsAdapter extends PassthroughAdapter {
this.logger.debug(`Authenticating as ${credentials.webId} using client credentials`);
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable ts/naming-convention */
payload = {
client_id: label,
client_secret: credentials.secret,
@ -52,7 +52,7 @@ export class ClientCredentialsAdapter extends PassthroughAdapter {
redirect_uris: [],
response_types: [],
};
/* eslint-enable @typescript-eslint/naming-convention */
/* eslint-enable ts/naming-convention */
}
return payload;
}

View File

@ -29,7 +29,7 @@ export class BaseClientCredentialsStore extends Initializer implements ClientCre
public constructor(storage: AccountLoginStorage<any>) {
super();
this.storage = storage;
this.storage = storage as typeof this.storage;
}
// Initialize the type definitions

View File

@ -62,7 +62,7 @@ export abstract class ResolveLoginHandler extends JsonInteractionHandler {
// We are not reusing this cookie as it could be associated with a different account.
const oldCookie = input.metadata.get(SOLID_HTTP.terms.accountCookie)?.value;
if (oldCookie) {
this.logger.debug(`Replacing old cookie ${oldCookie} with ${json.cookie}`);
this.logger.debug(`Replacing old cookie ${oldCookie} with ${json.cookie as string}`);
await this.cookieStore.delete(oldCookie);
}

View File

@ -12,7 +12,7 @@ export class CancelOidcHandler extends JsonInteractionHandler<never> {
assertOidcInteraction(oidcInteraction);
const error = {
error: 'access_denied',
// eslint-disable-next-line @typescript-eslint/naming-convention
// eslint-disable-next-line ts/naming-convention
error_description: 'User cancelled the interaction.',
};

View File

@ -41,6 +41,7 @@ export class ClientInfoHandler extends JsonInteractionHandler<OutType> {
const jsonLd = Object.fromEntries(
CLIENT_KEYS.filter((key): boolean => key in metadata)
.map((key): [ KeyType, ValType ] => [ key, metadata[key] ]),
// eslint-disable-next-line ts/naming-convention
) as Record<KeyType, ValType> & { '@context': 'https://www.w3.org/ns/solid/oidc-context.jsonld' };
jsonLd['@context'] = 'https://www.w3.org/ns/solid/oidc-context.jsonld';

View File

@ -1,4 +1,4 @@
import { hash, compare } from 'bcryptjs';
import { compare, hash } from 'bcryptjs';
import { Initializer } from '../../../../init/Initializer';
import { getLoggerFor } from '../../../../logging/LogUtil';
import { BadRequestHttpError } from '../../../../util/errors/BadRequestHttpError';
@ -31,7 +31,7 @@ export class BasePasswordStore extends Initializer implements PasswordStore {
public constructor(storage: AccountLoginStorage<any>, saltRounds = 10) {
super();
this.storage = storage;
this.storage = storage as typeof this.storage;
this.saltRounds = saltRounds;
}

View File

@ -45,7 +45,7 @@ export class BasePodStore extends Initializer implements PodStore {
public constructor(storage: AccountLoginStorage<any>, manager: PodManager, visible = false) {
super();
this.storage = storage;
this.storage = storage as typeof this.storage;
this.visible = visible;
this.manager = manager;
}

View File

@ -25,7 +25,7 @@ export class BaseWebIdStore extends Initializer implements WebIdStore {
public constructor(storage: AccountLoginStorage<any>) {
super();
this.storage = storage;
this.storage = storage as typeof this.storage;
}
// Initialize the type definitions

View File

@ -8,6 +8,7 @@ import { errorTermsToMetadata } from '../../util/errors/HttpErrorUtil';
import { fetchDataset } from '../../util/FetchUtil';
import { SOLID } from '../../util/Vocabularies';
import { OwnershipValidator } from './OwnershipValidator';
const { literal, namedNode, quad } = DataFactory;
/**

View File

@ -46,9 +46,9 @@ export class ClientIdAdapter extends PassthroughAdapter {
throw new Error(`Unable to access data at ${id}: ${await response.text()}`);
}
const data = await response.text();
let json: any | undefined;
let json: Record<string, unknown> | undefined;
try {
json = JSON.parse(data);
json = JSON.parse(data) as Record<string, unknown>;
const contexts = Array.isArray(json['@context']) ? json['@context'] : [ json['@context'] ];
// We can only parse as simple JSON if the @context is correct
if (!contexts.includes('https://www.w3.org/ns/solid/oidc-context.jsonld')) {
@ -71,7 +71,7 @@ export class ClientIdAdapter extends PassthroughAdapter {
}
// `token_endpoint_auth_method: 'none'` prevents oidc-provider from requiring a client_secret
// eslint-disable-next-line @typescript-eslint/naming-convention
// eslint-disable-next-line ts/naming-convention
payload = { ...payload, token_endpoint_auth_method: 'none' };
}
@ -97,12 +97,12 @@ export class ClientIdAdapter extends PassthroughAdapter {
}
}
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable ts/naming-convention */
return {
client_id: id,
redirect_uris: redirectUris,
};
/* eslint-enable @typescript-eslint/naming-convention */
/* eslint-enable ts/naming-convention */
}
}

View File

@ -9,7 +9,7 @@ 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, joinFilePath } from '../util/PathUtil';
import { joinFilePath, resolveAssetPath, resolveModulePath } from '../util/PathUtil';
import type { App } from './App';
import type { CliExtractor } from './cli/CliExtractor';
import type { CliResolver } from './CliResolver';
@ -100,10 +100,10 @@ export class AppRunner {
try {
componentsManager = await this.createComponentsManager<any>(loaderProperties, configs);
} catch (error: unknown) {
this.resolveError(`Could not build the config files from ${configs}`, error);
this.resolveError(`Could not build the config files from ${configs.join(',')}`, error);
}
const cliResolver = await this.createCliResolver(componentsManager);
const cliResolver = await this.createCliResolver(componentsManager as ComponentsManager<CliResolver>);
let extracted: Shorthand = {};
if (input.argv) {
extracted = await this.extractShorthand(cliResolver.cliExtractor, input.argv);
@ -115,7 +115,8 @@ export class AppRunner {
// Create the application using the translated variable values.
// `variableBindings` override those resolved from the `shorthand` input.
return this.createApp(componentsManager, { ...parsedVariables, ...input.variableBindings });
return this.createApp(componentsManager as ComponentsManager<App>,
{ ...parsedVariables, ...input.variableBindings });
}
/**
@ -126,8 +127,9 @@ export class AppRunner {
* This is only relevant when this is used to start as a Node.js application on its own,
* if you use this as part of your code you probably want to use the async version.
*
* @param argv - Command line arguments.
* @param stderr - Stream that should be used to output errors before the logger is enabled.
* @param argv - Input parameters.
* @param argv.argv - Command line arguments.
* @param argv.stderr - Stream that should be used to output errors before the logger is enabled.
*/
public runCliSync({ argv, stderr = process.stderr }: { argv?: CliArgv; stderr?: WriteStream }): void {
this.runCli(argv).catch((error): never => {
@ -203,20 +205,20 @@ export class AppRunner {
// 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);
return readJSON(cssConfigPath) as Promise<Record<string, unknown>>;
}
// 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);
return import(cssConfigPathJs) as Promise<Record<string, unknown>>;
}
// Finally try and read from the config.community-solid-server
// field in the root package.json
const pkg = await readJSON(packageJsonPath);
const pkg = await readJSON(packageJsonPath) as { config?: Record<string, any> };
if (typeof pkg.config?.['community-solid-server'] === 'object') {
return pkg.config['community-solid-server'];
return pkg.config['community-solid-server'] as Record<string, unknown>;
}
}

View File

@ -20,6 +20,6 @@ export class ModuleVersionVerifier extends Initializer {
public async handle(): Promise<void> {
const pkg = await readPackageJson();
await this.storage.set(this.storageKey, pkg.version);
await this.storage.set(this.storageKey, pkg.version as string);
}
}

View File

@ -33,7 +33,7 @@ export class ServerInitializer extends Initializer implements Finalizable {
this.server = await this.serverFactory.createServer();
if (this.socketPath) {
this.logger.info(`Listening to server at ${this.server.address()}`);
this.logger.info(`Listening to server at ${this.server.address() as string}`);
this.server.listen(this.socketPath);
} else {
const url = new URL(`http${isHttpsServer(this.server) ? 's' : ''}://localhost:${this.port}/`).href;

View File

@ -1,4 +1,3 @@
/* eslint-disable tsdoc/syntax */
import type { Arguments, Argv, Options } from 'yargs';
import yargs from 'yargs';
import { CliExtractor } from './CliExtractor';
@ -77,6 +76,7 @@ export class YargsCliExtractor extends CliExtractor {
yArgv.check((args): boolean => {
for (const [ name, options ] of Object.entries(this.yargsArgOptions)) {
if (options.type !== 'array' && Array.isArray(args[name])) {
// eslint-disable-next-line ts/restrict-template-expressions
throw new Error(`Multiple values for --${name} (-${options.alias}) were provided where only one is allowed`);
}
}

View File

@ -13,7 +13,7 @@ enum ClusterMode {
/** Single threaded mode, no clustering */
singleThreaded,
/** Fixed amount of workers being forked. (limited to core_count) */
fixed
fixed,
}
/**

View File

@ -23,7 +23,7 @@ Promise<string> {
skipValidation: true,
});
// The keys of the package.json `lsd:contexts` array contains all the IRIs of the relevant contexts;
const lsdContexts = Object.keys(pkg['lsd:contexts']);
const lsdContexts = Object.keys(pkg['lsd:contexts'] as Record<string, string>);
// Feed the lsd:context IRIs to the ContextParser
const cssContext = await contextParser.parse(lsdContexts);
// We can now expand a simple interface name, to its full Components.js type identifier.

View File

@ -34,7 +34,7 @@ export class SingleContainerJsonStorage<T> extends JsonResourceStorage<T> {
continue;
}
const json = JSON.parse(await readableToString(document.data));
const json = JSON.parse(await readableToString(document.data)) as T;
const key = this.identifierToKey(documentId);
yield [ key, json ];
}

View File

@ -113,7 +113,7 @@ export class V6MigrationInitializer extends Initializer {
this.accountStorage = args.accountStorage;
this.clientCredentialsStorage = args.clientCredentialsStorage;
this.cleanupStorages = args.cleanupStorages;
this.newAccountStorage = args.newAccountStorage;
this.newAccountStorage = args.newAccountStorage as AccountLoginStorage<typeof STORAGE_DESCRIPTION>;
this.newSetupStorage = args.newSetupStorage;
}

View File

@ -21,7 +21,7 @@ export class AssetPathExtractor extends ShorthandExtractor {
const path = args[this.key] ?? this.defaultPath;
if (path) {
if (typeof path !== 'string') {
throw new Error(`Invalid ${this.key} argument`);
throw new TypeError(`Invalid ${this.key} argument`);
}
return resolveAssetPath(path);

View File

@ -19,7 +19,7 @@ export class BaseUrlExtractor extends ShorthandExtractor {
return ensureTrailingSlash(args.baseUrl);
}
if (typeof args.socket === 'string') {
throw new Error('BaseUrl argument should be provided when using Unix Domain Sockets.');
throw new TypeError('BaseUrl argument should be provided when using Unix Domain Sockets.');
}
const port = (args.port as string) ?? this.defaultPort;
const url = new URL('http://localhost/');

View File

@ -75,7 +75,7 @@ export class LazyLoggerFactory implements LoggerFactory {
public get loggerFactory(): LoggerFactory {
if (this.factory instanceof TemporaryLoggerFactory) {
throw new Error('Logger factory not yet set.');
throw new TypeError('Logger factory not yet set.');
}
return this.factory;
}

View File

@ -1,12 +1,10 @@
import { BaseLogger } from './Logger';
import type { LogLevel } from './LogLevel';
/**
* A logger that does nothing on a log message.
*/
export class VoidLogger extends BaseLogger {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public log(level: LogLevel, message: string, meta?: any): this {
public log(): this {
// Do nothing
return this;
}

Some files were not shown because too many files have changed in this diff Show More