@occultist/occultist 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/dist/accept.d.ts +41 -0
- package/dist/accept.js +110 -0
- package/dist/accept.test.d.ts +1 -0
- package/dist/accept.test.js +44 -0
- package/dist/action.test.d.ts +1 -0
- package/dist/action.test.js +1 -0
- package/dist/actions/actionSets.d.ts +23 -0
- package/dist/actions/actionSets.js +49 -0
- package/dist/actions/actions.d.ts +163 -0
- package/dist/actions/actions.js +436 -0
- package/dist/actions/context.d.ts +78 -0
- package/dist/actions/context.js +112 -0
- package/dist/actions/meta.d.ts +49 -0
- package/dist/actions/meta.js +177 -0
- package/dist/actions/path.d.ts +21 -0
- package/dist/actions/path.js +83 -0
- package/dist/actions/path.test.d.ts +1 -0
- package/dist/actions/path.test.js +9 -0
- package/dist/actions/spec.d.ts +214 -0
- package/dist/actions/spec.js +1 -0
- package/dist/actions/types.d.ts +112 -0
- package/dist/actions/types.js +2 -0
- package/dist/actions/writer.d.ts +27 -0
- package/dist/actions/writer.js +140 -0
- package/dist/actions/writer.test.d.ts +1 -0
- package/dist/actions/writer.test.js +42 -0
- package/dist/auth/types.d.ts +14 -0
- package/dist/auth/types.js +1 -0
- package/dist/cache/cache.d.ts +30 -0
- package/dist/cache/cache.js +220 -0
- package/dist/cache/etag.d.ts +17 -0
- package/dist/cache/etag.js +83 -0
- package/dist/cache/etag.test.d.ts +1 -0
- package/dist/cache/etag.test.js +91 -0
- package/dist/cache/memory.d.ts +12 -0
- package/dist/cache/memory.js +36 -0
- package/dist/cache/types.d.ts +175 -0
- package/dist/cache/types.js +4 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +54 -0
- package/dist/jsonld.d.ts +43 -0
- package/dist/jsonld.js +1 -0
- package/dist/makeTypeDefs.d.ts +27 -0
- package/dist/makeTypeDefs.js +70 -0
- package/dist/merge.d.ts +61 -0
- package/dist/merge.js +1 -0
- package/dist/mod.d.ts +14 -0
- package/dist/mod.js +14 -0
- package/dist/processAction.d.ts +15 -0
- package/dist/processAction.js +512 -0
- package/dist/registry.d.ts +88 -0
- package/dist/registry.js +314 -0
- package/dist/registry.test.d.ts +1 -0
- package/dist/registry.test.js +133 -0
- package/dist/request.d.ts +29 -0
- package/dist/request.js +118 -0
- package/dist/scopes.d.ts +35 -0
- package/dist/scopes.js +121 -0
- package/dist/scopes.test.d.ts +1 -0
- package/dist/scopes.test.js +55 -0
- package/dist/transformers/fileTransformer.d.ts +1 -0
- package/dist/transformers/fileTransformer.js +8 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.js +1 -0
- package/dist/utils/alwaysArray.d.ts +1 -0
- package/dist/utils/alwaysArray.js +9 -0
- package/dist/utils/contextBuilder.d.ts +9 -0
- package/dist/utils/contextBuilder.js +82 -0
- package/dist/utils/getActionContext.d.ts +7 -0
- package/dist/utils/getActionContext.js +48 -0
- package/dist/utils/getInternalName.d.ts +6 -0
- package/dist/utils/getInternalName.js +7 -0
- package/dist/utils/getParamLocation.d.ts +2 -0
- package/dist/utils/getParamLocation.js +6 -0
- package/dist/utils/getPropertyValueSpecifications.d.ts +2 -0
- package/dist/utils/getPropertyValueSpecifications.js +49 -0
- package/dist/utils/getRequestBodyValues.d.ts +11 -0
- package/dist/utils/getRequestBodyValues.js +122 -0
- package/dist/utils/getRequestIRIValues.d.ts +14 -0
- package/dist/utils/getRequestIRIValues.js +133 -0
- package/dist/utils/isBodyInit.d.ts +1 -0
- package/dist/utils/isBodyInit.js +21 -0
- package/dist/utils/isNil.d.ts +1 -0
- package/dist/utils/isNil.js +4 -0
- package/dist/utils/isObject.d.ts +6 -0
- package/dist/utils/isObject.js +6 -0
- package/dist/utils/isPopulatedObject.d.ts +5 -0
- package/dist/utils/isPopulatedObject.js +8 -0
- package/dist/utils/isPopulatedString.d.ts +1 -0
- package/dist/utils/isPopulatedString.js +4 -0
- package/dist/utils/joinPaths.d.ts +1 -0
- package/dist/utils/joinPaths.js +31 -0
- package/dist/utils/makeAppendProblemDetails.d.ts +14 -0
- package/dist/utils/makeAppendProblemDetails.js +26 -0
- package/dist/utils/makeURLPattern.d.ts +5 -0
- package/dist/utils/makeURLPattern.js +12 -0
- package/dist/utils/normalizeURL.d.ts +4 -0
- package/dist/utils/normalizeURL.js +11 -0
- package/dist/utils/parseSearchParams.d.ts +3 -0
- package/dist/utils/parseSearchParams.js +24 -0
- package/dist/utils/preferredMediaTypes.d.ts +42 -0
- package/dist/utils/preferredMediaTypes.js +149 -0
- package/dist/utils/urlToIRI.d.ts +1 -0
- package/dist/utils/urlToIRI.js +8 -0
- package/dist/utils/validateSpecValue.d.ts +1 -0
- package/dist/utils/validateSpecValue.js +1 -0
- package/dist/validators.d.ts +16 -0
- package/dist/validators.js +134 -0
- package/lib/accept.test.ts +55 -0
- package/lib/accept.ts +147 -0
- package/lib/action.test.ts +2 -0
- package/lib/actions/actionSets.ts +88 -0
- package/lib/actions/actions.ts +795 -0
- package/lib/actions/context.ts +170 -0
- package/lib/actions/meta.ts +251 -0
- package/lib/actions/path.test.ts +15 -0
- package/lib/actions/path.ts +99 -0
- package/lib/actions/spec.ts +545 -0
- package/lib/actions/types.ts +146 -0
- package/lib/actions/writer.test.ts +57 -0
- package/lib/actions/writer.ts +176 -0
- package/lib/auth/types.ts +22 -0
- package/lib/cache/cache.ts +291 -0
- package/lib/cache/etag.test.ts +122 -0
- package/lib/cache/etag.ts +106 -0
- package/lib/cache/memory.ts +52 -0
- package/lib/cache/types.ts +240 -0
- package/lib/errors.ts +66 -0
- package/lib/jsonld.ts +67 -0
- package/lib/makeTypeDefs.ts +138 -0
- package/lib/merge.ts +86 -0
- package/lib/mod.ts +14 -0
- package/lib/processAction.ts +690 -0
- package/lib/registry.test.ts +174 -0
- package/lib/registry.ts +455 -0
- package/lib/request.ts +153 -0
- package/lib/scopes.test.ts +70 -0
- package/lib/scopes.ts +178 -0
- package/lib/transformers/fileTransformer.ts +10 -0
- package/lib/types.ts +13 -0
- package/lib/utils/alwaysArray.ts +10 -0
- package/lib/utils/contextBuilder.ts +111 -0
- package/lib/utils/getActionContext.ts +76 -0
- package/lib/utils/getInternalName.ts +15 -0
- package/lib/utils/getParamLocation.ts +14 -0
- package/lib/utils/getPropertyValueSpecifications.ts +76 -0
- package/lib/utils/getRequestBodyValues.ts +155 -0
- package/lib/utils/getRequestIRIValues.ts +201 -0
- package/lib/utils/isBodyInit.ts +22 -0
- package/lib/utils/isNil.ts +4 -0
- package/lib/utils/isObject.ts +8 -0
- package/lib/utils/isPopulatedObject.ts +9 -0
- package/lib/utils/isPopulatedString.ts +4 -0
- package/lib/utils/joinPaths.ts +36 -0
- package/lib/utils/makeAppendProblemDetails.ts +57 -0
- package/lib/utils/makeURLPattern.ts +18 -0
- package/lib/utils/normalizeURL.ts +15 -0
- package/lib/utils/parseSearchParams.ts +36 -0
- package/lib/utils/preferredMediaTypes.ts +220 -0
- package/lib/utils/urlToIRI.ts +11 -0
- package/lib/utils/validateSpecValue.ts +0 -0
- package/lib/validators.ts +186 -0
- package/package.json +41 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { ProblemDetailsError } from "../errors.js";
|
|
2
|
+
import { getParamLocation } from "./getParamLocation.js";
|
|
3
|
+
export function getRequestIRIValues({ iri, action, }) {
|
|
4
|
+
const pathValues = {};
|
|
5
|
+
const queryValues = {};
|
|
6
|
+
// deno-lint-ignore no-explicit-any
|
|
7
|
+
const iriValues = {};
|
|
8
|
+
const urlPatternResult = action.pattern.exec(iri);
|
|
9
|
+
const pathParams = urlPatternResult?.pathname.groups || {};
|
|
10
|
+
const searchParams = new URL(iri).searchParams;
|
|
11
|
+
const valueNames = Object.values(action.spec)
|
|
12
|
+
.filter((specItem) => typeof specItem.valueName === 'string')
|
|
13
|
+
.map((specItem) => specItem.valueName);
|
|
14
|
+
//if (action.strict) {
|
|
15
|
+
for (const valueName of searchParams.keys()) {
|
|
16
|
+
if (!valueNames.includes(valueName)) {
|
|
17
|
+
throw new ProblemDetailsError(400, {
|
|
18
|
+
title: `Unexpected value "${valueName}"`,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//}
|
|
23
|
+
for (const [term, specItem] of Object.entries(action.spec)) {
|
|
24
|
+
if (typeof specItem.valueName !== 'string') {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
let value;
|
|
28
|
+
const valueName = specItem.valueName;
|
|
29
|
+
const multipleValues = Boolean(specItem.multipleValues);
|
|
30
|
+
const paramLocation = getParamLocation(valueName, action.pattern);
|
|
31
|
+
if (paramLocation === 'path') {
|
|
32
|
+
value = pathParams[valueName];
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
value = searchParams.getAll(valueName);
|
|
36
|
+
}
|
|
37
|
+
if (value === null) {
|
|
38
|
+
value = undefined;
|
|
39
|
+
}
|
|
40
|
+
if (!multipleValues && Array.isArray(value) && value.length > 1) {
|
|
41
|
+
throw new ProblemDetailsError(400, {
|
|
42
|
+
title: `Invalid request`,
|
|
43
|
+
errors: [{
|
|
44
|
+
name: term,
|
|
45
|
+
pointer: `#${term}`,
|
|
46
|
+
reason: `Received array when expecting single value`,
|
|
47
|
+
}],
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (multipleValues && typeof value === 'string') {
|
|
51
|
+
value = [value];
|
|
52
|
+
}
|
|
53
|
+
else if (!multipleValues && Array.isArray(value)) {
|
|
54
|
+
value = value[0];
|
|
55
|
+
}
|
|
56
|
+
if (typeof value === 'undefined') {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
else if (!specItem.valueRequired && Array.isArray(value) && value.length === 0) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (specItem.dataType === 'boolean' && typeof value === 'string') {
|
|
63
|
+
iriValues[term] = parseBoolean({
|
|
64
|
+
term,
|
|
65
|
+
value,
|
|
66
|
+
pointer: `#${term}`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
else if (specItem.dataType === 'boolean' && Array.isArray(value)) {
|
|
70
|
+
iriValues[term] = value.map((value, index) => parseBoolean({
|
|
71
|
+
term,
|
|
72
|
+
value,
|
|
73
|
+
pointer: `#${term}[${index}]`,
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
else if (specItem.dataType === 'number' && typeof value === 'string') {
|
|
77
|
+
iriValues[term] = parseNumber({
|
|
78
|
+
term,
|
|
79
|
+
value,
|
|
80
|
+
pointer: `#${term}`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
else if (specItem.dataType === 'number' && Array.isArray(value)) {
|
|
84
|
+
iriValues[term] = value.map((value, index) => parseNumber({
|
|
85
|
+
term,
|
|
86
|
+
value,
|
|
87
|
+
pointer: `#${term}[${index}]`,
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// string values don't require parsing
|
|
92
|
+
iriValues[term] = value;
|
|
93
|
+
}
|
|
94
|
+
if (paramLocation === 'path') {
|
|
95
|
+
pathValues[term] = iriValues[term];
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
queryValues[term] = iriValues[term];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
pathValues,
|
|
103
|
+
queryValues,
|
|
104
|
+
iriValues,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function parseBoolean({ term, value, pointer, }) {
|
|
108
|
+
if (!['', 'true', 'false'].includes(value)) {
|
|
109
|
+
throw new ProblemDetailsError(400, {
|
|
110
|
+
title: `Invalid request`,
|
|
111
|
+
errors: [{
|
|
112
|
+
name: term,
|
|
113
|
+
pointer,
|
|
114
|
+
reason: `Boolean values must be "", "true" or "false"`,
|
|
115
|
+
}],
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return value === '' || value === 'true';
|
|
119
|
+
}
|
|
120
|
+
function parseNumber({ term, value, pointer, }) {
|
|
121
|
+
const numberValue = Number(value);
|
|
122
|
+
if (isNaN(numberValue) || !Number.isFinite(numberValue)) {
|
|
123
|
+
throw new ProblemDetailsError(400, {
|
|
124
|
+
title: `Invalid request`,
|
|
125
|
+
errors: [{
|
|
126
|
+
name: term,
|
|
127
|
+
pointer,
|
|
128
|
+
reason: `Numeric values must valid numbers and finite`,
|
|
129
|
+
}],
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return numberValue;
|
|
133
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isBodyInit(value: unknown): value is BodyInit;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function isBodyInit(value) {
|
|
2
|
+
return value instanceof ReadableStream ||
|
|
3
|
+
value instanceof Blob ||
|
|
4
|
+
value instanceof DataView ||
|
|
5
|
+
value instanceof ArrayBuffer ||
|
|
6
|
+
value instanceof Int8Array ||
|
|
7
|
+
value instanceof Uint8Array ||
|
|
8
|
+
value instanceof Uint8ClampedArray ||
|
|
9
|
+
value instanceof Int16Array ||
|
|
10
|
+
value instanceof Uint16Array ||
|
|
11
|
+
value instanceof Int32Array ||
|
|
12
|
+
value instanceof Uint32Array ||
|
|
13
|
+
value instanceof Float16Array ||
|
|
14
|
+
value instanceof Float32Array ||
|
|
15
|
+
value instanceof Float64Array ||
|
|
16
|
+
value instanceof BigInt64Array ||
|
|
17
|
+
value instanceof BigUint64Array ||
|
|
18
|
+
value instanceof FormData ||
|
|
19
|
+
value instanceof URLSearchParams ||
|
|
20
|
+
typeof value === 'string';
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isNil(value: any): value is null | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isPopulatedString(value: any): value is string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function joinPaths(...paths: Array<string | number>): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function joinPaths(...paths) {
|
|
2
|
+
let fullPath = '';
|
|
3
|
+
if (paths[0] == null || paths[0] == '') {
|
|
4
|
+
throw new Error('The first path must be a populated string when joining paths');
|
|
5
|
+
}
|
|
6
|
+
for (const pathSrc of paths) {
|
|
7
|
+
let path = null;
|
|
8
|
+
if (typeof pathSrc === 'number') {
|
|
9
|
+
path = `${pathSrc}`;
|
|
10
|
+
}
|
|
11
|
+
else if (typeof pathSrc === 'string') {
|
|
12
|
+
path = pathSrc;
|
|
13
|
+
}
|
|
14
|
+
if (path == null || path == '') {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (fullPath === '') {
|
|
18
|
+
fullPath = path;
|
|
19
|
+
}
|
|
20
|
+
else if (fullPath.endsWith('/') && path.startsWith('/')) {
|
|
21
|
+
fullPath += path.replace(/^\//, '');
|
|
22
|
+
}
|
|
23
|
+
else if (fullPath.endsWith('/') || path.startsWith('/')) {
|
|
24
|
+
fullPath += path;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
fullPath += `/${path}`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return fullPath;
|
|
31
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ProblemDetailsParam, ProblemDetails } from '../types.js';
|
|
2
|
+
export type AppendProblemDetails = (args: {
|
|
3
|
+
status: number;
|
|
4
|
+
title?: string;
|
|
5
|
+
detail?: string;
|
|
6
|
+
param?: ProblemDetailsParam;
|
|
7
|
+
}) => void;
|
|
8
|
+
export type ProblemDetailsParamsRefs = {
|
|
9
|
+
title?: string;
|
|
10
|
+
detail?: string;
|
|
11
|
+
httpStatus?: number;
|
|
12
|
+
problemDetails?: ProblemDetails;
|
|
13
|
+
};
|
|
14
|
+
export declare function makeAppendProblemDetails(refs: ProblemDetailsParamsRefs): AppendProblemDetails;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function makeAppendProblemDetails(refs) {
|
|
2
|
+
function appendProblemDetails({ title, detail, status, param, }) {
|
|
3
|
+
if (refs.httpStatus == null) {
|
|
4
|
+
refs.httpStatus = status;
|
|
5
|
+
}
|
|
6
|
+
else if (refs.httpStatus !== status &&
|
|
7
|
+
refs.httpStatus < 400) {
|
|
8
|
+
refs.httpStatus = status;
|
|
9
|
+
}
|
|
10
|
+
if (!refs.problemDetails) {
|
|
11
|
+
refs.problemDetails = {
|
|
12
|
+
title: title ??= "Bad request",
|
|
13
|
+
detail: detail ??= "Invalid parameters",
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (param) {
|
|
17
|
+
if (!Array.isArray(refs.problemDetails.errors)) {
|
|
18
|
+
refs.problemDetails.errors = [param];
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
refs.problemDetails.errors.push(param);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return appendProblemDetails;
|
|
26
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import url from 'node:url';
|
|
2
|
+
/**
|
|
3
|
+
* Work-around for how URLPatterns are currently supported across runtimes.
|
|
4
|
+
* This requires node v23 and above to run.
|
|
5
|
+
*/
|
|
6
|
+
export function makeURLPattern(pattern, baseURL) {
|
|
7
|
+
if (typeof URLPattern === 'undefined') {
|
|
8
|
+
const URLPattern = url.URLPattern;
|
|
9
|
+
return new URLPattern(pattern, baseURL);
|
|
10
|
+
}
|
|
11
|
+
return new URLPattern(pattern, baseURL);
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps the URL of the request to the root IRI.
|
|
3
|
+
*/
|
|
4
|
+
export function normalizeURL(rootIRI, urlStr) {
|
|
5
|
+
const sourceURL = new URL(urlStr);
|
|
6
|
+
const targetURL = new URL(rootIRI);
|
|
7
|
+
targetURL.pathname = sourceURL.pathname;
|
|
8
|
+
targetURL.search = sourceURL.search;
|
|
9
|
+
targetURL.hash = sourceURL.hash;
|
|
10
|
+
return targetURL.toString();
|
|
11
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ActionSpec, ContextState } from "../actions/spec.js";
|
|
2
|
+
import type { EmptyObject, JSONObject } from "../jsonld.js";
|
|
3
|
+
export declare function parseSearchParams<ActionState extends ContextState = EmptyObject>(spec: ActionSpec<ActionState>, searchParams: URLSearchParams): JSONObject;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function parseSearchParams(spec, searchParams) {
|
|
2
|
+
const body = {};
|
|
3
|
+
for (const [key, specItem] of Object.entries(spec)) {
|
|
4
|
+
const value = searchParams.get(key);
|
|
5
|
+
if (specItem.dataType === "number" &&
|
|
6
|
+
Array.isArray(value) &&
|
|
7
|
+
value !== null) {
|
|
8
|
+
body[key] = value.map(Number);
|
|
9
|
+
}
|
|
10
|
+
else if (specItem.dataType === "number" &&
|
|
11
|
+
value !== null &&
|
|
12
|
+
isNaN(Number(value))) {
|
|
13
|
+
// keeping the number value as a string allows error handling to work with it
|
|
14
|
+
body[key] = value;
|
|
15
|
+
}
|
|
16
|
+
else if (specItem.dataType === "number" && value !== null) {
|
|
17
|
+
body[key] = Number(value);
|
|
18
|
+
}
|
|
19
|
+
else if (value !== null) {
|
|
20
|
+
body[key] = value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return body;
|
|
24
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Adapted directly from negotiator at https://github.com/jshttp/negotiator/
|
|
3
|
+
* which is licensed as follows:
|
|
4
|
+
*
|
|
5
|
+
* (The MIT License)
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2012-2014 Federico Romero
|
|
8
|
+
* Copyright (c) 2012-2014 Isaac Z. Schlueter
|
|
9
|
+
* Copyright (c) 2014-2015 Douglas Christopher Wilson
|
|
10
|
+
*
|
|
11
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
|
12
|
+
* a copy of this software and associated documentation files (the
|
|
13
|
+
* 'Software'), to deal in the Software without restriction, including
|
|
14
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
|
15
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
16
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
|
17
|
+
* the following conditions:
|
|
18
|
+
*
|
|
19
|
+
* The above copyright notice and this permission notice shall be
|
|
20
|
+
* included in all copies or substantial portions of the Software.
|
|
21
|
+
*
|
|
22
|
+
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
23
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
24
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
25
|
+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
26
|
+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
27
|
+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
28
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Taken from deno source as they do not export it publicly
|
|
32
|
+
* https://jsr.io/@std/http/1.0.16/_negotiation/media_type.js
|
|
33
|
+
*/
|
|
34
|
+
export interface Specificity {
|
|
35
|
+
i: number;
|
|
36
|
+
o: number | undefined;
|
|
37
|
+
q: number;
|
|
38
|
+
s: number | undefined;
|
|
39
|
+
}
|
|
40
|
+
export declare function compareSpecs(a: Specificity, b: Specificity): number;
|
|
41
|
+
export declare function isQuality(spec: Specificity): boolean;
|
|
42
|
+
export declare function preferredMediaTypes(accept?: string | null, provided?: string[]): string[];
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
2
|
+
/*!
|
|
3
|
+
* Adapted directly from negotiator at https://github.com/jshttp/negotiator/
|
|
4
|
+
* which is licensed as follows:
|
|
5
|
+
*
|
|
6
|
+
* (The MIT License)
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2012-2014 Federico Romero
|
|
9
|
+
* Copyright (c) 2012-2014 Isaac Z. Schlueter
|
|
10
|
+
* Copyright (c) 2014-2015 Douglas Christopher Wilson
|
|
11
|
+
*
|
|
12
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
|
13
|
+
* a copy of this software and associated documentation files (the
|
|
14
|
+
* 'Software'), to deal in the Software without restriction, including
|
|
15
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
|
16
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
17
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
|
18
|
+
* the following conditions:
|
|
19
|
+
*
|
|
20
|
+
* The above copyright notice and this permission notice shall be
|
|
21
|
+
* included in all copies or substantial portions of the Software.
|
|
22
|
+
*
|
|
23
|
+
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
24
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
25
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
26
|
+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
27
|
+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
28
|
+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
29
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
30
|
+
*/
|
|
31
|
+
export function compareSpecs(a, b) {
|
|
32
|
+
return (b.q - a.q ||
|
|
33
|
+
(b.s ?? 0) - (a.s ?? 0) ||
|
|
34
|
+
(a.o ?? 0) - (b.o ?? 0) ||
|
|
35
|
+
a.i - b.i ||
|
|
36
|
+
0);
|
|
37
|
+
}
|
|
38
|
+
export function isQuality(spec) {
|
|
39
|
+
return spec.q > 0;
|
|
40
|
+
}
|
|
41
|
+
const simpleMediaTypeRegExp = /^\s*([^\s\/;]+)\/([^;\s]+)\s*(?:;(.*))?$/;
|
|
42
|
+
function splitKeyValuePair(str) {
|
|
43
|
+
const [key, value] = str.split("=");
|
|
44
|
+
return [key.toLowerCase(), value];
|
|
45
|
+
}
|
|
46
|
+
function parseMediaType(str, i) {
|
|
47
|
+
const match = simpleMediaTypeRegExp.exec(str);
|
|
48
|
+
if (!match) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const [, type, subtype, parameters] = match;
|
|
52
|
+
if (!type || !subtype) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const params = Object.create(null);
|
|
56
|
+
let q = 1;
|
|
57
|
+
if (parameters) {
|
|
58
|
+
const kvps = parameters.split(";").map((p) => p.trim()).map(splitKeyValuePair);
|
|
59
|
+
for (const [key, val] of kvps) {
|
|
60
|
+
const value = val && val[0] === `"` && val[val.length - 1] === `"`
|
|
61
|
+
? val.slice(1, val.length - 1)
|
|
62
|
+
: val;
|
|
63
|
+
if (key === "q" && value) {
|
|
64
|
+
q = parseFloat(value);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
params[key] = value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { type, subtype, params, i, o: undefined, q, s: undefined };
|
|
71
|
+
}
|
|
72
|
+
function parseAccept(accept) {
|
|
73
|
+
const accepts = accept.split(",").map((p) => p.trim());
|
|
74
|
+
const mediaTypes = [];
|
|
75
|
+
for (const [index, accept] of accepts.entries()) {
|
|
76
|
+
const mediaType = parseMediaType(accept.trim(), index);
|
|
77
|
+
if (mediaType) {
|
|
78
|
+
mediaTypes.push(mediaType);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return mediaTypes;
|
|
82
|
+
}
|
|
83
|
+
function getFullType(spec) {
|
|
84
|
+
return `${spec.type}/${spec.subtype}`;
|
|
85
|
+
}
|
|
86
|
+
function specify(type, spec, index) {
|
|
87
|
+
const p = parseMediaType(type, index);
|
|
88
|
+
if (!p) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
let s = 0;
|
|
92
|
+
if (spec.type.toLowerCase() === p.type.toLowerCase()) {
|
|
93
|
+
s |= 4;
|
|
94
|
+
}
|
|
95
|
+
else if (spec.type !== "*") {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (spec.subtype.toLowerCase() === p.subtype.toLowerCase()) {
|
|
99
|
+
s |= 2;
|
|
100
|
+
}
|
|
101
|
+
else if (spec.subtype !== "*") {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const keys = Object.keys(spec.params);
|
|
105
|
+
if (keys.length) {
|
|
106
|
+
if (keys.every((key) => (spec.params[key] ?? "").toLowerCase() ===
|
|
107
|
+
(p.params[key] ?? "").toLowerCase())) {
|
|
108
|
+
s |= 1;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
i: index,
|
|
116
|
+
o: spec.o,
|
|
117
|
+
q: spec.q,
|
|
118
|
+
s,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function getMediaTypePriority(type, accepted, index) {
|
|
122
|
+
let priority = { o: -1, q: 0, s: 0, i: index };
|
|
123
|
+
for (const accepts of accepted) {
|
|
124
|
+
const spec = specify(type, accepts, index);
|
|
125
|
+
if (spec &&
|
|
126
|
+
((priority.s ?? 0) - (spec.s ?? 0) ||
|
|
127
|
+
(priority.q ?? 0) - (spec.q ?? 0) ||
|
|
128
|
+
(priority.o ?? 0) - (spec.o ?? 0)) < 0) {
|
|
129
|
+
priority = spec;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return priority;
|
|
133
|
+
}
|
|
134
|
+
export function preferredMediaTypes(accept, provided) {
|
|
135
|
+
const accepts = parseAccept(accept === undefined ? "*/*" : accept ?? "");
|
|
136
|
+
if (!provided) {
|
|
137
|
+
return accepts
|
|
138
|
+
.filter(isQuality)
|
|
139
|
+
.sort(compareSpecs)
|
|
140
|
+
.map(getFullType);
|
|
141
|
+
}
|
|
142
|
+
const priorities = provided.map((type, index) => {
|
|
143
|
+
return getMediaTypePriority(type, accepts, index);
|
|
144
|
+
});
|
|
145
|
+
return priorities
|
|
146
|
+
.filter(isQuality)
|
|
147
|
+
.sort(compareSpecs)
|
|
148
|
+
.map((priority) => provided[priorities.indexOf(priority)]);
|
|
149
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function urlToIRI(value: string, rootIRI: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ArraySpec, ObjectArraySpec, ObjectSpec, PropertySpec } from './actions/spec.js';
|
|
2
|
+
import { JSONValue } from "./jsonld.js";
|
|
3
|
+
export declare function isFileData(value: JSONValue | File): value is string | File;
|
|
4
|
+
export declare function isObjectArraySpec(spec: PropertySpec): spec is ObjectArraySpec;
|
|
5
|
+
export declare function isObjectSpec(spec: PropertySpec): spec is ObjectSpec;
|
|
6
|
+
export declare function isArraySpec(spec: PropertySpec): spec is ArraySpec;
|
|
7
|
+
export declare function failsRequiredRequirement(value: JSONValue, specValue: PropertySpec): boolean;
|
|
8
|
+
export declare function failsTypeRequirement(value: JSONValue | File, specValue: PropertySpec): boolean;
|
|
9
|
+
export declare function failsContentTypeRequirement(value: JSONValue | File, specValue: PropertySpec): boolean;
|
|
10
|
+
export declare function failsMinValue(value: JSONValue, specValue: PropertySpec): boolean;
|
|
11
|
+
export declare function failsMaxValue(value: JSONValue, specValue: PropertySpec): boolean;
|
|
12
|
+
export declare function failsStepValue(value: JSONValue, specValue: PropertySpec): boolean;
|
|
13
|
+
export declare function failsPatternValue(value: JSONValue, specValue: PropertySpec): boolean;
|
|
14
|
+
export declare function failValueMinLength(value: JSONValue, specValue: PropertySpec): boolean;
|
|
15
|
+
export declare function failValueMaxLength(value: JSONValue, specValue: PropertySpec): boolean;
|
|
16
|
+
export declare function failsValidator(value: JSONValue | File, specValue: PropertySpec): boolean;
|