@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 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:
@@ -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
- const SPARQL_ENDPOINT = env_var_1.default.get('MU_SPARQL_ENDPOINT').required().asString();
11
- const LOG_SPARQL_ALL = env_var_1.default.get('LOG_SPARQL_ALL').required().asString();
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').required().asBool();
15
- // The following configuration options are considered optional, but may be overriden as a temporary workaround for issues. Thus, a last resort.
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 ?? SPARQL_ENDPOINT;
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 (await response.json());
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 {};
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lblod/mu-auth-sudo",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "this package provides an alternative sparql client for the mu-javascript-template that has sudo rights.",
5
5
  "main": "dist/auth-sudo.js",
6
6
  "types": "dist/auth-sudo.d.ts",