zinkee 0.1.1 → 0.1.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zinkee",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "CLI for Zinkee API v2",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,7 +20,7 @@ import {
20
20
  type UpdateAutomationInput,
21
21
  } from "../api/automations.js";
22
22
  import { ApiClient } from "../client.js";
23
- import { defaultConfigPath, readConfig } from "../config.js";
23
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
24
24
  import { parseJsonAssignment, parseKeyValue } from "../parsers/kv.js";
25
25
  import {
26
26
  normalizeUuidOrSlug,
@@ -210,7 +210,7 @@ function createAutomationsApi(
210
210
  filePath: string,
211
211
  ): { api: AutomationsApi; json: boolean; readOnly: boolean } {
212
212
  try {
213
- const config = readConfig(filePath);
213
+ const config = readRuntimeConfig(filePath);
214
214
  const runtime = resolveRuntimeContext(config, getGlobalOptions(command));
215
215
 
216
216
  if (!runtime.baseUrl) {
@@ -8,7 +8,7 @@ import {
8
8
  type CreateCommentInput,
9
9
  } from "../api/comments.js";
10
10
  import { ApiClient } from "../client.js";
11
- import { defaultConfigPath, readConfig } from "../config.js";
11
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
12
12
  import {
13
13
  normalizeUuidOrSlug,
14
14
  type NormalizedUuidOrSlug,
@@ -85,7 +85,7 @@ function createCommentsApi(
85
85
  filePath: string,
86
86
  ): { api: CommentsApi; json: boolean; readOnly: boolean } {
87
87
  try {
88
- const config = readConfig(filePath);
88
+ const config = readRuntimeConfig(filePath);
89
89
  const runtime = resolveRuntimeContext(config, getGlobalOptions(command));
90
90
 
91
91
  if (!runtime.baseUrl) {
@@ -5,7 +5,7 @@ import { Command, InvalidArgumentError } from "commander";
5
5
 
6
6
  import { DisplaysApi, type DisplayResource, type DisplaySummary } from "../api/displays.js";
7
7
  import { ApiClient } from "../client.js";
8
- import { defaultConfigPath, readConfig } from "../config.js";
8
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
9
9
  import { normalizeUuidOrSlug, type NormalizedUuidOrSlug } from "../parsers/selectors.js";
10
10
  import { resolveRuntimeContext } from "../runtime-context.js";
11
11
  import type { RuntimeOverrides } from "../types.js";
@@ -148,7 +148,7 @@ function createDisplaysApi(
148
148
  filePath: string,
149
149
  ): { api: DisplaysApi; json: boolean; readOnly: boolean } {
150
150
  try {
151
- const config = readConfig(filePath);
151
+ const config = readRuntimeConfig(filePath);
152
152
  const runtime = resolveRuntimeContext(config, getGlobalOptions(command));
153
153
 
154
154
  if (!runtime.baseUrl) {
@@ -6,7 +6,7 @@ import { Command, InvalidArgumentError } from "commander";
6
6
 
7
7
  import { FilesApi } from "../api/files.js";
8
8
  import { ApiClient } from "../client.js";
9
- import { defaultConfigPath, readConfig } from "../config.js";
9
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
10
10
  import { normalizeUuidOrSlug, type NormalizedUuidOrSlug } from "../parsers/selectors.js";
11
11
  import { resolveRuntimeContext } from "../runtime-context.js";
12
12
  import type { JsonObject, RuntimeOverrides } from "../types.js";
@@ -83,7 +83,7 @@ function createFilesApi(
83
83
  filePath: string,
84
84
  ): { api: FilesApi; json: boolean; readOnly: boolean } {
85
85
  try {
86
- const config = readConfig(filePath);
86
+ const config = readRuntimeConfig(filePath);
87
87
  const runtime = resolveRuntimeContext(config, getGlobalOptions(command));
88
88
 
89
89
  if (!runtime.baseUrl) {
@@ -5,7 +5,7 @@ import { Command, InvalidArgumentError } from "commander";
5
5
 
6
6
  import { NavigationApi, type NavigationFolder } from "../api/navigation.js";
7
7
  import { ApiClient } from "../client.js";
8
- import { defaultConfigPath, readConfig } from "../config.js";
8
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
9
9
  import { normalizeUuidOrSlug, type NormalizedUuidOrSlug } from "../parsers/selectors.js";
10
10
  import { resolveRuntimeContext } from "../runtime-context.js";
11
11
  import type { RuntimeOverrides } from "../types.js";
@@ -72,7 +72,7 @@ function createNavigationApi(
72
72
  filePath: string,
73
73
  ): { api: NavigationApi; json: boolean; readOnly: boolean } {
74
74
  try {
75
- const config = readConfig(filePath);
75
+ const config = readRuntimeConfig(filePath);
76
76
  const runtime = resolveRuntimeContext(config, getGlobalOptions(command));
77
77
 
78
78
  if (!runtime.baseUrl) {
@@ -14,7 +14,7 @@ import {
14
14
  } from "../api/records.js";
15
15
  import { SchemasApi } from "../api/schemas.js";
16
16
  import { ApiClient } from "../client.js";
17
- import { defaultConfigPath, readConfig } from "../config.js";
17
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
18
18
  import {
19
19
  type ParsedExpression,
20
20
  parseExpression,
@@ -128,7 +128,7 @@ function createRecordsApi(
128
128
  readOnly: boolean;
129
129
  } {
130
130
  try {
131
- const config = readConfig(filePath);
131
+ const config = readRuntimeConfig(filePath);
132
132
  const runtime = resolveRuntimeContext(config, getGlobalOptions(command));
133
133
 
134
134
  if (!runtime.baseUrl) {
@@ -14,7 +14,7 @@ import {
14
14
  } from "../api/schemas.js";
15
15
  import { ApiClientError } from "../client.js";
16
16
  import { ApiClient } from "../client.js";
17
- import { defaultConfigPath, readConfig } from "../config.js";
17
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
18
18
  import {
19
19
  normalizeUuidOrSlug,
20
20
  type NormalizedUuidOrSlug,
@@ -124,7 +124,7 @@ function createSchemasApi(
124
124
  filePath: string,
125
125
  ): { api: SchemasApi; json: boolean; profile: string; readOnly: boolean } {
126
126
  try {
127
- const config = readConfig(filePath);
127
+ const config = readRuntimeConfig(filePath);
128
128
  const runtime = resolveRuntimeContext(config, getGlobalOptions(command));
129
129
 
130
130
  if (!runtime.baseUrl) {
@@ -10,7 +10,7 @@ import {
10
10
  type UpdateTeamspaceFolderInput,
11
11
  } from "../api/teamspace.js";
12
12
  import { ApiClient } from "../client.js";
13
- import { defaultConfigPath, readConfig } from "../config.js";
13
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
14
14
  import {
15
15
  normalizeUuidOrSlug,
16
16
  type NormalizedUuidOrSlug,
@@ -98,7 +98,7 @@ function createTeamspaceApi(
98
98
  filePath: string,
99
99
  ): { api: TeamspaceApi; json: boolean; readOnly: boolean } {
100
100
  try {
101
- const config = readConfig(filePath);
101
+ const config = readRuntimeConfig(filePath);
102
102
  const runtime = resolveRuntimeContext(config, getGlobalOptions(command));
103
103
 
104
104
  if (!runtime.baseUrl) {
@@ -1,9 +1,17 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
3
  import {
4
+ DEFAULT_PRODUCTION_BASE_URL,
5
+ ENV_API_KEY,
6
+ ENV_BASE_URL,
7
+ ENV_PROFILE,
4
8
  parseConfig,
5
9
  redactConfig,
6
10
  redactSecret,
11
+ readRuntimeConfig,
12
+ readEnvApiKey,
13
+ readEnvBaseUrl,
14
+ readEnvProfile,
7
15
  removeProfileConfig,
8
16
  resolveProfile,
9
17
  serializeConfig,
@@ -30,6 +38,14 @@ retry_count = 3
30
38
  });
31
39
  });
32
40
 
41
+ describe("readRuntimeConfig", () => {
42
+ it("returns an empty runtime config when the file does not exist", () => {
43
+ expect(readRuntimeConfig("/tmp/definitely-missing-zinkee-config.toml")).toEqual({
44
+ profiles: {},
45
+ });
46
+ });
47
+ });
48
+
33
49
  describe("resolveProfile", () => {
34
50
  it("prefers explicit profile over default_profile", () => {
35
51
  const config = {
@@ -89,8 +105,167 @@ describe("resolveRuntimeContext", () => {
89
105
  apiKey: "override-token",
90
106
  readOnly: true,
91
107
  json: false,
108
+ profileSource: "flag",
109
+ baseUrlSource: "flag",
110
+ apiKeySource: "flag",
111
+ });
112
+ });
113
+
114
+ it("resolves runtime directly from env vars without config", () => {
115
+ const previousApiKey = process.env[ENV_API_KEY];
116
+ const previousBaseUrl = process.env[ENV_BASE_URL];
117
+ const previousProfile = process.env[ENV_PROFILE];
118
+ process.env[ENV_API_KEY] = "env-token";
119
+ process.env[ENV_BASE_URL] = "http://localhost:8088/";
120
+ delete process.env[ENV_PROFILE];
121
+
122
+ try {
123
+ expect(resolveRuntimeContext({ profiles: {} }, {})).toEqual({
124
+ profile: "runtime",
125
+ baseUrl: "http://localhost:8088",
126
+ apiKey: "env-token",
127
+ readOnly: false,
128
+ json: false,
129
+ profileSource: undefined,
130
+ baseUrlSource: "env",
131
+ apiKeySource: "env",
132
+ });
133
+ } finally {
134
+ if (previousApiKey === undefined) delete process.env[ENV_API_KEY];
135
+ else process.env[ENV_API_KEY] = previousApiKey;
136
+ if (previousBaseUrl === undefined) delete process.env[ENV_BASE_URL];
137
+ else process.env[ENV_BASE_URL] = previousBaseUrl;
138
+ if (previousProfile === undefined) delete process.env[ENV_PROFILE];
139
+ else process.env[ENV_PROFILE] = previousProfile;
140
+ }
141
+ });
142
+
143
+ it("prefers env vars over config values", () => {
144
+ const previousApiKey = process.env[ENV_API_KEY];
145
+ const previousBaseUrl = process.env[ENV_BASE_URL];
146
+ const previousProfile = process.env[ENV_PROFILE];
147
+ process.env[ENV_API_KEY] = "env-token";
148
+ process.env[ENV_BASE_URL] = "http://localhost:8088";
149
+ process.env[ENV_PROFILE] = "local";
150
+
151
+ try {
152
+ expect(
153
+ resolveRuntimeContext({
154
+ defaultProfile: "prod",
155
+ profiles: {
156
+ prod: { apiKey: "prod-token", baseUrl: "https://api.zinkee.com" },
157
+ local: { apiKey: "local-token", baseUrl: "http://127.0.0.1:9999" },
158
+ },
159
+ }, {}),
160
+ ).toEqual({
161
+ profile: "local",
162
+ baseUrl: "http://localhost:8088",
163
+ apiKey: "env-token",
164
+ readOnly: false,
165
+ json: false,
166
+ profileSource: "env",
167
+ baseUrlSource: "env",
168
+ apiKeySource: "env",
169
+ });
170
+ } finally {
171
+ if (previousApiKey === undefined) delete process.env[ENV_API_KEY];
172
+ else process.env[ENV_API_KEY] = previousApiKey;
173
+ if (previousBaseUrl === undefined) delete process.env[ENV_BASE_URL];
174
+ else process.env[ENV_BASE_URL] = previousBaseUrl;
175
+ if (previousProfile === undefined) delete process.env[ENV_PROFILE];
176
+ else process.env[ENV_PROFILE] = previousProfile;
177
+ }
178
+ });
179
+
180
+ it("falls back to the production base URL when the resolved profile has no base URL", () => {
181
+ expect(
182
+ resolveRuntimeContext({
183
+ defaultProfile: "prod",
184
+ profiles: {
185
+ prod: { apiKey: "prod-token" },
186
+ },
187
+ }, {}),
188
+ ).toEqual({
189
+ profile: "prod",
190
+ baseUrl: DEFAULT_PRODUCTION_BASE_URL,
191
+ apiKey: "prod-token",
192
+ readOnly: false,
193
+ json: false,
194
+ profileSource: "config",
195
+ baseUrlSource: "config",
196
+ apiKeySource: "config",
92
197
  });
93
198
  });
199
+
200
+ it("still prefers an explicit base URL override over the production fallback", () => {
201
+ expect(
202
+ resolveRuntimeContext({
203
+ defaultProfile: "prod",
204
+ profiles: {
205
+ prod: { apiKey: "prod-token" },
206
+ },
207
+ }, {
208
+ profile: "prod",
209
+ baseUrl: "http://localhost:8088",
210
+ apiKey: "override-token",
211
+ }),
212
+ ).toEqual({
213
+ profile: "prod",
214
+ baseUrl: "http://localhost:8088",
215
+ apiKey: "override-token",
216
+ readOnly: false,
217
+ json: false,
218
+ profileSource: "flag",
219
+ baseUrlSource: "flag",
220
+ apiKeySource: "flag",
221
+ });
222
+ });
223
+
224
+ it("throws a clear error when runtime api key is provided without base url", () => {
225
+ const previousApiKey = process.env[ENV_API_KEY];
226
+ const previousBaseUrl = process.env[ENV_BASE_URL];
227
+ process.env[ENV_API_KEY] = "env-token";
228
+ delete process.env[ENV_BASE_URL];
229
+
230
+ try {
231
+ expect(() => resolveRuntimeContext({ profiles: {} }, {})).toThrowError(
232
+ `Runtime API key was provided, but ${ENV_BASE_URL} or --base-url is missing.`,
233
+ );
234
+ } finally {
235
+ if (previousApiKey === undefined) delete process.env[ENV_API_KEY];
236
+ else process.env[ENV_API_KEY] = previousApiKey;
237
+ if (previousBaseUrl === undefined) delete process.env[ENV_BASE_URL];
238
+ else process.env[ENV_BASE_URL] = previousBaseUrl;
239
+ }
240
+ });
241
+
242
+ it("throws a clear error when runtime base url is provided without api key", () => {
243
+ const previousApiKey = process.env[ENV_API_KEY];
244
+ const previousBaseUrl = process.env[ENV_BASE_URL];
245
+ delete process.env[ENV_API_KEY];
246
+ process.env[ENV_BASE_URL] = "http://localhost:8088";
247
+
248
+ try {
249
+ expect(() => resolveRuntimeContext({ profiles: {} }, {})).toThrowError(
250
+ `Runtime base URL was provided, but ${ENV_API_KEY} or --api-key is missing.`,
251
+ );
252
+ } finally {
253
+ if (previousApiKey === undefined) delete process.env[ENV_API_KEY];
254
+ else process.env[ENV_API_KEY] = previousApiKey;
255
+ if (previousBaseUrl === undefined) delete process.env[ENV_BASE_URL];
256
+ else process.env[ENV_BASE_URL] = previousBaseUrl;
257
+ }
258
+ });
259
+ });
260
+
261
+ describe("env readers", () => {
262
+ it("normalizes env values", () => {
263
+ expect(readEnvApiKey({ [ENV_API_KEY]: " token " } as NodeJS.ProcessEnv)).toBe("token");
264
+ expect(readEnvProfile({ [ENV_PROFILE]: " local " } as NodeJS.ProcessEnv)).toBe("local");
265
+ expect(readEnvBaseUrl({ [ENV_BASE_URL]: " http://localhost:8088/ " } as NodeJS.ProcessEnv)).toBe(
266
+ "http://localhost:8088",
267
+ );
268
+ });
94
269
  });
95
270
 
96
271
  describe("config mutation helpers", () => {
package/src/config.ts CHANGED
@@ -8,6 +8,10 @@ import type { AppConfig, ProfileConfig, RuntimeOverrides, ResolvedProfile } from
8
8
 
9
9
  export const defaultConfigPath = join(homedir(), ".config", "zinkee", "config.toml");
10
10
  export const redactedSecretMask = "********";
11
+ export const ENV_API_KEY = "ZINKEE_API_KEY";
12
+ export const ENV_BASE_URL = "ZINKEE_API_BASE_URL";
13
+ export const ENV_PROFILE = "ZINKEE_PROFILE";
14
+ export const DEFAULT_PRODUCTION_BASE_URL = "https://api-z2.zinkee.com";
11
15
 
12
16
  export class ProfileResolutionError extends Error {
13
17
  override name = "ProfileResolutionError";
@@ -25,6 +29,11 @@ function toStringValue(value: unknown): string | undefined {
25
29
  return typeof value === "string" ? value : undefined;
26
30
  }
27
31
 
32
+ function toNonEmptyString(value: string | undefined): string | undefined {
33
+ const normalized = value?.trim();
34
+ return normalized ? normalized : undefined;
35
+ }
36
+
28
37
  function parseProfileConfig(value: unknown): ProfileConfig {
29
38
  const profile: ProfileConfig = {};
30
39
 
@@ -102,6 +111,10 @@ export function readConfigIfExists(filePath: string = defaultConfigPath): AppCon
102
111
  }
103
112
  }
104
113
 
114
+ export function readRuntimeConfig(filePath: string = defaultConfigPath): AppConfig {
115
+ return readConfigIfExists(filePath) ?? { profiles: {} };
116
+ }
117
+
105
118
  function serializeProfileConfig(profile: ProfileConfig): Record<string, unknown> {
106
119
  const serialized: Record<string, unknown> = {};
107
120
 
@@ -246,3 +259,40 @@ export function resolveProfile(
246
259
 
247
260
  throw new ProfileResolutionError("No profile could be resolved from config.");
248
261
  }
262
+
263
+ export function validateBaseUrl(value: string): string {
264
+ let parsed: URL;
265
+
266
+ try {
267
+ parsed = new URL(value);
268
+ } catch {
269
+ throw new ProfileResolutionError(
270
+ `Environment variable ${ENV_BASE_URL} must be an absolute http(s) URL.`,
271
+ );
272
+ }
273
+
274
+ if (!["http:", "https:"].includes(parsed.protocol) || !parsed.host) {
275
+ throw new ProfileResolutionError(
276
+ `Environment variable ${ENV_BASE_URL} must be an absolute http(s) URL.`,
277
+ );
278
+ }
279
+
280
+ return value.replace(/\/+$/, "");
281
+ }
282
+
283
+ export function readEnvApiKey(env: NodeJS.ProcessEnv = process.env): string | undefined {
284
+ return toNonEmptyString(env[ENV_API_KEY]);
285
+ }
286
+
287
+ export function readEnvBaseUrl(env: NodeJS.ProcessEnv = process.env): string | undefined {
288
+ const baseUrl = toNonEmptyString(env[ENV_BASE_URL]);
289
+ if (!baseUrl) {
290
+ return undefined;
291
+ }
292
+
293
+ return validateBaseUrl(baseUrl);
294
+ }
295
+
296
+ export function readEnvProfile(env: NodeJS.ProcessEnv = process.env): string | undefined {
297
+ return toNonEmptyString(env[ENV_PROFILE]);
298
+ }
@@ -1,18 +1,97 @@
1
1
  import type { AppConfig, RuntimeContext, RuntimeOverrides } from "./types.js";
2
2
 
3
- import { resolveProfile } from "./config.js";
3
+ import {
4
+ DEFAULT_PRODUCTION_BASE_URL,
5
+ ENV_API_KEY,
6
+ ENV_BASE_URL,
7
+ readEnvApiKey,
8
+ readEnvBaseUrl,
9
+ readEnvProfile,
10
+ resolveProfile,
11
+ ProfileResolutionError,
12
+ } from "./config.js";
4
13
 
5
14
  export function resolveRuntimeContext(
6
15
  config: AppConfig,
7
16
  overrides: RuntimeOverrides = {},
8
17
  ): RuntimeContext {
9
- const profile = resolveProfile(config, overrides);
18
+ const envProfile = readEnvProfile();
19
+ const envApiKey = readEnvApiKey();
20
+ const envBaseUrl = readEnvBaseUrl();
21
+
22
+ const profileOverride = overrides.profile ?? envProfile;
23
+ const apiKeyOverride = overrides.apiKey ?? envApiKey;
24
+ const baseUrlOverride = overrides.baseUrl ?? envBaseUrl;
25
+
26
+ if (apiKeyOverride && !baseUrlOverride) {
27
+ throw new ProfileResolutionError(
28
+ `Runtime API key was provided, but ${ENV_BASE_URL} or --base-url is missing.`,
29
+ );
30
+ }
31
+
32
+ if (baseUrlOverride && !apiKeyOverride) {
33
+ throw new ProfileResolutionError(
34
+ `Runtime base URL was provided, but ${ENV_API_KEY} or --api-key is missing.`,
35
+ );
36
+ }
37
+
38
+ if (apiKeyOverride && baseUrlOverride) {
39
+ return {
40
+ profile: profileOverride ?? "runtime",
41
+ baseUrl: baseUrlOverride,
42
+ apiKey: apiKeyOverride,
43
+ readOnly: overrides.readOnly ?? false,
44
+ json: overrides.json ?? false,
45
+ profileSource:
46
+ overrides.profile !== undefined
47
+ ? "flag"
48
+ : envProfile !== undefined
49
+ ? "env"
50
+ : undefined,
51
+ baseUrlSource:
52
+ overrides.baseUrl !== undefined
53
+ ? "flag"
54
+ : envBaseUrl !== undefined
55
+ ? "env"
56
+ : undefined,
57
+ apiKeySource:
58
+ overrides.apiKey !== undefined
59
+ ? "flag"
60
+ : envApiKey !== undefined
61
+ ? "env"
62
+ : undefined,
63
+ };
64
+ }
65
+
66
+ const profile = resolveProfile(config, {
67
+ profile: profileOverride,
68
+ baseUrl: baseUrlOverride,
69
+ apiKey: apiKeyOverride,
70
+ });
10
71
 
11
72
  return {
12
73
  profile: profile.name,
13
- baseUrl: overrides.baseUrl ?? profile.baseUrl,
14
- apiKey: overrides.apiKey ?? profile.apiKey,
74
+ baseUrl: baseUrlOverride ?? profile.baseUrl ?? DEFAULT_PRODUCTION_BASE_URL,
75
+ apiKey: apiKeyOverride ?? profile.apiKey,
15
76
  readOnly: overrides.readOnly ?? false,
16
77
  json: overrides.json ?? false,
78
+ profileSource:
79
+ overrides.profile !== undefined
80
+ ? "flag"
81
+ : envProfile !== undefined
82
+ ? "env"
83
+ : "config",
84
+ baseUrlSource:
85
+ overrides.baseUrl !== undefined
86
+ ? "flag"
87
+ : envBaseUrl !== undefined
88
+ ? "env"
89
+ : "config",
90
+ apiKeySource:
91
+ overrides.apiKey !== undefined
92
+ ? "flag"
93
+ : envApiKey !== undefined
94
+ ? "env"
95
+ : "config",
17
96
  };
18
97
  }
package/src/types.ts CHANGED
@@ -26,12 +26,17 @@ export interface RuntimeOverrides {
26
26
  json?: boolean;
27
27
  }
28
28
 
29
+ export type RuntimeValueSource = "flag" | "env" | "config";
30
+
29
31
  export interface RuntimeContext {
30
32
  profile: string;
31
33
  baseUrl?: string;
32
34
  apiKey?: string;
33
35
  readOnly: boolean;
34
36
  json: boolean;
37
+ profileSource?: RuntimeValueSource;
38
+ baseUrlSource?: RuntimeValueSource;
39
+ apiKeySource?: RuntimeValueSource;
35
40
  }
36
41
 
37
42
  export type JsonScalar = string | number | boolean | null;
@@ -1,7 +1,7 @@
1
1
  import { AutomationsApi } from "../api/automations.js";
2
2
  import { SchemasApi, type ApiSchema, type ApiSchemaField } from "../api/schemas.js";
3
3
  import { ApiClient } from "../client.js";
4
- import { defaultConfigPath, readConfig } from "../config.js";
4
+ import { defaultConfigPath, readRuntimeConfig } from "../config.js";
5
5
  import type { NormalizedUuidOrSlug } from "../parsers/selectors.js";
6
6
  import { resolveRuntimeContext } from "../runtime-context.js";
7
7
  import type { RuntimeOverrides } from "../types.js";
@@ -466,7 +466,7 @@ async function createExampleAutomationContext(
466
466
  }
467
467
 
468
468
  try {
469
- const config = readConfig(options.configPath ?? defaultConfigPath);
469
+ const config = readRuntimeConfig(options.configPath ?? defaultConfigPath);
470
470
  const runtime = resolveRuntimeContext(config, options.overrides);
471
471
 
472
472
  if (!runtime.baseUrl) {