@lblod/mu-auth-sudo 1.0.0 → 1.1.0
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/README.md +53 -0
- package/dist/auth-sudo.d.ts +4 -11
- package/dist/auth-sudo.js +33 -6
- package/dist/sparql-result-types.d.ts +34 -0
- package/dist/sparql-result-types.js +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,6 +42,59 @@ await update(updateString, extraHeaders, connectionOptions);
|
|
|
42
42
|
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
## Typescript usage
|
|
46
|
+
|
|
47
|
+
The query method allows for specifying the resulting bindings you expect to receive. Additionally, there are special return types for
|
|
48
|
+
ASK, CONSTRUCT and DESCRIBE queries.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
|
|
52
|
+
const queryString = `SELECT * FROM { GRAPH ?g { ?s ?p ?o. } } LIMIT 1`;
|
|
53
|
+
// for SELECT queries, list the variable bindings you ask for in the select as an array of strings
|
|
54
|
+
const result = await querySudo<['g', 's', 'p', 'o']>(queryString);
|
|
55
|
+
// result shape and bindings are now typed, and will fully autocomplete
|
|
56
|
+
result.results.bindins[0].g.value
|
|
57
|
+
|
|
58
|
+
const queryString = `ASK {?something ?exists "with this value"}`
|
|
59
|
+
// for ASK queries, simply specify the literal 'ask' as the generic
|
|
60
|
+
const result = await querySudo<'ask'>(queryString)
|
|
61
|
+
// result shape is typed
|
|
62
|
+
result.boolean
|
|
63
|
+
|
|
64
|
+
const queryString = `DESCRIBE <http://my-cool.uri/1>`
|
|
65
|
+
// for DESCRIBE queries, simply specify the literal 'describe' as the generic
|
|
66
|
+
// note, this is fully equivalent to querySudo<['s', 'p', 'v']>
|
|
67
|
+
const result = await querySudo<'describe'>(queryString)
|
|
68
|
+
// result shape is typed
|
|
69
|
+
result.results.bindings[0].s.value
|
|
70
|
+
|
|
71
|
+
const queryString = `CONSTRUCT {?my ?triple ?pattern. } WHERE {?my ?triple ?pattern .}`
|
|
72
|
+
// for CONSTRUCT queries, simply specify the literal 'construct' as the generic
|
|
73
|
+
// note, this is fully equivalent to querySudo<['s', 'p', 'v']>
|
|
74
|
+
const result = await querySudo<'construct'>(queryString)
|
|
75
|
+
// result shape is typed
|
|
76
|
+
result.results.bindings[0].s.value
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If you don't care or don't know the result shape, you can simply leave out the generic. It defaults to `string[]`, which means
|
|
80
|
+
everything except the specific binding names will still be typed, e.g:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
|
|
84
|
+
const queryString = `SELECT * FROM { GRAPH ?g { ?s ?p ?o. } } LIMIT 1`;
|
|
85
|
+
const result = querySudo(queryString);
|
|
86
|
+
|
|
87
|
+
// still fully typed
|
|
88
|
+
const firstBinding = result.results.bindings[0]
|
|
89
|
+
|
|
90
|
+
// won't complain, since we haven't specified the precise binding names
|
|
91
|
+
const hmmm = firstBinding.banana
|
|
92
|
+
|
|
93
|
+
// however, the shape of the binding is still typed
|
|
94
|
+
const {value, type} = hmmm
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
|
|
45
98
|
## Logging
|
|
46
99
|
|
|
47
100
|
The verbosity of logging can be configured as in the [javascript template](https://github.com/mu-semtech/mu-javascript-template/blob/6ff43eaf51856783c6946e82344e31a3348ce4a3/README.md#logging) through following environment variables:
|
package/dist/auth-sudo.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
export * from './sparql-result-types';
|
|
3
|
+
import type { SPARQLQueryConfig, SPARQLResult } from './sparql-result-types';
|
|
2
4
|
export interface ConnectionOptions {
|
|
3
5
|
sparqlEndpoint?: string;
|
|
4
6
|
authUser?: string;
|
|
@@ -6,22 +8,13 @@ export interface ConnectionOptions {
|
|
|
6
8
|
authType?: "basic" | "digest";
|
|
7
9
|
mayRetry?: boolean;
|
|
8
10
|
}
|
|
9
|
-
export interface SPARQLResult {
|
|
10
|
-
head: Record<string, any>;
|
|
11
|
-
results?: {
|
|
12
|
-
distinct: boolean;
|
|
13
|
-
ordered: boolean;
|
|
14
|
-
bindings: Record<string, any>[];
|
|
15
|
-
};
|
|
16
|
-
boolean?: boolean;
|
|
17
|
-
}
|
|
18
11
|
export declare class HTTPResponseError extends Error {
|
|
19
12
|
httpStatus: number;
|
|
20
13
|
httpStatusText: string;
|
|
21
14
|
constructor(response: Response);
|
|
22
15
|
}
|
|
23
|
-
export declare function querySudo(queryString: string, extraHeaders?: Record<string, string>, connectionOptions?: ConnectionOptions): Promise<SPARQLResult | null>;
|
|
24
|
-
export declare function updateSudo(queryString: string, extraHeaders?: Record<string, string>, connectionOptions?: ConnectionOptions): Promise<SPARQLResult | null>;
|
|
16
|
+
export declare function querySudo<C extends SPARQLQueryConfig = string[]>(queryString: string, extraHeaders?: Record<string, string>, connectionOptions?: ConnectionOptions): Promise<SPARQLResult<C> | null>;
|
|
17
|
+
export declare function updateSudo<C extends SPARQLQueryConfig = string[]>(queryString: string, extraHeaders?: Record<string, string>, connectionOptions?: ConnectionOptions): Promise<SPARQLResult<C> | null>;
|
|
25
18
|
declare const defaultExport: {
|
|
26
19
|
querySudo: typeof querySudo;
|
|
27
20
|
updateSudo: typeof updateSudo;
|
package/dist/auth-sudo.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
18
|
};
|
|
@@ -7,12 +21,16 @@ exports.updateSudo = exports.querySudo = exports.HTTPResponseError = void 0;
|
|
|
7
21
|
const express_http_context_1 = __importDefault(require("express-http-context"));
|
|
8
22
|
const env_var_1 = __importDefault(require("env-var"));
|
|
9
23
|
const digest_fetch_1 = __importDefault(require("digest-fetch"));
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
__exportStar(require("./sparql-result-types"), exports);
|
|
25
|
+
// The query methods accept an endpoint parameter in the connectionOptions, so we should not make this required for consumers
|
|
26
|
+
// that want to explicitly pass the endpoint. Otherwise those consumers have to set this env var to a dummy value for no reason.
|
|
27
|
+
// We check at runtime wether we have a suitable endpoint and error if not
|
|
28
|
+
const SPARQL_ENDPOINT = env_var_1.default.get('MU_SPARQL_ENDPOINT').asString();
|
|
29
|
+
const LOG_SPARQL_ALL = env_var_1.default.get('LOG_SPARQL_ALL').default('true').asString();
|
|
12
30
|
const LOG_SPARQL_QUERIES = env_var_1.default.get('LOG_SPARQL_QUERIES').default(LOG_SPARQL_ALL).asBool();
|
|
13
31
|
const LOG_SPARQL_UPDATES = env_var_1.default.get('LOG_SPARQL_UPDATES').default(LOG_SPARQL_ALL).asBool();
|
|
14
|
-
const DEBUG_AUTH_HEADERS = env_var_1.default.get('DEBUG_AUTH_HEADERS').
|
|
15
|
-
// The following configuration options are
|
|
32
|
+
const DEBUG_AUTH_HEADERS = env_var_1.default.get('DEBUG_AUTH_HEADERS').default('false').asBool();
|
|
33
|
+
// The following configuration options are optional and best left at the default values, but may be overriden as a temporary workaround for issues. Thus, a last resort.
|
|
16
34
|
const RETRY = env_var_1.default.get('SUDO_QUERY_RETRY').default('false').asBool();
|
|
17
35
|
const RETRY_MAX_ATTEMPTS = env_var_1.default.get('SUDO_QUERY_RETRY_MAX_ATTEMPTS').default('5').asInt();
|
|
18
36
|
const RETRY_FOR_HTTP_STATUS_CODES = env_var_1.default.get('SUDO_QUERY_RETRY_FOR_HTTP_STATUS_CODES').default('').asArray();
|
|
@@ -28,6 +46,15 @@ class HTTPResponseError extends Error {
|
|
|
28
46
|
}
|
|
29
47
|
}
|
|
30
48
|
exports.HTTPResponseError = HTTPResponseError;
|
|
49
|
+
function ensureEndpoint(endpoint) {
|
|
50
|
+
if (typeof endpoint === "string") {
|
|
51
|
+
return endpoint;
|
|
52
|
+
}
|
|
53
|
+
if (typeof SPARQL_ENDPOINT === "string") {
|
|
54
|
+
return SPARQL_ENDPOINT;
|
|
55
|
+
}
|
|
56
|
+
throw new Error("No endpoint configured. Either pass it into the queryoptions, or make sure the MU_SPARQL_ENDPOINT environment variable is set.");
|
|
57
|
+
}
|
|
31
58
|
function defaultHeaders() {
|
|
32
59
|
const headers = new Headers();
|
|
33
60
|
headers.set('content-type', 'application/x-www-form-urlencoded');
|
|
@@ -40,7 +67,7 @@ function defaultHeaders() {
|
|
|
40
67
|
return headers;
|
|
41
68
|
}
|
|
42
69
|
async function executeRawQuery(queryString, extraHeaders = {}, connectionOptions = {}, attempt = 0) {
|
|
43
|
-
const sparqlEndpoint = connectionOptions.sparqlEndpoint
|
|
70
|
+
const sparqlEndpoint = ensureEndpoint(connectionOptions.sparqlEndpoint);
|
|
44
71
|
const headers = defaultHeaders();
|
|
45
72
|
for (const key of Object.keys(extraHeaders)) {
|
|
46
73
|
headers.append(key, extraHeaders[key]);
|
|
@@ -100,7 +127,7 @@ async function executeRawQuery(queryString, extraHeaders = {}, connectionOptions
|
|
|
100
127
|
}
|
|
101
128
|
async function maybeJSON(response) {
|
|
102
129
|
try {
|
|
103
|
-
return
|
|
130
|
+
return await response.json();
|
|
104
131
|
}
|
|
105
132
|
catch (e) {
|
|
106
133
|
return null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type Binding<B extends string[]> = {
|
|
2
|
+
[Key in B[number]]: {
|
|
3
|
+
type: string;
|
|
4
|
+
value: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
export type SPARQLQueryResult<B extends string[]> = {
|
|
8
|
+
head: {
|
|
9
|
+
link: unknown[];
|
|
10
|
+
vars: B;
|
|
11
|
+
};
|
|
12
|
+
results: {
|
|
13
|
+
distinct: boolean;
|
|
14
|
+
ordered: boolean;
|
|
15
|
+
bindings: Binding<B>[];
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export type SPARQLConstructResult = SPARQLQueryResult<['s', 'p', 'v']>;
|
|
19
|
+
export type SPARQLDescribeResult = SPARQLQueryResult<['s', 'p', 'v']>;
|
|
20
|
+
export type SPARQLAskResult = {
|
|
21
|
+
head: {
|
|
22
|
+
link: unknown[];
|
|
23
|
+
};
|
|
24
|
+
boolean: boolean;
|
|
25
|
+
};
|
|
26
|
+
type QueryTypes = 'ask' | 'construct' | 'describe';
|
|
27
|
+
export interface ConfigMap {
|
|
28
|
+
'ask': SPARQLAskResult;
|
|
29
|
+
'construct': SPARQLConstructResult;
|
|
30
|
+
'describe': SPARQLDescribeResult;
|
|
31
|
+
}
|
|
32
|
+
export type SPARQLQueryConfig = QueryTypes | string[];
|
|
33
|
+
export type SPARQLResult<C extends SPARQLQueryConfig> = C extends QueryTypes ? ConfigMap[C] : C extends string[] ? SPARQLQueryResult<C> : never;
|
|
34
|
+
export {};
|
package/package.json
CHANGED