mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Improve vocabulary typings
This commit is contained in:
parent
4b39b50b0c
commit
2e1bae90c7
@ -22,6 +22,7 @@ The following changes are relevant for v5 custom configs that replaced certain f
|
|||||||
### Interface changes
|
### Interface changes
|
||||||
These changes are relevant if you wrote custom modules for the server that depend on existing interfaces.
|
These changes are relevant if you wrote custom modules for the server that depend on existing interfaces.
|
||||||
- `AgentGroupAccessChecker` no longer accepts any input parameters.
|
- `AgentGroupAccessChecker` no longer accepts any input parameters.
|
||||||
|
- The functions in `Vocabularies.ts` were renamed, the typings have been made more precise and several utility types were added.
|
||||||
|
|
||||||
## v5.0.0
|
## v5.0.0
|
||||||
### New features
|
### New features
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { createUriAndTermNamespace } from '../../../util/Vocabularies';
|
import { createVocabulary } from '../../../util/Vocabularies';
|
||||||
|
|
||||||
export const TEMPLATE = createUriAndTermNamespace('urn:solid-server:template:',
|
export const TEMPLATE = createVocabulary('urn:solid-server:template:',
|
||||||
'ResourceStore');
|
'ResourceStore');
|
||||||
|
|
||||||
// Variables used for configuration templates
|
// Variables used for configuration templates
|
||||||
// This is not an exclusive list
|
// This is not an exclusive list
|
||||||
export const TEMPLATE_VARIABLE = createUriAndTermNamespace(`${TEMPLATE.namespace}variable:`,
|
export const TEMPLATE_VARIABLE = createVocabulary(`${TEMPLATE.namespace}variable:`,
|
||||||
'baseUrl',
|
'baseUrl',
|
||||||
'rootFilePath',
|
'rootFilePath',
|
||||||
'sparqlEndpoint',
|
'sparqlEndpoint',
|
||||||
|
@ -2,46 +2,77 @@
|
|||||||
import { DataFactory } from 'n3';
|
import { DataFactory } from 'n3';
|
||||||
import type { NamedNode } from 'rdf-js';
|
import type { NamedNode } from 'rdf-js';
|
||||||
|
|
||||||
type RecordOf<TKey extends any[], TValue> = Record<TKey[number], TValue>;
|
/**
|
||||||
|
* A `Record` in which each value is a concatenation of the baseUrl and its key.
|
||||||
|
*/
|
||||||
|
type ExpandedRecord<TBase extends string, TLocal extends string> = {[K in TLocal]: `${TBase}${K}` };
|
||||||
|
|
||||||
export type Namespace<TKey extends any[], TValue> =
|
/**
|
||||||
{ namespace: TValue } & RecordOf<TKey, TValue>;
|
* Has a base URL as `namespace` value and each key has as value the concatenation with that base URL.
|
||||||
|
*/
|
||||||
|
type ValueVocabulary<TBase extends string, TLocal extends string> =
|
||||||
|
{ namespace: TBase } & ExpandedRecord<TBase, TLocal>;
|
||||||
|
/**
|
||||||
|
* A {@link ValueVocabulary} where the URI values are {@link NamedNode}s.
|
||||||
|
*/
|
||||||
|
type TermVocabulary<T> = T extends ValueVocabulary<any, any> ? {[K in keyof T]: NamedNode<T[K]> } : never;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a namespace and keys linking to the entries in this namespace.
|
||||||
|
* The `terms` field contains the same values but as {@link NamedNode} instead of string.
|
||||||
|
*/
|
||||||
|
export type Vocabulary<TBase extends string, TKey extends string> =
|
||||||
|
ValueVocabulary<TBase, TKey> & { terms: TermVocabulary<ValueVocabulary<TBase, TKey>> };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Vocabulary} where all the non-namespace fields are of unknown value.
|
||||||
|
* This is a fallback in case {@link createVocabulary} gets called with a non-strict string array.
|
||||||
|
*/
|
||||||
|
export type PartialVocabulary<TBase extends string> =
|
||||||
|
{ namespace: TBase } &
|
||||||
|
Partial<Record<string, string>> &
|
||||||
|
{ terms: { namespace: NamedNode<TBase> } & Partial<Record<string, NamedNode>> };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A local name of a {@link Vocabulary}.
|
||||||
|
*/
|
||||||
|
export type VocabularyLocal<T> = T extends Vocabulary<any, infer TKey> ? TKey : never;
|
||||||
|
/**
|
||||||
|
* A URI string entry of a {@link Vocabulary}.
|
||||||
|
*/
|
||||||
|
export type VocabularyValue<T> = T extends Vocabulary<any, infer TKey> ? T[TKey] : never;
|
||||||
|
/**
|
||||||
|
* A {@link NamedNode} entry of a {@link Vocabulary}.
|
||||||
|
*/
|
||||||
|
export type VocabularyTerm<T> = T extends Vocabulary<any, infer TKey> ? T['terms'][TKey] : never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a function that expands local names from the given base URI,
|
* Creates a function that expands local names from the given base URI,
|
||||||
* and exports the given local names as properties on the returned object.
|
* and exports the given local names as properties on the returned object.
|
||||||
*/
|
*/
|
||||||
export function createNamespace<TKey extends string, TValue>(
|
function createValueVocabulary<TBase extends string, TLocal extends string>(baseUri: TBase, localNames: TLocal[]):
|
||||||
baseUri: string,
|
ValueVocabulary<TBase, TLocal> {
|
||||||
toValue: (expanded: string) => TValue,
|
const expanded: Partial<ExpandedRecord<TBase, TLocal>> = { };
|
||||||
...localNames: TKey[]):
|
|
||||||
Namespace<typeof localNames, TValue> {
|
|
||||||
const expanded: Namespace<typeof localNames, TValue> = {} as any;
|
|
||||||
// Expose the main namespace
|
|
||||||
expanded.namespace = toValue(baseUri);
|
|
||||||
// Expose the listed local names as properties
|
// Expose the listed local names as properties
|
||||||
for (const localName of localNames) {
|
for (const localName of localNames) {
|
||||||
(expanded as RecordOf<TKey[], TValue>)[localName] = toValue(`${baseUri}${localName}`);
|
expanded[localName] = `${baseUri}${localName}`;
|
||||||
}
|
}
|
||||||
return expanded;
|
return {
|
||||||
}
|
namespace: baseUri,
|
||||||
|
...expanded as ExpandedRecord<TBase, TLocal>,
|
||||||
/**
|
};
|
||||||
* Creates a function that expands local names from the given base URI into strings,
|
|
||||||
* and exports the given local names as properties on the returned object.
|
|
||||||
*/
|
|
||||||
export function createUriNamespace<T extends string>(baseUri: string, ...localNames: T[]):
|
|
||||||
Namespace<typeof localNames, string> {
|
|
||||||
return createNamespace(baseUri, (expanded): string => expanded, ...localNames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a function that expands local names from the given base URI into named nodes,
|
* Creates a function that expands local names from the given base URI into named nodes,
|
||||||
* and exports the given local names as properties on the returned object.
|
* and exports the given local names as properties on the returned object.
|
||||||
*/
|
*/
|
||||||
export function createTermNamespace<T extends string>(baseUri: string, ...localNames: T[]):
|
function createTermVocabulary<TBase extends string, TLocal extends string>(namespace: ValueVocabulary<TBase, TLocal>):
|
||||||
Namespace<typeof localNames, NamedNode> {
|
TermVocabulary<ValueVocabulary<TBase, TLocal>> {
|
||||||
return createNamespace(baseUri, DataFactory.namedNode, ...localNames);
|
// Need to cast since `fromEntries` typings aren't strict enough
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(namespace).map(([ key, value ]): [string, NamedNode] => [ key, DataFactory.namedNode(value) ]),
|
||||||
|
) as TermVocabulary<ValueVocabulary<TBase, TLocal>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,13 +80,16 @@ Namespace<typeof localNames, NamedNode> {
|
|||||||
* and exports the given local names as properties on the returned object.
|
* and exports the given local names as properties on the returned object.
|
||||||
* Under the `terms` property, it exposes the expanded local names as named nodes.
|
* Under the `terms` property, it exposes the expanded local names as named nodes.
|
||||||
*/
|
*/
|
||||||
export function createUriAndTermNamespace<T extends string>(baseUri: string, ...localNames: T[]):
|
export function createVocabulary<TBase extends string, TLocal extends string>(baseUri: TBase,
|
||||||
Namespace<typeof localNames, string> & { terms: Namespace<typeof localNames, NamedNode> } {
|
...localNames: TLocal[]): string extends TLocal ? PartialVocabulary<TBase> : Vocabulary<TBase, TLocal> {
|
||||||
return Object.assign(createUriNamespace(baseUri, ...localNames),
|
const namespace = createValueVocabulary(baseUri, localNames);
|
||||||
{ terms: createTermNamespace(baseUri, ...localNames) });
|
return {
|
||||||
|
...namespace,
|
||||||
|
terms: createTermVocabulary(namespace),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ACL = createUriAndTermNamespace('http://www.w3.org/ns/auth/acl#',
|
export const ACL = createVocabulary('http://www.w3.org/ns/auth/acl#',
|
||||||
'accessTo',
|
'accessTo',
|
||||||
'agent',
|
'agent',
|
||||||
'agentClass',
|
'agentClass',
|
||||||
@ -71,42 +105,42 @@ export const ACL = createUriAndTermNamespace('http://www.w3.org/ns/auth/acl#',
|
|||||||
'Control',
|
'Control',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const AS = createUriAndTermNamespace('https://www.w3.org/ns/activitystreams#',
|
export const AS = createVocabulary('https://www.w3.org/ns/activitystreams#',
|
||||||
'Create',
|
'Create',
|
||||||
'Delete',
|
'Delete',
|
||||||
'Update',
|
'Update',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const AUTH = createUriAndTermNamespace('urn:solid:auth:',
|
export const AUTH = createVocabulary('urn:solid:auth:',
|
||||||
'userMode',
|
'userMode',
|
||||||
'publicMode',
|
'publicMode',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const DC = createUriAndTermNamespace('http://purl.org/dc/terms/',
|
export const DC = createVocabulary('http://purl.org/dc/terms/',
|
||||||
'description',
|
'description',
|
||||||
'modified',
|
'modified',
|
||||||
'title',
|
'title',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const FOAF = createUriAndTermNamespace('http://xmlns.com/foaf/0.1/',
|
export const FOAF = createVocabulary('http://xmlns.com/foaf/0.1/',
|
||||||
'Agent',
|
'Agent',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const HH = createUriAndTermNamespace('http://www.w3.org/2011/http-headers#',
|
export const HH = createVocabulary('http://www.w3.org/2011/http-headers#',
|
||||||
'content-length',
|
'content-length',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const HTTP = createUriAndTermNamespace('http://www.w3.org/2011/http#',
|
export const HTTP = createVocabulary('http://www.w3.org/2011/http#',
|
||||||
'statusCodeNumber',
|
'statusCodeNumber',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const IANA = createUriAndTermNamespace('http://www.w3.org/ns/iana/media-types/');
|
export const IANA = createVocabulary('http://www.w3.org/ns/iana/media-types/');
|
||||||
|
|
||||||
export const JSON_LD = createUriAndTermNamespace('http://www.w3.org/ns/json-ld#',
|
export const JSON_LD = createVocabulary('http://www.w3.org/ns/json-ld#',
|
||||||
'context',
|
'context',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const LDP = createUriAndTermNamespace('http://www.w3.org/ns/ldp#',
|
export const LDP = createVocabulary('http://www.w3.org/ns/ldp#',
|
||||||
'contains',
|
'contains',
|
||||||
|
|
||||||
'BasicContainer',
|
'BasicContainer',
|
||||||
@ -114,32 +148,32 @@ export const LDP = createUriAndTermNamespace('http://www.w3.org/ns/ldp#',
|
|||||||
'Resource',
|
'Resource',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const MA = createUriAndTermNamespace('http://www.w3.org/ns/ma-ont#',
|
export const MA = createVocabulary('http://www.w3.org/ns/ma-ont#',
|
||||||
'format',
|
'format',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const OIDC = createUriAndTermNamespace('http://www.w3.org/ns/solid/oidc#',
|
export const OIDC = createVocabulary('http://www.w3.org/ns/solid/oidc#',
|
||||||
'redirect_uris',
|
'redirect_uris',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PIM = createUriAndTermNamespace('http://www.w3.org/ns/pim/space#',
|
export const PIM = createVocabulary('http://www.w3.org/ns/pim/space#',
|
||||||
'Storage',
|
'Storage',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const POSIX = createUriAndTermNamespace('http://www.w3.org/ns/posix/stat#',
|
export const POSIX = createVocabulary('http://www.w3.org/ns/posix/stat#',
|
||||||
'mtime',
|
'mtime',
|
||||||
'size',
|
'size',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const RDF = createUriAndTermNamespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#',
|
export const RDF = createVocabulary('http://www.w3.org/1999/02/22-rdf-syntax-ns#',
|
||||||
'type',
|
'type',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const RDFS = createUriAndTermNamespace('http://www.w3.org/2000/01/rdf-schema#',
|
export const RDFS = createVocabulary('http://www.w3.org/2000/01/rdf-schema#',
|
||||||
'label',
|
'label',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const SOLID = createUriAndTermNamespace('http://www.w3.org/ns/solid/terms#',
|
export const SOLID = createVocabulary('http://www.w3.org/ns/solid/terms#',
|
||||||
'deletes',
|
'deletes',
|
||||||
'inserts',
|
'inserts',
|
||||||
'oidcIssuer',
|
'oidcIssuer',
|
||||||
@ -150,22 +184,22 @@ export const SOLID = createUriAndTermNamespace('http://www.w3.org/ns/solid/terms
|
|||||||
'InsertDeletePatch',
|
'InsertDeletePatch',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const SOLID_AS = createUriAndTermNamespace('http://www.w3.org/ns/solid/activitystreams#',
|
export const SOLID_AS = createVocabulary('http://www.w3.org/ns/solid/activitystreams#',
|
||||||
'Activity',
|
'Activity',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const SOLID_ERROR = createUriAndTermNamespace('urn:npm:solid:community-server:error:',
|
export const SOLID_ERROR = createVocabulary('urn:npm:solid:community-server:error:',
|
||||||
'disallowedMethod',
|
'disallowedMethod',
|
||||||
'errorResponse',
|
'errorResponse',
|
||||||
'stack',
|
'stack',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const SOLID_HTTP = createUriAndTermNamespace('urn:npm:solid:community-server:http:',
|
export const SOLID_HTTP = createVocabulary('urn:npm:solid:community-server:http:',
|
||||||
'location',
|
'location',
|
||||||
'slug',
|
'slug',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const SOLID_META = createUriAndTermNamespace('urn:npm:solid:community-server:meta:',
|
export const SOLID_META = createVocabulary('urn:npm:solid:community-server:meta:',
|
||||||
// This identifier is used as graph for all metadata that is generated on the fly and should not be stored
|
// This identifier is used as graph for all metadata that is generated on the fly and should not be stored
|
||||||
'ResponseMetadata',
|
'ResponseMetadata',
|
||||||
// This is used to identify templates that can be used for the representation of a resource
|
// This is used to identify templates that can be used for the representation of a resource
|
||||||
@ -177,15 +211,15 @@ export const SOLID_META = createUriAndTermNamespace('urn:npm:solid:community-ser
|
|||||||
'preserve',
|
'preserve',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const VANN = createUriAndTermNamespace('http://purl.org/vocab/vann/',
|
export const VANN = createVocabulary('http://purl.org/vocab/vann/',
|
||||||
'preferredNamespacePrefix',
|
'preferredNamespacePrefix',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const VCARD = createUriAndTermNamespace('http://www.w3.org/2006/vcard/ns#',
|
export const VCARD = createVocabulary('http://www.w3.org/2006/vcard/ns#',
|
||||||
'hasMember',
|
'hasMember',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const XSD = createUriAndTermNamespace('http://www.w3.org/2001/XMLSchema#',
|
export const XSD = createVocabulary('http://www.w3.org/2001/XMLSchema#',
|
||||||
'dateTime',
|
'dateTime',
|
||||||
'integer',
|
'integer',
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user