@cerios/salesforce-sobjectly 1.1.0 → 1.2.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
@@ -54,12 +54,19 @@ export default defineConfig({
54
54
  apiVersion: "v66.0",
55
55
  output: "src/generated/sobjects.ts",
56
56
  sobjects: ["Account", "Contact", "Case", "User"],
57
- // Reads SF_LOGIN_URL, SF_CLIENT_ID and SF_CLIENT_SECRET from the environment.
58
- auth: { type: "clientCredentials" },
57
+ // Fill these in from process.env (any variable names), a secret store or elsewhere.
58
+ auth: {
59
+ type: "clientCredentials",
60
+ loginUrl: process.env.SF_LOGIN_URL,
61
+ clientId: process.env.SF_CLIENT_ID,
62
+ clientSecret: process.env.SF_CLIENT_SECRET,
63
+ },
59
64
  picklists: "union",
60
65
  });
61
66
  ```
62
67
 
68
+ The variable names are only suggestions; use whatever names your environment already has. A JSON config uses `"${NAME}"` placeholders instead. See [Auth](docs/codegen.md#auth) for every login method.
69
+
63
70
  ### 2. Generate types for your org
64
71
 
65
72
  ```bash
@@ -79,6 +86,7 @@ const sf = new SalesforceClient<SObjectRegistry>({
79
86
  clientId: process.env.SF_CLIENT_ID!,
80
87
  clientSecret: process.env.SF_CLIENT_SECRET!,
81
88
  }),
89
+ // or reuse the config's auth: auth: await loadAuth() from "@cerios/salesforce-sobjectly/codegen"
82
90
  });
83
91
 
84
92
  // CRUD
@@ -107,16 +115,16 @@ for await (const contact of sf.iterate(sf.soql("Contact").select("Id", "Email"))
107
115
 
108
116
  ## 📖 Documentation
109
117
 
110
- | Guide | What's in it |
111
- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
112
- | [Authentication](docs/authentication.md) | Salesforce CLI, access tokens, client credentials, JWT bearer, refresh tokens, custom providers |
113
- | [Code generation](docs/codegen.md) | Config reference, type mapping, required fields, picklists, CI usage |
114
- | [SOQL builder](docs/soql.md) | Selecting, relationships, filters, aggregates, pagination, escaping |
115
- | [Composite & collections](docs/composite-and-collections.md) | Composite with references, batch, tree, graph, sObject collections |
116
- | [Approvals, files, reports & more](docs/platform.md) | Record types, picklists, platform events, approvals, quick actions, UI API, files, reports, query plans |
117
- | [Bulk API 2.0](docs/bulk.md) | Ingest jobs, query jobs, CSV handling |
118
- | [Transports](docs/transports.md) | Custom HTTP clients (axios and Playwright examples), streaming, hooks, retries, timeouts |
119
- | [Endpoint coverage](docs/endpoints.md) | Which Salesforce REST resources have typed helpers |
118
+ | Guide | What's in it |
119
+ | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
120
+ | [Authentication](docs/authentication.md) | Salesforce CLI, access tokens, client credentials, JWT bearer, refresh tokens, custom providers |
121
+ | [Code generation](docs/codegen.md) | Config reference, type mapping, required fields, picklists, CI usage |
122
+ | [SOQL builder](docs/soql.md) | Selecting, relationships, filters, aggregates, pagination, escaping |
123
+ | [Composite & collections](docs/composite-and-collections.md) | Composite with references, batch, tree, graph, sObject collections |
124
+ | [Approvals, files, reports & more](docs/platform.md) | Record types, picklists, platform events, approvals, quick actions, UI API, files, reports, query plans |
125
+ | [Bulk API 2.0](docs/bulk.md) | Ingest jobs, query jobs, CSV handling |
126
+ | [Transports](docs/transports.md) | Custom HTTP clients (axios and Playwright examples), streaming, hooks and request logging, retries, timeouts |
127
+ | [Endpoint coverage](docs/endpoints.md) | Which Salesforce REST resources have typed helpers |
120
128
 
121
129
  ## 🧭 API Overview
122
130
 
package/dist/cli.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- const require_sf_cli = require("./sf-cli-R6LHwqoo.cjs");
3
- const require_codegen = require("./codegen-Bylrt2Ju.cjs");
2
+ const require_sf_cli = require("./sf-cli-S2BrCbik.cjs");
3
+ const require_codegen = require("./codegen-Daud-Grz.cjs");
4
4
  let node_fs = require("node:fs");
5
5
  let node_path = require("node:path");
6
6
  let node_util = require("node:util");
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { Lt as __commonJSMin, Mt as init_api_version, Pt as normalizeApiVersion } from "./sf-cli-_Ua-M_Zi.mjs";
3
- import { C as init_validate_config, S as PICKLIST_MODES, a as init_prompter, c as init_init, d as runInit, g as loadConfig, l as parseSObjects, m as findConfigFiles, n as generate, o as readlinePrompter, r as init_codegen, t as checkGenerated } from "./codegen-C6MEYiWo.mjs";
2
+ import { Lt as __commonJSMin, Mt as init_api_version, Pt as normalizeApiVersion } from "./sf-cli-D2PgjErx.mjs";
3
+ import { T as init_validate_config, _ as findConfigFiles, f as runInit, l as init_init, n as generate, o as init_prompter, r as init_codegen, s as readlinePrompter, t as checkGenerated, u as parseSObjects, w as PICKLIST_MODES, y as loadConfig } from "./codegen-0L2ebG9j.mjs";
4
4
  import { existsSync } from "node:fs";
5
5
  import { resolve } from "node:path";
6
6
  import { parseArgs } from "node:util";
@@ -1,4 +1,4 @@
1
- import { Mt as init_api_version, Nt as isApiVersion, Pt as normalizeApiVersion, Rt as __esmMin, d as init_client, i as clientCredentials, n as sfCli, o as init_providers, r as accessToken, s as jwtBearer, t as init_sf_cli, u as SalesforceClient } from "./sf-cli-_Ua-M_Zi.mjs";
1
+ import { Mt as init_api_version, Nt as isApiVersion, Pt as normalizeApiVersion, Rt as __esmMin, d as init_client, i as clientCredentials, n as sfCli, o as init_providers, r as accessToken, s as jwtBearer, t as init_sf_cli, u as SalesforceClient } from "./sf-cli-D2PgjErx.mjs";
2
2
  import { createHash } from "node:crypto";
3
3
  import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
@@ -506,8 +506,17 @@ function validateAuth(value, { json, problem }) {
506
506
  problem(`auth.type: must be one of ${Object.keys(AUTH_OPTIONS).join(", ")}, got ${show(type)}.`);
507
507
  return;
508
508
  }
509
- for (const [key, option] of Object.entries(rest)) if (!allowed.includes(key)) problem(`auth.${key}: not an option of "${String(type)}". Valid options: ${allowed.join(", ")}.`);
510
- else if (typeof option !== "string" || option.length === 0) problem(`auth.${key}: must be a non-empty string, got ${show(option)}.`);
509
+ for (const [key, option] of Object.entries(rest)) if (!allowed.includes(key)) {
510
+ const valid = allowed.filter((name) => !(name in DEPRECATED_AUTH_OPTIONS));
511
+ problem(`auth.${key}: not an option of "${String(type)}". Valid options: ${valid.join(", ")}.`);
512
+ } else validateAuthOption(key, option, rest, problem);
513
+ }
514
+ function validateAuthOption(key, option, setting, problem) {
515
+ const replacement = DEPRECATED_AUTH_OPTIONS[key];
516
+ if (replacement !== void 0 && replacement in setting) problem(`auth.${key}: use either ${replacement} or ${key}, not both.`);
517
+ else if (replacement !== void 0) {
518
+ if (typeof option !== "string" || option.length === 0) problem(`auth.${key}: must be a non-empty string, got ${show(option)}.`);
519
+ } else if (option !== void 0 && typeof option !== "string") problem(`auth.${key}: must be a string, got ${show(option)}.`);
511
520
  }
512
521
  function show(value) {
513
522
  if (value === void 0) return "undefined";
@@ -518,7 +527,7 @@ function show(value) {
518
527
  return typeof value;
519
528
  }
520
529
  }
521
- var CodegenConfigError, AUTH_OPTIONS, PICKLIST_MODES, IDENTIFIER, VALIDATORS, CONFIG_OPTIONS;
530
+ var CodegenConfigError, AUTH_OPTIONS, DEPRECATED_AUTH_OPTIONS, PICKLIST_MODES, IDENTIFIER, VALIDATORS, CONFIG_OPTIONS;
522
531
  var init_validate_config = __esmMin((() => {
523
532
  init_api_version();
524
533
  CodegenConfigError = class extends Error {
@@ -533,12 +542,25 @@ var init_validate_config = __esmMin((() => {
533
542
  };
534
543
  AUTH_OPTIONS = {
535
544
  clientCredentials: [
545
+ "loginUrl",
546
+ "clientId",
547
+ "clientSecret",
536
548
  "loginUrlEnv",
537
549
  "clientIdEnv",
538
550
  "clientSecretEnv"
539
551
  ],
540
- accessToken: ["accessTokenEnv", "instanceUrlEnv"],
552
+ accessToken: [
553
+ "accessToken",
554
+ "instanceUrl",
555
+ "accessTokenEnv",
556
+ "instanceUrlEnv"
557
+ ],
541
558
  jwtBearer: [
559
+ "loginUrl",
560
+ "clientId",
561
+ "username",
562
+ "privateKey",
563
+ "privateKeyPath",
542
564
  "loginUrlEnv",
543
565
  "clientIdEnv",
544
566
  "usernameEnv",
@@ -547,6 +569,16 @@ var init_validate_config = __esmMin((() => {
547
569
  ],
548
570
  sfCli: ["targetOrg"]
549
571
  };
572
+ DEPRECATED_AUTH_OPTIONS = {
573
+ loginUrlEnv: "loginUrl",
574
+ clientIdEnv: "clientId",
575
+ clientSecretEnv: "clientSecret",
576
+ accessTokenEnv: "accessToken",
577
+ instanceUrlEnv: "instanceUrl",
578
+ usernameEnv: "username",
579
+ privateKeyEnv: "privateKey",
580
+ privateKeyPathEnv: "privateKeyPath"
581
+ };
550
582
  PICKLIST_MODES = [
551
583
  "union",
552
584
  "string",
@@ -598,25 +630,6 @@ var init_validate_config = __esmMin((() => {
598
630
  CONFIG_OPTIONS = Object.keys(VALIDATORS).filter((key) => key !== "$schema");
599
631
  }));
600
632
  //#endregion
601
- //#region src/codegen/config.ts
602
- /**
603
- * Type-checks a `sobjectly.config.ts`. The listed `sobjects` become a literal union, so a typo in
604
- * a per-sObject option is a compile error:
605
- *
606
- * ```ts
607
- * export default defineConfig({
608
- * apiVersion: "v66.0",
609
- * output: "src/generated/sobjects.ts",
610
- * sobjects: ["Account", "Contact"],
611
- * excludeCreateFields: { Acount: ["Name"] }, // ❌ "Acount" is not in sobjects
612
- * });
613
- * ```
614
- */
615
- function defineConfig(config) {
616
- return config;
617
- }
618
- var init_config = __esmMin((() => {}));
619
- //#endregion
620
633
  //#region src/codegen/load-config.ts
621
634
  /** Looks for a `sobjectly.config.{ts,mts,cts,json}` file in `cwd`; the first match in lookup order wins. */
622
635
  function findConfigFile(cwd = process.cwd()) {
@@ -671,6 +684,25 @@ var init_load_config = __esmMin((() => {
671
684
  ]);
672
685
  }));
673
686
  //#endregion
687
+ //#region src/codegen/config.ts
688
+ /**
689
+ * Type-checks a `sobjectly.config.ts`. The listed `sobjects` become a literal union, so a typo in
690
+ * a per-sObject option is a compile error:
691
+ *
692
+ * ```ts
693
+ * export default defineConfig({
694
+ * apiVersion: "v66.0",
695
+ * output: "src/generated/sobjects.ts",
696
+ * sobjects: ["Account", "Contact"],
697
+ * excludeCreateFields: { Acount: ["Name"] }, // ❌ "Acount" is not in sobjects
698
+ * });
699
+ * ```
700
+ */
701
+ function defineConfig(config) {
702
+ return config;
703
+ }
704
+ var init_config = __esmMin((() => {}));
705
+ //#endregion
674
706
  //#region src/codegen/init.ts
675
707
  /**
676
708
  * Creates a `sobjectly.config` file by asking for the API version, output path, sObjects, auth
@@ -785,7 +817,6 @@ function renderJsonConfig(answers) {
785
817
  return `${JSON.stringify(config, null, " ")}\n`;
786
818
  }
787
819
  function renderTypeScriptConfig(answers) {
788
- const envVars = AUTH_ENV_VARS[answers.auth];
789
820
  const sobjects = answers.sobjects.map((name) => JSON.stringify(name)).join(", ");
790
821
  return [
791
822
  "import { defineConfig } from \"@cerios/salesforce-sobjectly/codegen\";",
@@ -797,26 +828,38 @@ function renderTypeScriptConfig(answers) {
797
828
  `\toutput: ${JSON.stringify(answers.output)},`,
798
829
  " // The sObjects to generate types for.",
799
830
  `\tsobjects: [${sobjects}],`,
800
- `\t// ${authComment(answers.auth, envVars)}`,
831
+ `\t// ${authComment(answers.auth)}`,
801
832
  `\tauth: ${renderAuth(answers)},`,
802
833
  `\tpicklists: ${JSON.stringify(answers.picklists)},`,
803
834
  "});",
804
835
  ""
805
836
  ].join("\n");
806
837
  }
838
+ /** The JSON auth setting: credentials are `"${NAME}"` placeholders, read from the environment. */
807
839
  function authSetting(answers) {
808
- return answers.auth === "sfCli" && answers.targetOrg ? {
840
+ if (answers.auth === "sfCli") return answers.targetOrg ? {
809
841
  type: "sfCli",
810
842
  targetOrg: answers.targetOrg
811
- } : { type: answers.auth };
843
+ } : { type: "sfCli" };
844
+ const fields = AUTH_FIELDS[answers.auth].map(([key, envName]) => [key, `\${${envName}}`]);
845
+ return {
846
+ type: answers.auth,
847
+ ...Object.fromEntries(fields)
848
+ };
812
849
  }
850
+ /** The TypeScript auth setting: credentials are read with `process.env`. */
813
851
  function renderAuth(answers) {
814
- const setting = authSetting(answers);
815
- const targetOrg = setting.targetOrg ? `, targetOrg: ${JSON.stringify(setting.targetOrg)}` : "";
816
- return `{ type: ${JSON.stringify(setting.type)}${targetOrg} }`;
852
+ if (answers.auth === "sfCli") return `{ type: "sfCli"${answers.targetOrg ? `, targetOrg: ${JSON.stringify(answers.targetOrg)}` : ""} }`;
853
+ const fields = AUTH_FIELDS[answers.auth].map(([key, envName]) => `\t\t${key}: process.env.${envName},`);
854
+ return [
855
+ "{",
856
+ `\t\ttype: ${JSON.stringify(answers.auth)},`,
857
+ ...fields,
858
+ " }"
859
+ ].join("\n");
817
860
  }
818
- function authComment(auth, envVars) {
819
- return auth === "sfCli" ? "Uses an org you are logged into with the Salesforce CLI (sf org login web)." : `Reads ${formatList(envVars)} from the environment.`;
861
+ function authComment(auth) {
862
+ return auth === "sfCli" ? "Uses an org you are logged into with the Salesforce CLI (sf org login web)." : "Fill these in from process.env (any variable names), a secret store or elsewhere. Keep secrets out of this file.";
820
863
  }
821
864
  async function maybeUpdateEnvExample(options, auth) {
822
865
  const path = join(options.cwd, ".env.example");
@@ -866,36 +909,43 @@ function printNextSteps(log, answers, scriptAdded, cwd) {
866
909
  "Next steps:",
867
910
  cli ? ` 1. Log in with the Salesforce CLI: sf org login web${answers.targetOrg ? ` --alias ${answers.targetOrg}` : " --set-default"}` : ` 1. Put ${formatList(AUTH_ENV_VARS[answers.auth])} in a .env file${envIgnored ? "" : " (and add .env to .gitignore)"}.`,
868
911
  ` 2. Generate the types: ${command}`,
869
- " 3. Use them:",
912
+ " 3. Use them, logging in with the config's auth:",
913
+ " import { loadAuth } from \"@cerios/salesforce-sobjectly/codegen\";",
870
914
  ` import { API_VERSION, type SObjectRegistry } from "./${answers.output.replace(/\.(ts|mts|cts)$/, "")}";`,
871
- " const sf = new SalesforceClient<SObjectRegistry>({ apiVersion: API_VERSION, auth });"
915
+ " const sf = new SalesforceClient<SObjectRegistry>({ apiVersion: API_VERSION, auth: await loadAuth() });"
872
916
  ].join("\n"));
873
917
  }
874
918
  function formatList(items) {
875
919
  if (items.length <= 1) return items.join("");
876
920
  return `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
877
921
  }
878
- var SOBJECT_NAME, NPM_SCRIPT, AUTH_ENV_VARS, AUTH_CHOICES, PICKLIST_CHOICES, FORMAT_CHOICES, JSON_SCHEMA_REFERENCE;
922
+ var SOBJECT_NAME, NPM_SCRIPT, AUTH_FIELDS, AUTH_ENV_VARS, AUTH_CHOICES, PICKLIST_CHOICES, FORMAT_CHOICES, JSON_SCHEMA_REFERENCE;
879
923
  var init_init = __esmMin((() => {
880
924
  init_api_version();
881
925
  init_load_config();
882
926
  SOBJECT_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
883
927
  NPM_SCRIPT = "sobjects:generate";
884
- AUTH_ENV_VARS = {
928
+ AUTH_FIELDS = {
885
929
  clientCredentials: [
886
- "SF_LOGIN_URL",
887
- "SF_CLIENT_ID",
888
- "SF_CLIENT_SECRET"
930
+ ["loginUrl", "SF_LOGIN_URL"],
931
+ ["clientId", "SF_CLIENT_ID"],
932
+ ["clientSecret", "SF_CLIENT_SECRET"]
889
933
  ],
890
- accessToken: ["SF_ACCESS_TOKEN", "SF_INSTANCE_URL"],
934
+ accessToken: [["accessToken", "SF_ACCESS_TOKEN"], ["instanceUrl", "SF_INSTANCE_URL"]],
891
935
  jwtBearer: [
892
- "SF_LOGIN_URL",
893
- "SF_CLIENT_ID",
894
- "SF_USERNAME",
895
- "SF_PRIVATE_KEY_PATH"
936
+ ["loginUrl", "SF_LOGIN_URL"],
937
+ ["clientId", "SF_CLIENT_ID"],
938
+ ["username", "SF_USERNAME"],
939
+ ["privateKeyPath", "SF_PRIVATE_KEY_PATH"]
896
940
  ],
897
941
  sfCli: []
898
942
  };
943
+ AUTH_ENV_VARS = {
944
+ clientCredentials: AUTH_FIELDS.clientCredentials.map(([, envName]) => envName),
945
+ accessToken: AUTH_FIELDS.accessToken.map(([, envName]) => envName),
946
+ jwtBearer: AUTH_FIELDS.jwtBearer.map(([, envName]) => envName),
947
+ sfCli: []
948
+ };
899
949
  AUTH_CHOICES = [
900
950
  {
901
951
  value: "clientCredentials",
@@ -1098,7 +1148,7 @@ async function buildSource(input, options) {
1098
1148
  const env = options.env ?? process.env;
1099
1149
  const outputPath = isAbsolute(config.output) ? config.output : resolve(options.cwd ?? process.cwd(), config.output);
1100
1150
  const client = new SalesforceClient({
1101
- auth: resolveAuth(config.auth, env),
1151
+ auth: resolveAuth(config.auth, env, { warn: (message) => logger.warn(message) }),
1102
1152
  apiVersion,
1103
1153
  transport: config.transport,
1104
1154
  retry: true
@@ -1151,39 +1201,114 @@ function normalizeSource(source) {
1151
1201
  }
1152
1202
  return result;
1153
1203
  }
1154
- /** Turns the config's auth setting into an auth provider, reading env-based credentials. */
1155
- function resolveAuth(auth, env) {
1204
+ /**
1205
+ * Turns the config's auth setting into an auth provider. Each credential comes from its key in
1206
+ * the setting (a `"${NAME}"` placeholder is read from `env`), else from the variable a deprecated
1207
+ * `*Env` key names, else from its default `SF_*` variable. Throws one error listing every
1208
+ * missing credential.
1209
+ */
1210
+ function resolveAuth(auth, env, options = {}) {
1156
1211
  const setting = auth ?? { type: "clientCredentials" };
1157
1212
  if ("getToken" in setting) return setting;
1158
- const read = (name) => {
1159
- const value = env[name];
1160
- if (!value) throw new Error(`Environment variable ${name} is not set.`);
1213
+ const problems = [];
1214
+ const lookup = (key, defaultEnv) => readCredential(setting, key, defaultEnv, env, options.warn);
1215
+ const read = (key, defaultEnv) => {
1216
+ const { value, problem } = lookup(key, defaultEnv);
1217
+ if (problem) problems.push(problem);
1161
1218
  return value;
1162
1219
  };
1163
1220
  switch (setting.type) {
1164
- case "accessToken": return accessToken({
1165
- accessToken: read(setting.accessTokenEnv ?? "SF_ACCESS_TOKEN"),
1166
- instanceUrl: read(setting.instanceUrlEnv ?? "SF_INSTANCE_URL")
1167
- });
1168
- case "jwtBearer": return jwtBearerFromEnv(setting, env, read);
1169
- case "sfCli": return sfCli({ targetOrg: setting.targetOrg });
1170
- case "clientCredentials": return clientCredentials({
1171
- loginUrl: read(setting.loginUrlEnv ?? "SF_LOGIN_URL"),
1172
- clientId: read(setting.clientIdEnv ?? "SF_CLIENT_ID"),
1173
- clientSecret: read(setting.clientSecretEnv ?? "SF_CLIENT_SECRET")
1174
- });
1221
+ case "accessToken": {
1222
+ const token = {
1223
+ accessToken: read("accessToken", "SF_ACCESS_TOKEN"),
1224
+ instanceUrl: read("instanceUrl", "SF_INSTANCE_URL")
1225
+ };
1226
+ throwIfMissing(setting.type, problems);
1227
+ return accessToken(token);
1228
+ }
1229
+ case "jwtBearer": {
1230
+ const loginUrl = read("loginUrl", "SF_LOGIN_URL");
1231
+ const clientId = read("clientId", "SF_CLIENT_ID");
1232
+ const username = read("username", "SF_USERNAME");
1233
+ const configured = PRIVATE_KEY_SOURCES.filter(([key]) => key in setting);
1234
+ const found = (configured.length > 0 ? configured : PRIVATE_KEY_SOURCES).map(([key, defaultEnv]) => ({
1235
+ key,
1236
+ ...lookup(key, defaultEnv)
1237
+ }));
1238
+ const source = found.find((item) => item.value);
1239
+ if (source === void 0) problems.push(`no private key: ${found.map((item) => item.problem).join(", and ")}`);
1240
+ throwIfMissing(setting.type, problems);
1241
+ const privateKey = source?.key === "privateKeyPath" ? readFileSync(source.value, "utf8") : source?.value ?? "";
1242
+ return jwtBearer({
1243
+ loginUrl,
1244
+ clientId,
1245
+ username,
1246
+ privateKey
1247
+ });
1248
+ }
1249
+ case "sfCli": {
1250
+ const targetOrg = "targetOrg" in setting ? read("targetOrg", "") : void 0;
1251
+ throwIfMissing(setting.type, problems);
1252
+ return sfCli({ targetOrg });
1253
+ }
1254
+ case "clientCredentials": {
1255
+ const credentials = {
1256
+ loginUrl: read("loginUrl", "SF_LOGIN_URL"),
1257
+ clientId: read("clientId", "SF_CLIENT_ID"),
1258
+ clientSecret: read("clientSecret", "SF_CLIENT_SECRET")
1259
+ };
1260
+ throwIfMissing(setting.type, problems);
1261
+ return clientCredentials(credentials);
1262
+ }
1175
1263
  default: throw new Error(`Unknown codegen auth type "${setting.type}".`);
1176
1264
  }
1177
1265
  }
1178
- function jwtBearerFromEnv(setting, env, read) {
1179
- const keyEnv = setting.privateKeyEnv ?? "SF_PRIVATE_KEY";
1180
- const privateKey = env[keyEnv] ? read(keyEnv) : readFileSync(read(setting.privateKeyPathEnv ?? "SF_PRIVATE_KEY_PATH"), "utf8");
1181
- return jwtBearer({
1182
- loginUrl: read(setting.loginUrlEnv ?? "SF_LOGIN_URL"),
1183
- clientId: read(setting.clientIdEnv ?? "SF_CLIENT_ID"),
1184
- username: read(setting.usernameEnv ?? "SF_USERNAME"),
1185
- privateKey
1186
- });
1266
+ /**
1267
+ * Loads the sobjectly config and returns an auth provider for its `auth` setting, so the client
1268
+ * logs in the same way as `sobjectly generate`:
1269
+ * `new SalesforceClient({ apiVersion: API_VERSION, auth: await loadAuth() })`.
1270
+ * Throws when no config file is found, or one error listing every missing credential.
1271
+ */
1272
+ async function loadAuth(options = {}) {
1273
+ const cwd = options.cwd ?? process.cwd();
1274
+ let configPath = options.configPath === void 0 ? void 0 : resolve(cwd, options.configPath);
1275
+ if (configPath === void 0) {
1276
+ const found = findConfigFiles(cwd);
1277
+ if (found.length > 1) options.warn?.(`found ${found.join(" and ")}; using ${found[0]}. Remove the other one.`);
1278
+ configPath = found[0];
1279
+ }
1280
+ if (configPath === void 0) throw new Error(`No sobjectly config file found in ${cwd} (looked for ${CONFIG_FILE_NAMES.join(", ")}).\nPass { configPath } to loadAuth(), run "npx sobjectly init" to create a config, or pass an auth provider such as clientCredentials() to SalesforceClient directly.`);
1281
+ const { config } = await loadConfig(configPath);
1282
+ return resolveAuth(config.auth, options.env ?? process.env, { warn: options.warn });
1283
+ }
1284
+ function readCredential(setting, key, defaultEnv, env, warn) {
1285
+ const values = setting;
1286
+ if (key in values) {
1287
+ const configured = values[key];
1288
+ const name = typeof configured === "string" ? ENV_PLACEHOLDER.exec(configured)?.[1] : void 0;
1289
+ if (name !== void 0) return fromEnv(env, name, ` (from auth.${key} "${String(configured)}")`);
1290
+ return typeof configured === "string" && configured.length > 0 ? { value: configured } : {
1291
+ value: "",
1292
+ problem: `auth.${key} is empty or undefined (if it reads process.env, that variable is not set)`
1293
+ };
1294
+ }
1295
+ const envKey = `${key}Env`;
1296
+ const legacy = values[envKey];
1297
+ if (typeof legacy === "string") {
1298
+ warn?.(`auth.${envKey} is deprecated and will be removed in 2.0. Use ${key}: process.env.${legacy} in a TypeScript config, or "${key}": "\${${legacy}}" in JSON.`);
1299
+ return fromEnv(env, legacy, "");
1300
+ }
1301
+ return fromEnv(env, defaultEnv, "");
1302
+ }
1303
+ function fromEnv(env, name, origin) {
1304
+ const value = env[name];
1305
+ return value ? { value } : {
1306
+ value: "",
1307
+ problem: `environment variable ${name}${origin} is not set`
1308
+ };
1309
+ }
1310
+ function throwIfMissing(type, problems) {
1311
+ if (problems.length > 0) throw new Error(`Missing Salesforce credentials for auth "${type}":\n${problems.map((problem) => ` - ${problem}`).join("\n")}\nFill them in under auth in the config, or set the environment variables (e.g. with --env-file .env).`);
1187
1312
  }
1188
1313
  async function resolveSObjectNames(client, config, logger) {
1189
1314
  const exclude = new Set((config.exclude ?? []).map((name) => name.toLowerCase()));
@@ -1253,24 +1378,26 @@ async function renameWithRetry(from, to) {
1253
1378
  await new Promise((resolve) => setTimeout(resolve, 50 * attempt));
1254
1379
  }
1255
1380
  }
1256
- var silentLogger;
1381
+ var silentLogger, PRIVATE_KEY_SOURCES, ENV_PLACEHOLDER;
1257
1382
  var init_codegen = __esmMin((() => {
1258
1383
  init_providers();
1259
1384
  init_sf_cli();
1260
1385
  init_client();
1261
1386
  init_generator();
1387
+ init_load_config();
1262
1388
  init_validate_config();
1263
1389
  init_config();
1264
1390
  init_type_mapper();
1265
- init_load_config();
1266
1391
  init_init();
1267
1392
  init_prompter();
1268
1393
  silentLogger = {
1269
1394
  info: () => void 0,
1270
1395
  warn: () => void 0
1271
1396
  };
1397
+ PRIVATE_KEY_SOURCES = [["privateKey", "SF_PRIVATE_KEY"], ["privateKeyPath", "SF_PRIVATE_KEY_PATH"]];
1398
+ ENV_PLACEHOLDER = /^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/;
1272
1399
  }));
1273
1400
  //#endregion
1274
- export { mapFieldType as A, init_validate_config as C, readGeneratedHashes as D, init_generator as E, FIELD_TYPE_MAP as O, PICKLIST_MODES as S, generateSource as T, defineConfig as _, init_prompter as a, CONFIG_OPTIONS as b, init_init as c, runInit as d, CONFIG_FILE_NAMES as f, loadConfig as g, init_load_config as h, resolveAuth as i, init_type_mapper as k, parseSObjects as l, findConfigFiles as m, generate as n, readlinePrompter as o, findConfigFile as p, init_codegen as r, AUTH_ENV_VARS as s, checkGenerated as t, renderConfig as u, init_config as v, validateConfig as w, CodegenConfigError as x, AUTH_OPTIONS as y };
1401
+ export { FIELD_TYPE_MAP as A, DEPRECATED_AUTH_OPTIONS as C, generateSource as D, validateConfig as E, mapFieldType as M, init_generator as O, CodegenConfigError as S, init_validate_config as T, findConfigFiles as _, resolveAuth as a, AUTH_OPTIONS as b, AUTH_ENV_VARS as c, renderConfig as d, runInit as f, findConfigFile as g, CONFIG_FILE_NAMES as h, loadAuth as i, init_type_mapper as j, readGeneratedHashes as k, init_init as l, init_config as m, generate as n, init_prompter as o, defineConfig as p, init_codegen as r, readlinePrompter as s, checkGenerated as t, parseSObjects as u, init_load_config as v, PICKLIST_MODES as w, CONFIG_OPTIONS as x, loadConfig as y };
1275
1402
 
1276
- //# sourceMappingURL=codegen-C6MEYiWo.mjs.map
1403
+ //# sourceMappingURL=codegen-0L2ebG9j.mjs.map