@tenonhq/dovetail-servicenow 0.0.9 → 0.0.11

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
@@ -66,6 +66,21 @@ SN_USER=...
66
66
  SN_PASSWORD=...
67
67
  ```
68
68
 
69
+ ### Selecting a .env file per command
70
+
71
+ Every `dove-sn` command (and `dove-sn mcp`) loads `.env` from the current
72
+ directory by default. Point it at a different file to target another instance:
73
+
74
+ ```bash
75
+ npx dove-sn view-flow --sys-id <id> --env .env.prod
76
+ npx dove-sn add-choices --env ../envs/workshop.env --table ... --column ...
77
+ ```
78
+
79
+ `--env` (alias `--env-file`) wins over the `DOVETAIL_ENV_FILE` env var, which in
80
+ turn beats the default `.env`. Variables already present in the environment are
81
+ never overridden, so an exported `SN_INSTANCE` still takes precedence over the
82
+ file — handy for CI.
83
+
69
84
  ## CLI
70
85
 
71
86
  ```bash
package/dist/cli.js CHANGED
@@ -57,6 +57,7 @@ var __importStar = (this && this.__importStar) || (function () {
57
57
  })();
58
58
  Object.defineProperty(exports, "__esModule", { value: true });
59
59
  const fs = __importStar(require("fs"));
60
+ const loadEnv_1 = require("./loadEnv");
60
61
  const client_1 = require("./client");
61
62
  const choices_1 = require("./choices");
62
63
  const formatter_1 = require("./formatter");
@@ -557,10 +558,17 @@ function printHelp() {
557
558
  " (--sys-id <sys_id> [--execute --confirm] [--inputs <json>] [--json])\n" +
558
559
  " edit-flow Patch a flow/subflow (rename, description, step inputs)\n" +
559
560
  " (--sys-id <sys_id> --from-json <ops.json> [--apply] [--update-set <sys_id>] [--scope <sys_id>] [--json])\n" +
560
- " mcp Run the MCP stdio server (--smoke lists tools and exits)\n");
561
+ " mcp Run the MCP stdio server (--smoke lists tools and exits)\n" +
562
+ "\nGlobal flags:\n" +
563
+ " --env <path> Load credentials from a specific .env file (also --env-file,\n" +
564
+ " or the DOVETAIL_ENV_FILE env var). Default: .env in the cwd.\n");
561
565
  }
562
566
  async function main() {
563
567
  var parsed = parseArgs(process.argv.slice(2));
568
+ // Load credentials before any command runs. `--env`/`--env-file` (or the
569
+ // DOVETAIL_ENV_FILE env var) selects a specific file so one checkout can
570
+ // target multiple instances; otherwise the cwd `.env` is used.
571
+ (0, loadEnv_1.loadEnvFile)(parsed.flags.env || parsed.flags["env-file"]);
564
572
  if (parsed.command === "add-choices") {
565
573
  await runAddChoices(parsed.flags);
566
574
  return 0;
package/dist/client.d.ts CHANGED
@@ -6,15 +6,15 @@
6
6
  * - `buildAgent.*` — reads via the sn_build_agent API, with graceful
7
7
  * fallback to Table API / sys_dictionary when the
8
8
  * Build Agent plugin is unavailable
9
- * - `claude.*` — writes via the Dovetail Scripted REST API
10
- * (/api/cadso/dovetail/*), which handles update-set + scope
11
- * switching atomically so every write lands in the right
12
- * update set without touching sys_user_preference.
13
- * Falls back to the legacy /api/cadso/claude/* path on
14
- * instances where the API has not yet been re-imported.
15
- * The namespace name `claude` is preserved for API
16
- * compatibility; the underlying server-side API is now
17
- * named "Dovetail".
9
+ * - `claude.*` — writes via the Dovetail core Scripted REST API
10
+ * (/api/cadso/dovetail_core/*), which handles update-set +
11
+ * scope switching atomically so every write lands in the
12
+ * right update set without touching sys_user_preference.
13
+ * Falls back to the legacy global-scope /api/cadso/dovetail/*
14
+ * path on instances without the Dovetail app installed.
15
+ * The `claude.*` property name is preserved for API
16
+ * compatibility; the server-side API now lives in the
17
+ * Dovetail scoped application as "Dovetail Core".
18
18
  *
19
19
  * Env fallbacks mirror prior dashboard-fetch helpers so dev setups that already
20
20
  * have SN_INSTANCE/SN_USER/SN_PASSWORD work without reconfiguration.
@@ -62,7 +62,7 @@ export interface ServiceNowClient {
62
62
  getTableSchema: (table: string) => Promise<TableSchema>;
63
63
  };
64
64
  claude: {
65
- /** POST /api/cadso/dovetail/createRecord (legacy path: /api/cadso/claude/createRecord). */
65
+ /** POST /api/cadso/dovetail_core/createRecord (legacy: /api/cadso/dovetail/createRecord). */
66
66
  createRecord: (params: {
67
67
  table: string;
68
68
  fields: Record<string, any>;
@@ -73,7 +73,7 @@ export interface ServiceNowClient {
73
73
  sys_id: string;
74
74
  [k: string]: any;
75
75
  }>;
76
- /** POST /api/cadso/dovetail/pushWithUpdateSet (legacy: /api/cadso/claude/pushWithUpdateSet). */
76
+ /** POST /api/cadso/dovetail_core/pushWithUpdateSet (legacy: /api/cadso/dovetail/pushWithUpdateSet). */
77
77
  pushWithUpdateSet: (params: {
78
78
  update_set_sys_id: string;
79
79
  table: string;
@@ -83,18 +83,18 @@ export interface ServiceNowClient {
83
83
  sys_id: string;
84
84
  [k: string]: any;
85
85
  }>;
86
- /** GET /api/cadso/dovetail/currentUpdateSet?scope=... (legacy: /api/cadso/claude/currentUpdateSet). */
86
+ /** GET /api/cadso/dovetail_core/currentUpdateSet?scope=... (legacy: /api/cadso/dovetail/currentUpdateSet). */
87
87
  currentUpdateSet: (scope?: string) => Promise<{
88
88
  sys_id: string;
89
89
  name: string;
90
90
  }>;
91
- /** GET /api/cadso/dovetail/changeUpdateSet?sysId=... — pins the REST session's active update set. */
91
+ /** GET /api/cadso/dovetail_core/changeUpdateSet?sysId=... — pins the REST session's active update set. */
92
92
  changeUpdateSet: (params: {
93
93
  sysId: string;
94
94
  }) => Promise<{
95
95
  [k: string]: any;
96
96
  }>;
97
- /** POST /api/cadso/dovetail/deleteRecord — body { table, sys_id }. Returns the deleted record. */
97
+ /** POST /api/cadso/dovetail_core/deleteRecord — body { table, sys_id }. Returns the deleted record. */
98
98
  deleteRecord: (params: {
99
99
  table: string;
100
100
  sys_id: string;
package/dist/client.js CHANGED
@@ -7,15 +7,15 @@
7
7
  * - `buildAgent.*` — reads via the sn_build_agent API, with graceful
8
8
  * fallback to Table API / sys_dictionary when the
9
9
  * Build Agent plugin is unavailable
10
- * - `claude.*` — writes via the Dovetail Scripted REST API
11
- * (/api/cadso/dovetail/*), which handles update-set + scope
12
- * switching atomically so every write lands in the right
13
- * update set without touching sys_user_preference.
14
- * Falls back to the legacy /api/cadso/claude/* path on
15
- * instances where the API has not yet been re-imported.
16
- * The namespace name `claude` is preserved for API
17
- * compatibility; the underlying server-side API is now
18
- * named "Dovetail".
10
+ * - `claude.*` — writes via the Dovetail core Scripted REST API
11
+ * (/api/cadso/dovetail_core/*), which handles update-set +
12
+ * scope switching atomically so every write lands in the
13
+ * right update set without touching sys_user_preference.
14
+ * Falls back to the legacy global-scope /api/cadso/dovetail/*
15
+ * path on instances without the Dovetail app installed.
16
+ * The `claude.*` property name is preserved for API
17
+ * compatibility; the server-side API now lives in the
18
+ * Dovetail scoped application as "Dovetail Core".
19
19
  *
20
20
  * Env fallbacks mirror prior dashboard-fetch helpers so dev setups that already
21
21
  * have SN_INSTANCE/SN_USER/SN_PASSWORD work without reconfiguration.
@@ -104,11 +104,12 @@ function createClient(config = {}) {
104
104
  validateStatus: function () { return true; }
105
105
  });
106
106
  var lastAt = 0;
107
- // Dovetail Scripted REST API rebrand: prefer /api/cadso/dovetail/* and fall back
108
- // to the legacy /api/cadso/claude/* path on instances where the rename hasn't
109
- // been imported yet. Latch the legacy flag after the first 404 to avoid paying
110
- // the round-trip cost on every subsequent call.
111
- var useDovetailLegacyClaudePath = false;
107
+ // Dovetail core Scripted REST API: prefer the Dovetail-app path
108
+ // /api/cadso/dovetail_core/* and fall back to the legacy global-scope path
109
+ // /api/cadso/dovetail/* on instances that don't have the Dovetail app yet.
110
+ // Latch the legacy flag after the first 404 to avoid paying the round-trip
111
+ // cost on every subsequent call.
112
+ var useDovetailLegacyPath = false;
112
113
  async function request(cfg, ctx) {
113
114
  var attempt429 = 0;
114
115
  var attempt5xx = 0;
@@ -160,24 +161,24 @@ function createClient(config = {}) {
160
161
  return res.data;
161
162
  }
162
163
  }
163
- // Dovetail Scripted REST API request: try /api/cadso/dovetail/<op>, fall back to
164
- // /api/cadso/claude/<op> on 404 (with a one-time deprecation warning).
164
+ // Dovetail core Scripted REST API request: try /api/cadso/dovetail_core/<op>,
165
+ // fall back to the legacy /api/cadso/dovetail/<op> on 404 (one-time warning).
165
166
  async function dovetailRequest(method, op, body, params, ctx) {
166
- var url = useDovetailLegacyClaudePath
167
- ? "/api/cadso/claude/" + op
168
- : "/api/cadso/dovetail/" + op;
167
+ var url = useDovetailLegacyPath
168
+ ? "/api/cadso/dovetail/" + op
169
+ : "/api/cadso/dovetail_core/" + op;
169
170
  try {
170
171
  return await request({ method: method, url: url, data: body, params: params }, ctx);
171
172
  }
172
173
  catch (e) {
173
174
  var msg = e && e.message ? String(e.message) : "";
174
- if (!useDovetailLegacyClaudePath && msg.indexOf("SN 404 on") === 0) {
175
+ if (!useDovetailLegacyPath && msg.indexOf("SN 404 on") === 0) {
175
176
  // eslint-disable-next-line no-console
176
- console.warn("[deprecation] /api/cadso/dovetail/" + op +
177
- " returned 404. Falling back to legacy /api/cadso/claude/" + op +
178
- ". Re-import the Dovetail Scripted REST API XML on your ServiceNow instance to silence this warning.");
179
- useDovetailLegacyClaudePath = true;
180
- var legacyUrl = "/api/cadso/claude/" + op;
177
+ console.warn("[deprecation] /api/cadso/dovetail_core/" + op +
178
+ " returned 404. Falling back to legacy /api/cadso/dovetail/" + op +
179
+ ". Install the Dovetail application's Scripted REST APIs to silence this warning.");
180
+ useDovetailLegacyPath = true;
181
+ var legacyUrl = "/api/cadso/dovetail/" + op;
181
182
  return await request({ method: method, url: legacyUrl, data: body, params: params }, ctx);
182
183
  }
183
184
  throw e;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Loads ServiceNow credentials for the `dove-sn` CLI and its MCP server.
3
+ *
4
+ * Resolution order for the env file:
5
+ * 1. An explicit `--env <path>` / `--env-file <path>` flag (passed in here).
6
+ * 2. The `DOVETAIL_ENV_FILE` environment variable — lets an MCP host point
7
+ * `dove-sn mcp` at a specific credential file without a CLI flag.
8
+ * 3. The default `.env` in the current working directory.
9
+ *
10
+ * dotenv does not override variables already present in process.env, so an
11
+ * explicit file augments (never clobbers) credentials the parent shell exported.
12
+ *
13
+ * @param {string} [explicitPath] - Path from the `--env` / `--env-file` flag.
14
+ */
15
+ export declare function loadEnvFile(explicitPath?: string): void;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadEnvFile = loadEnvFile;
7
+ const dotenv_1 = __importDefault(require("dotenv"));
8
+ const path_1 = __importDefault(require("path"));
9
+ /**
10
+ * Loads ServiceNow credentials for the `dove-sn` CLI and its MCP server.
11
+ *
12
+ * Resolution order for the env file:
13
+ * 1. An explicit `--env <path>` / `--env-file <path>` flag (passed in here).
14
+ * 2. The `DOVETAIL_ENV_FILE` environment variable — lets an MCP host point
15
+ * `dove-sn mcp` at a specific credential file without a CLI flag.
16
+ * 3. The default `.env` in the current working directory.
17
+ *
18
+ * dotenv does not override variables already present in process.env, so an
19
+ * explicit file augments (never clobbers) credentials the parent shell exported.
20
+ *
21
+ * @param {string} [explicitPath] - Path from the `--env` / `--env-file` flag.
22
+ */
23
+ function loadEnvFile(explicitPath) {
24
+ var raw = explicitPath || process.env.DOVETAIL_ENV_FILE;
25
+ if (raw) {
26
+ var resolved = path_1.default.isAbsolute(raw) ? raw : path_1.default.resolve(process.cwd(), raw);
27
+ dotenv_1.default.config({ path: resolved });
28
+ return;
29
+ }
30
+ // No explicit selection — load .env from cwd if it exists (no-op otherwise).
31
+ dotenv_1.default.config();
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenonhq/dovetail-servicenow",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },
@@ -20,6 +20,7 @@
20
20
  "dependencies": {
21
21
  "@modelcontextprotocol/sdk": "^1.29.0",
22
22
  "axios": "^1.5.1",
23
+ "dotenv": "^16.3.1",
23
24
  "zod": "^3.23.0"
24
25
  },
25
26
  "devDependencies": {