@tenonhq/dovetail-servicenow 0.0.35 → 0.0.36
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/dist/client.d.ts +9 -0
- package/dist/client.js +32 -5
- package/dist/createClientFromEnvFile.d.ts +3 -2
- package/dist/createClientFromEnvFile.js +13 -3
- package/dist/types.d.ts +9 -2
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -20,6 +20,15 @@
|
|
|
20
20
|
* have SN_INSTANCE/SN_USER/SN_PASSWORD work without reconfiguration.
|
|
21
21
|
*/
|
|
22
22
|
import type { ServiceNowClientConfig } from "./types";
|
|
23
|
+
/** Resolved auth mode: inbound API key (x-sn-apikey header) or basic auth. */
|
|
24
|
+
export type ResolvedAuth = {
|
|
25
|
+
mode: "apiKey";
|
|
26
|
+
apiKey: string;
|
|
27
|
+
} | {
|
|
28
|
+
mode: "basic";
|
|
29
|
+
user: string;
|
|
30
|
+
password: string;
|
|
31
|
+
};
|
|
23
32
|
export interface TableQueryOptions {
|
|
24
33
|
limit?: number;
|
|
25
34
|
fields?: string[];
|
package/dist/client.js
CHANGED
|
@@ -52,6 +52,15 @@ function resolveInstance(cfg) {
|
|
|
52
52
|
return normalizeHost(raw);
|
|
53
53
|
}
|
|
54
54
|
function resolveAuth(cfg) {
|
|
55
|
+
// Explicit config wins over the environment, and within each layer an API
|
|
56
|
+
// key is the default over basic credentials. A cfg that names user/password
|
|
57
|
+
// (e.g. one resolved from an --env file) deliberately pins basic auth even
|
|
58
|
+
// when the surrounding process.env carries SN_API_KEY — an env-file retarget
|
|
59
|
+
// must be fully determined by its file.
|
|
60
|
+
if (cfg.apiKey) {
|
|
61
|
+
return { mode: "apiKey", apiKey: cfg.apiKey };
|
|
62
|
+
}
|
|
63
|
+
var cfgWantsBasic = Boolean(cfg.user || cfg.password);
|
|
55
64
|
var user = cfg.user
|
|
56
65
|
|| process.env.SN_USER
|
|
57
66
|
|| process.env.SN_DEV_USERNAME
|
|
@@ -62,11 +71,20 @@ function resolveAuth(cfg) {
|
|
|
62
71
|
|| process.env.SN_DEV_PASSWORD
|
|
63
72
|
|| process.env.SN_PROD_PASSWORD
|
|
64
73
|
|| "";
|
|
74
|
+
if (!cfgWantsBasic) {
|
|
75
|
+
var envApiKey = process.env.SN_API_KEY
|
|
76
|
+
|| process.env.SN_DEV_API_KEY
|
|
77
|
+
|| process.env.SN_PROD_API_KEY
|
|
78
|
+
|| "";
|
|
79
|
+
if (envApiKey) {
|
|
80
|
+
return { mode: "apiKey", apiKey: envApiKey };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
65
83
|
if (!user || !password) {
|
|
66
|
-
throw new Error("ServiceNow credentials missing — set
|
|
67
|
-
"or SN_DEV_USERNAME/SN_DEV_PASSWORD (or SN_PROD_*).");
|
|
84
|
+
throw new Error("ServiceNow credentials missing — set SN_API_KEY (inbound API key, preferred), " +
|
|
85
|
+
"or SN_USER/SN_PASSWORD, or SN_DEV_USERNAME/SN_DEV_PASSWORD (or SN_PROD_*).");
|
|
68
86
|
}
|
|
69
|
-
return { user: user, password: password };
|
|
87
|
+
return { mode: "basic", user: user, password: password };
|
|
70
88
|
}
|
|
71
89
|
function sleep(ms) {
|
|
72
90
|
return new Promise(function (resolve) {
|
|
@@ -97,10 +115,19 @@ function createClient(config = {}) {
|
|
|
97
115
|
var max5xx = config.maxRetries5xx != null
|
|
98
116
|
? config.maxRetries5xx
|
|
99
117
|
: Number(process.env.SN_MAX_RETRIES_5XX) || 3;
|
|
118
|
+
var baseHeaders = {
|
|
119
|
+
accept: "application/json",
|
|
120
|
+
"content-type": "application/json"
|
|
121
|
+
};
|
|
122
|
+
if (creds.mode === "apiKey") {
|
|
123
|
+
baseHeaders["x-sn-apikey"] = creds.apiKey;
|
|
124
|
+
}
|
|
100
125
|
var http = axios_1.default.create({
|
|
101
126
|
baseURL: "https://" + host,
|
|
102
|
-
auth:
|
|
103
|
-
|
|
127
|
+
auth: creds.mode === "basic"
|
|
128
|
+
? { username: creds.user, password: creds.password }
|
|
129
|
+
: undefined,
|
|
130
|
+
headers: baseHeaders,
|
|
104
131
|
validateStatus: function () { return true; }
|
|
105
132
|
});
|
|
106
133
|
var lastAt = 0;
|
|
@@ -17,8 +17,9 @@ import type { ServiceNowClientConfig } from "./types";
|
|
|
17
17
|
* the surrounding process.env, so the file fully determines the target.
|
|
18
18
|
*
|
|
19
19
|
* Throws if the file cannot be read, or if it does not define an instance and
|
|
20
|
-
* a complete
|
|
21
|
-
* back to whatever instance the host
|
|
20
|
+
* credentials (an inbound API key, or a complete basic-auth pair) — failing
|
|
21
|
+
* loudly rather than silently falling back to whatever instance the host
|
|
22
|
+
* process happens to be pointed at.
|
|
22
23
|
*/
|
|
23
24
|
export declare function resolveConfigFromEnvFile(envPath: string): ServiceNowClientConfig;
|
|
24
25
|
/**
|
|
@@ -25,8 +25,9 @@ const client_1 = require("./client");
|
|
|
25
25
|
* the surrounding process.env, so the file fully determines the target.
|
|
26
26
|
*
|
|
27
27
|
* Throws if the file cannot be read, or if it does not define an instance and
|
|
28
|
-
* a complete
|
|
29
|
-
* back to whatever instance the host
|
|
28
|
+
* credentials (an inbound API key, or a complete basic-auth pair) — failing
|
|
29
|
+
* loudly rather than silently falling back to whatever instance the host
|
|
30
|
+
* process happens to be pointed at.
|
|
30
31
|
*/
|
|
31
32
|
function resolveConfigFromEnvFile(envPath) {
|
|
32
33
|
if (typeof envPath !== "string" || envPath.length === 0) {
|
|
@@ -41,15 +42,24 @@ function resolveConfigFromEnvFile(envPath) {
|
|
|
41
42
|
}
|
|
42
43
|
var parsed = dotenv_1.default.parse(raw);
|
|
43
44
|
var instance = parsed.SN_INSTANCE || parsed.SN_DEV_INSTANCE || parsed.SN_PROD_INSTANCE || "";
|
|
45
|
+
var apiKey = parsed.SN_API_KEY || parsed.SN_DEV_API_KEY || parsed.SN_PROD_API_KEY || "";
|
|
44
46
|
var user = parsed.SN_USER || parsed.SN_DEV_USERNAME || parsed.SN_PROD_USERNAME || "";
|
|
45
47
|
var password = parsed.SN_PASSWORD || parsed.SN_DEV_PASSWORD || parsed.SN_PROD_PASSWORD || "";
|
|
46
48
|
if (!instance) {
|
|
47
49
|
throw new Error("env file '" + envPath + "' does not define a ServiceNow instance — " +
|
|
48
50
|
"set SN_INSTANCE (preferred) or SN_DEV_INSTANCE / SN_PROD_INSTANCE.");
|
|
49
51
|
}
|
|
52
|
+
if (apiKey) {
|
|
53
|
+
// Key is the default auth mode when the file defines one. Returning the
|
|
54
|
+
// key WITHOUT user/password keeps the resolved config fully explicit —
|
|
55
|
+
// resolveAuth treats a config that names user/password as a deliberate
|
|
56
|
+
// basic-auth pin, so leaking them here would flip the mode.
|
|
57
|
+
return { instance: instance, apiKey: apiKey };
|
|
58
|
+
}
|
|
50
59
|
if (!user || !password) {
|
|
51
60
|
throw new Error("env file '" + envPath + "' is missing ServiceNow credentials — " +
|
|
52
|
-
"set
|
|
61
|
+
"set SN_API_KEY (inbound API key, preferred), SN_USER/SN_PASSWORD, " +
|
|
62
|
+
"or SN_DEV_USERNAME/SN_DEV_PASSWORD (or SN_PROD_*).");
|
|
53
63
|
}
|
|
54
64
|
return { instance: instance, user: user, password: password };
|
|
55
65
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -4,9 +4,16 @@
|
|
|
4
4
|
export interface ServiceNowClientConfig {
|
|
5
5
|
/** Instance host, e.g. "tenonworkstudio.service-now.com". Defaults to SN_INSTANCE env var. */
|
|
6
6
|
instance?: string;
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Inbound REST API key, sent as the `x-sn-apikey` header. Defaults to the
|
|
9
|
+
* SN_API_KEY env var. When a key is present it is the default auth mode and
|
|
10
|
+
* basic auth is not sent. Requires matching REST API access policies on the
|
|
11
|
+
* instance — an API without a key-enabled policy ignores the header (401).
|
|
12
|
+
*/
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
/** Basic-auth user. Defaults to SN_USER env var. Fallback when no API key is configured. */
|
|
8
15
|
user?: string;
|
|
9
|
-
/** Basic-auth password. Defaults to SN_PASSWORD env var. */
|
|
16
|
+
/** Basic-auth password. Defaults to SN_PASSWORD env var. Fallback when no API key is configured. */
|
|
10
17
|
password?: string;
|
|
11
18
|
/** Min gap between requests (ms). Defaults to SN_REQUEST_INTERVAL_MS or 20. */
|
|
12
19
|
requestIntervalMs?: number;
|