@cerios/salesforce-sobjectly 1.0.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 +21 -13
- package/dist/cli.cjs +4 -4
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +5 -4
- package/dist/cli.mjs.map +1 -1
- package/dist/{codegen-CSx0WAtK.mjs → codegen-0L2ebG9j.mjs} +410 -117
- package/dist/codegen-0L2ebG9j.mjs.map +1 -0
- package/dist/{codegen-BgDgU2RR.cjs → codegen-Daud-Grz.cjs} +419 -112
- package/dist/codegen-Daud-Grz.cjs.map +1 -0
- package/dist/codegen.cjs +3 -1
- package/dist/codegen.d.cts +117 -35
- package/dist/codegen.d.mts +117 -35
- package/dist/codegen.mjs +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +15 -4
- package/dist/index.d.mts +15 -4
- package/dist/index.mjs +1 -1
- package/dist/{sf-cli-CtWtdkJ0.mjs → sf-cli-D2PgjErx.mjs} +40 -17
- package/dist/sf-cli-D2PgjErx.mjs.map +1 -0
- package/dist/{sf-cli-DEVZQTR7.cjs → sf-cli-S2BrCbik.cjs} +40 -17
- package/dist/sf-cli-S2BrCbik.cjs.map +1 -0
- package/package.json +1 -1
- package/sobjectly.config.schema.json +94 -18
- package/dist/codegen-BgDgU2RR.cjs.map +0 -1
- package/dist/codegen-CSx0WAtK.mjs.map +0 -1
- package/dist/sf-cli-CtWtdkJ0.mjs.map +0 -1
- package/dist/sf-cli-DEVZQTR7.cjs.map +0 -1
|
@@ -1,22 +1,50 @@
|
|
|
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-
|
|
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";
|
|
5
5
|
import { dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
6
|
import { createJiti } from "jiti";
|
|
7
7
|
import { createInterface } from "node:readline";
|
|
8
|
+
//#region src/codegen/emit.ts
|
|
9
|
+
/** Fields sorted by name, `Id` first, so the output is deterministic. */
|
|
10
|
+
function sortedFields(describe) {
|
|
11
|
+
return [...describe.fields].sort((a, b) => a.name === "Id" ? -1 : b.name === "Id" ? 1 : compare(a.name, b.name));
|
|
12
|
+
}
|
|
13
|
+
/** An object key: the bare name when it is an identifier, otherwise a quoted string. */
|
|
14
|
+
function propertyKey(name) {
|
|
15
|
+
return IDENTIFIER$1.test(name) ? name : JSON.stringify(name);
|
|
16
|
+
}
|
|
17
|
+
function escapeComment(value) {
|
|
18
|
+
return String(value ?? "").replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
|
|
19
|
+
}
|
|
20
|
+
function compare(a, b) {
|
|
21
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
22
|
+
}
|
|
23
|
+
var IDENTIFIER$1;
|
|
24
|
+
var init_emit = __esmMin((() => {
|
|
25
|
+
IDENTIFIER$1 = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
26
|
+
}));
|
|
27
|
+
//#endregion
|
|
8
28
|
//#region src/codegen/type-mapper.ts
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Returns the TypeScript type for a field, including `| null` for nillable fields. With picklist
|
|
31
|
+
* mode `"const"` or `"enum"`, `typeName` is the field's named picklist type; it replaces the union.
|
|
32
|
+
*/
|
|
33
|
+
function mapFieldType(field, picklists = "union", typeName) {
|
|
34
|
+
const base = picklistType(field, picklists, typeName) ?? FIELD_TYPE_MAP[field.type] ?? "unknown";
|
|
12
35
|
return field.nillable && base !== "unknown" ? `${base} | null` : base;
|
|
13
36
|
}
|
|
14
|
-
function picklistType(field, picklists) {
|
|
15
|
-
if (picklists
|
|
16
|
-
const values =
|
|
37
|
+
function picklistType(field, picklists, typeName) {
|
|
38
|
+
if (picklists === "string" || field.type !== "picklist" && field.type !== "combobox") return;
|
|
39
|
+
const values = activePicklistValues(field);
|
|
17
40
|
if (values.length === 0) return;
|
|
18
|
-
const
|
|
19
|
-
return field.restrictedPicklist && field.type === "picklist" ?
|
|
41
|
+
const members = picklists !== "union" && typeName !== void 0 ? typeName : values.map((value) => JSON.stringify(value)).join(" | ");
|
|
42
|
+
return field.restrictedPicklist && field.type === "picklist" ? members : `${members} | (string & {})`;
|
|
43
|
+
}
|
|
44
|
+
/** The distinct active values of a picklist, multi-select picklist or combobox, in describe order. */
|
|
45
|
+
function activePicklistValues(field) {
|
|
46
|
+
if (field.type !== "picklist" && field.type !== "multipicklist" && field.type !== "combobox") return [];
|
|
47
|
+
return [...new Set((field.picklistValues ?? []).filter((entry) => entry.active).map((entry) => entry.value))];
|
|
20
48
|
}
|
|
21
49
|
var ADDRESS_TYPE, GEOLOCATION_TYPE, FIELD_TYPE_MAP;
|
|
22
50
|
var init_type_mapper = __esmMin((() => {
|
|
@@ -54,24 +82,151 @@ var init_type_mapper = __esmMin((() => {
|
|
|
54
82
|
};
|
|
55
83
|
}));
|
|
56
84
|
//#endregion
|
|
85
|
+
//#region src/codegen/picklist-types.ts
|
|
86
|
+
function isNamedPicklistMode(mode) {
|
|
87
|
+
return mode === "const" || mode === "enum";
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Names the type of every picklist with active values: sObject and field in PascalCase, e.g.
|
|
91
|
+
* `Case.Status` -> `CaseStatus` and `Case.Status__c` -> `CaseStatusCustom`. A name that is in
|
|
92
|
+
* `taken` (the sObjects and other names the file defines) or already used by another picklist gets
|
|
93
|
+
* the suffix `Picklist`; when that is taken too, this throws.
|
|
94
|
+
*/
|
|
95
|
+
function picklistTypeNames(describes, taken) {
|
|
96
|
+
const used = new Map([...taken].map((name) => [name, void 0]));
|
|
97
|
+
const result = /* @__PURE__ */ new Map();
|
|
98
|
+
for (const describe of [...describes].sort((a, b) => compare(a.name, b.name))) {
|
|
99
|
+
const names = /* @__PURE__ */ new Map();
|
|
100
|
+
for (const field of sortedFields(describe).filter((item) => activePicklistValues(item).length > 0)) {
|
|
101
|
+
const base = `${pascalApiName(describe.name, "sobject")}${pascalApiName(field.name, "field")}`;
|
|
102
|
+
if (IDENTIFIER$1.test(base)) {
|
|
103
|
+
const picklist = `${describe.name}.${field.name}`;
|
|
104
|
+
const name = resolveName(base, picklist, used);
|
|
105
|
+
used.set(name, picklist);
|
|
106
|
+
names.set(field.name, name);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (names.size > 0) result.set(describe.name, names);
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
function resolveName(base, picklist, used) {
|
|
114
|
+
const name = used.has(base) ? `${base}${CLASH_SUFFIX}` : base;
|
|
115
|
+
if (used.has(name)) {
|
|
116
|
+
const owner = used.get(name);
|
|
117
|
+
const other = owner === void 0 ? "a type the generated file defines" : `the picklist type for ${owner}`;
|
|
118
|
+
throw new Error(`The picklist type "${name}" for ${picklist} clashes with ${other}; exclude one of the sObjects or use picklists: "union".`);
|
|
119
|
+
}
|
|
120
|
+
return name;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* An API name in PascalCase without underscores. A field's `__c` becomes `Custom`
|
|
124
|
+
* (`Lead_Source__c` -> `LeadSourceCustom`) and an sObject's is dropped (`My_Object__c` ->
|
|
125
|
+
* `MyObject`). Other suffixes are kept: `Foo__pc` -> `FooPc`, `Config__mdt` -> `ConfigMdt`.
|
|
126
|
+
*/
|
|
127
|
+
function pascalApiName(name, kind) {
|
|
128
|
+
const match = /^(.+?)__([a-z]+)$/.exec(name);
|
|
129
|
+
const body = match ? match[1] : name;
|
|
130
|
+
const suffix = match ? match[2] : "";
|
|
131
|
+
const suffixPart = suffix === "c" ? kind === "field" ? "Custom" : "" : capitalize(suffix);
|
|
132
|
+
return `${body.split("_").filter((part) => part.length > 0).map(capitalize).join("")}${suffixPart}`;
|
|
133
|
+
}
|
|
134
|
+
function capitalize(value) {
|
|
135
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The member names for a picklist's values, in the same order. A value that is an identifier is
|
|
139
|
+
* its own name; other values are sanitized (`"Closed Won"` -> `Closed_Won`, `"3rd Party"` ->
|
|
140
|
+
* `_3rd_Party`). When the sanitized name is empty or taken, the value itself is the (quoted) name.
|
|
141
|
+
*/
|
|
142
|
+
function picklistMemberKeys(values, mode) {
|
|
143
|
+
const used = /* @__PURE__ */ new Set();
|
|
144
|
+
const claim = (key) => {
|
|
145
|
+
used.add(key);
|
|
146
|
+
return key;
|
|
147
|
+
};
|
|
148
|
+
const usable = (key) => key.length > 0 && key !== "__proto__" && !used.has(key) && (mode === "const" || !isNumericName(key));
|
|
149
|
+
const own = values.map((value) => IDENTIFIER$1.test(value) && usable(value) ? claim(value) : void 0);
|
|
150
|
+
return values.map((value, index) => {
|
|
151
|
+
const ownKey = own[index];
|
|
152
|
+
if (ownKey !== void 0) return ownKey;
|
|
153
|
+
const sanitized = sanitizeKey(value);
|
|
154
|
+
if (usable(sanitized)) return claim(sanitized);
|
|
155
|
+
if (usable(value)) return claim(value);
|
|
156
|
+
let counter = 2;
|
|
157
|
+
while (!usable(`${sanitized || "_"}_${counter}`)) counter++;
|
|
158
|
+
return claim(`${sanitized || "_"}_${counter}`);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function sanitizeKey(value) {
|
|
162
|
+
const key = value.normalize("NFKD").replace(/\p{M}/gu, "").replace(/[^A-Za-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
|
|
163
|
+
return /^[0-9]/.test(key) ? `_${key}` : key;
|
|
164
|
+
}
|
|
165
|
+
/** Names TypeScript rejects as enum members because they are numeric, e.g. `"1"` or `"-1"`. */
|
|
166
|
+
function isNumericName(key) {
|
|
167
|
+
const number = Number(key);
|
|
168
|
+
return Number.isFinite(number) && String(number) === key;
|
|
169
|
+
}
|
|
170
|
+
/** The named type declarations for one sObject's picklists, in field order; `""` when there are none. */
|
|
171
|
+
function picklistDeclarations(describe, names, mode) {
|
|
172
|
+
if (!names) return "";
|
|
173
|
+
return sortedFields(describe).flatMap((field) => {
|
|
174
|
+
const name = names.get(field.name);
|
|
175
|
+
return name === void 0 ? [] : [declaration(describe.name, field, name, mode)];
|
|
176
|
+
}).join("\n\n");
|
|
177
|
+
}
|
|
178
|
+
function declaration(sobject, field, name, mode) {
|
|
179
|
+
const values = activePicklistValues(field);
|
|
180
|
+
const keys = picklistMemberKeys(values, mode);
|
|
181
|
+
const doc = `/** Active values of ${escapeComment(`${sobject}.${field.name}`)} (${escapeComment(field.type)}). */`;
|
|
182
|
+
if (mode === "enum") {
|
|
183
|
+
const members = values.map((value, index) => `\t${propertyKey(keys[index])} = ${JSON.stringify(value)},`);
|
|
184
|
+
return [
|
|
185
|
+
doc,
|
|
186
|
+
`export enum ${name} {`,
|
|
187
|
+
...members,
|
|
188
|
+
"}"
|
|
189
|
+
].join("\n");
|
|
190
|
+
}
|
|
191
|
+
const members = values.map((value, index) => `\t${propertyKey(keys[index])}: ${JSON.stringify(value)},`);
|
|
192
|
+
return [
|
|
193
|
+
doc,
|
|
194
|
+
`export const ${name} = {`,
|
|
195
|
+
...members,
|
|
196
|
+
"} as const;",
|
|
197
|
+
`export type ${name} = (typeof ${name})[keyof typeof ${name}];`
|
|
198
|
+
].join("\n");
|
|
199
|
+
}
|
|
200
|
+
var CLASH_SUFFIX;
|
|
201
|
+
var init_picklist_types = __esmMin((() => {
|
|
202
|
+
init_emit();
|
|
203
|
+
init_type_mapper();
|
|
204
|
+
CLASH_SUFFIX = "Picklist";
|
|
205
|
+
}));
|
|
206
|
+
//#endregion
|
|
57
207
|
//#region src/codegen/generator.ts
|
|
58
208
|
/**
|
|
59
209
|
* Generates the TypeScript source for a set of sObject describes: a read interface, create
|
|
60
|
-
* and update input types per sObject, and the `SObjectRegistry` that ties them together.
|
|
210
|
+
* and update input types per sObject, and the `SObjectRegistry` that ties them together. With
|
|
211
|
+
* picklist mode `"const"` or `"enum"`, each picklist also gets a named type before its sObject.
|
|
61
212
|
* The output is deterministic: sObjects are sorted by name and fields by name (`Id` first).
|
|
62
213
|
*/
|
|
63
214
|
function generateSource(describes, options = {}) {
|
|
64
215
|
const sorted = [...describes].sort((a, b) => compare(a.name, b.name));
|
|
65
|
-
assertGeneratableNames(sorted);
|
|
216
|
+
const definedNames = assertGeneratableNames(sorted);
|
|
66
217
|
const names = new Set(sorted.map((describe) => describe.name));
|
|
218
|
+
const picklists = options.picklists ?? "union";
|
|
219
|
+
const picklistTypes = isNamedPicklistMode(picklists) ? picklistTypeNames(sorted, definedNames) : void 0;
|
|
67
220
|
const sections = [imports(sorted, options.importSource ?? "@cerios/salesforce-sobjectly")];
|
|
68
221
|
const objectHashes = [];
|
|
69
222
|
for (const describe of sorted) {
|
|
223
|
+
const typeNames = picklistTypes?.get(describe.name);
|
|
70
224
|
const objectSections = [
|
|
71
|
-
|
|
225
|
+
isNamedPicklistMode(picklists) ? picklistDeclarations(describe, typeNames, picklists) : "",
|
|
226
|
+
readInterface(describe, picklists, typeNames),
|
|
72
227
|
inputType(describe, "CreateInput", "createable", lookup(options.excludeCreateFields, describe.name)),
|
|
73
228
|
inputType(describe, "UpdateInput", "updateable", lookup(options.excludeUpdateFields, describe.name))
|
|
74
|
-
];
|
|
229
|
+
].filter((section) => section.length > 0);
|
|
75
230
|
sections.push(...objectSections);
|
|
76
231
|
const fingerprint = [
|
|
77
232
|
...objectSections,
|
|
@@ -86,7 +241,10 @@ function generateSource(describes, options = {}) {
|
|
|
86
241
|
const body = sections.filter((section) => section.length > 0).join("\n\n");
|
|
87
242
|
return `${header(sha256(body), objectHashes)}\n\n${body}\n`;
|
|
88
243
|
}
|
|
89
|
-
/**
|
|
244
|
+
/**
|
|
245
|
+
* Fails with a clear message for sObject names the generated TypeScript can't represent. Returns
|
|
246
|
+
* every name the file defines apart from picklist types, so those can avoid them.
|
|
247
|
+
*/
|
|
90
248
|
function assertGeneratableNames(describes) {
|
|
91
249
|
const seen = /* @__PURE__ */ new Map();
|
|
92
250
|
const generated = new Set(describes.flatMap((describe) => [`${describe.name}CreateInput`, `${describe.name}UpdateInput`]));
|
|
@@ -97,6 +255,11 @@ function assertGeneratableNames(describes) {
|
|
|
97
255
|
if (previous !== void 0) throw new Error(`sObjects "${previous}" and "${name}" differ only in case; list each sObject once.`);
|
|
98
256
|
seen.set(name.toLowerCase(), name);
|
|
99
257
|
}
|
|
258
|
+
return /* @__PURE__ */ new Set([
|
|
259
|
+
...RESERVED_TYPE_NAMES,
|
|
260
|
+
...generated,
|
|
261
|
+
...describes.map((describe) => describe.name)
|
|
262
|
+
]);
|
|
100
263
|
}
|
|
101
264
|
/** Looks up a per-sObject option case-insensitively (sObject names are case-insensitive in Salesforce). */
|
|
102
265
|
function lookup(map, name) {
|
|
@@ -141,12 +304,11 @@ function imports(describes, importSource) {
|
|
|
141
304
|
if (fields.some((field) => field.type === "location")) used.push(GEOLOCATION_TYPE);
|
|
142
305
|
return used.length > 0 ? `import type { ${used.join(", ")} } from ${JSON.stringify(importSource)};` : "";
|
|
143
306
|
}
|
|
144
|
-
function
|
|
145
|
-
return [...describe.fields].sort((a, b) => a.name === "Id" ? -1 : b.name === "Id" ? 1 : compare(a.name, b.name));
|
|
146
|
-
}
|
|
147
|
-
function readInterface(describe, picklists) {
|
|
307
|
+
function readInterface(describe, picklists, typeNames) {
|
|
148
308
|
const lines = sortedFields(describe).map((field) => {
|
|
149
|
-
|
|
309
|
+
const comment = `\t/** ${escapeComment(field.label)} (${escapeComment(field.type)}) */`;
|
|
310
|
+
const type = mapFieldType(field, picklists, typeNames?.get(field.name));
|
|
311
|
+
return `${comment}\n\t${propertyKey(field.name)}: ${type};`;
|
|
150
312
|
});
|
|
151
313
|
return `${describe.label ? `/** ${escapeComment(describe.label)} */\n` : ""}export interface ${describe.name} {\n${lines.join("\n")}\n}`;
|
|
152
314
|
}
|
|
@@ -233,10 +395,6 @@ function recordTypeConstants(describes) {
|
|
|
233
395
|
const entries = describes.map((describe) => [describe.name, recordTypeNames(describe)]).filter(([, names]) => names.length > 0).map(([name, names]) => `\t${name}: [${names.map((value) => JSON.stringify(value)).join(", ")}],`);
|
|
234
396
|
return ["/** Record type DeveloperNames per sObject. Resolve ids with `sf.sobject(name).recordTypeId(developerName)`. */", `export const RECORD_TYPES = {${entries.length > 0 ? `\n${entries.join("\n")}\n` : ""}} as const;`].join("\n");
|
|
235
397
|
}
|
|
236
|
-
function activePicklistValues(field) {
|
|
237
|
-
if (field.type !== "picklist" && field.type !== "multipicklist" && field.type !== "combobox") return [];
|
|
238
|
-
return [...new Set((field.picklistValues ?? []).filter((entry) => entry.active).map((entry) => entry.value))];
|
|
239
|
-
}
|
|
240
398
|
function unionOrNever(values) {
|
|
241
399
|
return values.length > 0 ? values.map((value) => JSON.stringify(value)).join(" | ") : "never";
|
|
242
400
|
}
|
|
@@ -259,17 +417,10 @@ function relationshipMap(entries) {
|
|
|
259
417
|
function keyUnion(names) {
|
|
260
418
|
return names.map((name) => JSON.stringify(name)).join(" | ");
|
|
261
419
|
}
|
|
262
|
-
|
|
263
|
-
return IDENTIFIER$1.test(name) ? name : JSON.stringify(name);
|
|
264
|
-
}
|
|
265
|
-
function escapeComment(value) {
|
|
266
|
-
return String(value ?? "").replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ");
|
|
267
|
-
}
|
|
268
|
-
function compare(a, b) {
|
|
269
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
270
|
-
}
|
|
271
|
-
var FIELD_KINDS, IDENTIFIER$1, RESERVED_TYPE_NAMES, CONTENT_HASH_PREFIX, OBJECT_HASHES_PREFIX, OBJECT_HASH_LENGTH;
|
|
420
|
+
var FIELD_KINDS, RESERVED_TYPE_NAMES, CONTENT_HASH_PREFIX, OBJECT_HASHES_PREFIX, OBJECT_HASH_LENGTH;
|
|
272
421
|
var init_generator = __esmMin((() => {
|
|
422
|
+
init_emit();
|
|
423
|
+
init_picklist_types();
|
|
273
424
|
init_type_mapper();
|
|
274
425
|
FIELD_KINDS = /* @__PURE__ */ new Set([
|
|
275
426
|
"date",
|
|
@@ -277,7 +428,6 @@ var init_generator = __esmMin((() => {
|
|
|
277
428
|
"time",
|
|
278
429
|
"multipicklist"
|
|
279
430
|
]);
|
|
280
|
-
IDENTIFIER$1 = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
281
431
|
RESERVED_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
282
432
|
"Record",
|
|
283
433
|
"Pick",
|
|
@@ -356,8 +506,17 @@ function validateAuth(value, { json, problem }) {
|
|
|
356
506
|
problem(`auth.type: must be one of ${Object.keys(AUTH_OPTIONS).join(", ")}, got ${show(type)}.`);
|
|
357
507
|
return;
|
|
358
508
|
}
|
|
359
|
-
for (const [key, option] of Object.entries(rest)) if (!allowed.includes(key))
|
|
360
|
-
|
|
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)}.`);
|
|
361
520
|
}
|
|
362
521
|
function show(value) {
|
|
363
522
|
if (value === void 0) return "undefined";
|
|
@@ -368,7 +527,7 @@ function show(value) {
|
|
|
368
527
|
return typeof value;
|
|
369
528
|
}
|
|
370
529
|
}
|
|
371
|
-
var CodegenConfigError, AUTH_OPTIONS, PICKLIST_MODES, IDENTIFIER, VALIDATORS, CONFIG_OPTIONS;
|
|
530
|
+
var CodegenConfigError, AUTH_OPTIONS, DEPRECATED_AUTH_OPTIONS, PICKLIST_MODES, IDENTIFIER, VALIDATORS, CONFIG_OPTIONS;
|
|
372
531
|
var init_validate_config = __esmMin((() => {
|
|
373
532
|
init_api_version();
|
|
374
533
|
CodegenConfigError = class extends Error {
|
|
@@ -383,12 +542,25 @@ var init_validate_config = __esmMin((() => {
|
|
|
383
542
|
};
|
|
384
543
|
AUTH_OPTIONS = {
|
|
385
544
|
clientCredentials: [
|
|
545
|
+
"loginUrl",
|
|
546
|
+
"clientId",
|
|
547
|
+
"clientSecret",
|
|
386
548
|
"loginUrlEnv",
|
|
387
549
|
"clientIdEnv",
|
|
388
550
|
"clientSecretEnv"
|
|
389
551
|
],
|
|
390
|
-
accessToken: [
|
|
552
|
+
accessToken: [
|
|
553
|
+
"accessToken",
|
|
554
|
+
"instanceUrl",
|
|
555
|
+
"accessTokenEnv",
|
|
556
|
+
"instanceUrlEnv"
|
|
557
|
+
],
|
|
391
558
|
jwtBearer: [
|
|
559
|
+
"loginUrl",
|
|
560
|
+
"clientId",
|
|
561
|
+
"username",
|
|
562
|
+
"privateKey",
|
|
563
|
+
"privateKeyPath",
|
|
392
564
|
"loginUrlEnv",
|
|
393
565
|
"clientIdEnv",
|
|
394
566
|
"usernameEnv",
|
|
@@ -397,7 +569,22 @@ var init_validate_config = __esmMin((() => {
|
|
|
397
569
|
],
|
|
398
570
|
sfCli: ["targetOrg"]
|
|
399
571
|
};
|
|
400
|
-
|
|
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
|
+
};
|
|
582
|
+
PICKLIST_MODES = [
|
|
583
|
+
"union",
|
|
584
|
+
"string",
|
|
585
|
+
"const",
|
|
586
|
+
"enum"
|
|
587
|
+
];
|
|
401
588
|
IDENTIFIER = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
402
589
|
VALIDATORS = {
|
|
403
590
|
$schema: (value, { problem }) => {
|
|
@@ -417,7 +604,7 @@ var init_validate_config = __esmMin((() => {
|
|
|
417
604
|
excludeCreateFields: (value, context) => validateFieldMap("excludeCreateFields", value, context),
|
|
418
605
|
excludeUpdateFields: (value, context) => validateFieldMap("excludeUpdateFields", value, context),
|
|
419
606
|
picklists: (value, { problem }) => {
|
|
420
|
-
if (!PICKLIST_MODES.includes(value)) problem(`picklists: must be
|
|
607
|
+
if (!PICKLIST_MODES.includes(value)) problem(`picklists: must be one of ${PICKLIST_MODES.join(", ")}, got ${show(value)}.`);
|
|
421
608
|
},
|
|
422
609
|
constants: (value, { problem }) => {
|
|
423
610
|
if (typeof value !== "boolean") problem(`constants: must be true or false, got ${show(value)}.`);
|
|
@@ -443,25 +630,6 @@ var init_validate_config = __esmMin((() => {
|
|
|
443
630
|
CONFIG_OPTIONS = Object.keys(VALIDATORS).filter((key) => key !== "$schema");
|
|
444
631
|
}));
|
|
445
632
|
//#endregion
|
|
446
|
-
//#region src/codegen/config.ts
|
|
447
|
-
/**
|
|
448
|
-
* Type-checks a `sobjectly.config.ts`. The listed `sobjects` become a literal union, so a typo in
|
|
449
|
-
* a per-sObject option is a compile error:
|
|
450
|
-
*
|
|
451
|
-
* ```ts
|
|
452
|
-
* export default defineConfig({
|
|
453
|
-
* apiVersion: "v66.0",
|
|
454
|
-
* output: "src/generated/sobjects.ts",
|
|
455
|
-
* sobjects: ["Account", "Contact"],
|
|
456
|
-
* excludeCreateFields: { Acount: ["Name"] }, // ❌ "Acount" is not in sobjects
|
|
457
|
-
* });
|
|
458
|
-
* ```
|
|
459
|
-
*/
|
|
460
|
-
function defineConfig(config) {
|
|
461
|
-
return config;
|
|
462
|
-
}
|
|
463
|
-
var init_config = __esmMin((() => {}));
|
|
464
|
-
//#endregion
|
|
465
633
|
//#region src/codegen/load-config.ts
|
|
466
634
|
/** Looks for a `sobjectly.config.{ts,mts,cts,json}` file in `cwd`; the first match in lookup order wins. */
|
|
467
635
|
function findConfigFile(cwd = process.cwd()) {
|
|
@@ -516,6 +684,25 @@ var init_load_config = __esmMin((() => {
|
|
|
516
684
|
]);
|
|
517
685
|
}));
|
|
518
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
|
|
519
706
|
//#region src/codegen/init.ts
|
|
520
707
|
/**
|
|
521
708
|
* Creates a `sobjectly.config` file by asking for the API version, output path, sObjects, auth
|
|
@@ -630,7 +817,6 @@ function renderJsonConfig(answers) {
|
|
|
630
817
|
return `${JSON.stringify(config, null, " ")}\n`;
|
|
631
818
|
}
|
|
632
819
|
function renderTypeScriptConfig(answers) {
|
|
633
|
-
const envVars = AUTH_ENV_VARS[answers.auth];
|
|
634
820
|
const sobjects = answers.sobjects.map((name) => JSON.stringify(name)).join(", ");
|
|
635
821
|
return [
|
|
636
822
|
"import { defineConfig } from \"@cerios/salesforce-sobjectly/codegen\";",
|
|
@@ -642,26 +828,38 @@ function renderTypeScriptConfig(answers) {
|
|
|
642
828
|
`\toutput: ${JSON.stringify(answers.output)},`,
|
|
643
829
|
" // The sObjects to generate types for.",
|
|
644
830
|
`\tsobjects: [${sobjects}],`,
|
|
645
|
-
`\t// ${authComment(answers.auth
|
|
831
|
+
`\t// ${authComment(answers.auth)}`,
|
|
646
832
|
`\tauth: ${renderAuth(answers)},`,
|
|
647
833
|
`\tpicklists: ${JSON.stringify(answers.picklists)},`,
|
|
648
834
|
"});",
|
|
649
835
|
""
|
|
650
836
|
].join("\n");
|
|
651
837
|
}
|
|
838
|
+
/** The JSON auth setting: credentials are `"${NAME}"` placeholders, read from the environment. */
|
|
652
839
|
function authSetting(answers) {
|
|
653
|
-
|
|
840
|
+
if (answers.auth === "sfCli") return answers.targetOrg ? {
|
|
654
841
|
type: "sfCli",
|
|
655
842
|
targetOrg: answers.targetOrg
|
|
656
|
-
} : { type:
|
|
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
|
+
};
|
|
657
849
|
}
|
|
850
|
+
/** The TypeScript auth setting: credentials are read with `process.env`. */
|
|
658
851
|
function renderAuth(answers) {
|
|
659
|
-
|
|
660
|
-
const
|
|
661
|
-
return
|
|
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");
|
|
662
860
|
}
|
|
663
|
-
function authComment(auth
|
|
664
|
-
return auth === "sfCli" ? "Uses an org you are logged into with the Salesforce CLI (sf org login web)." :
|
|
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.";
|
|
665
863
|
}
|
|
666
864
|
async function maybeUpdateEnvExample(options, auth) {
|
|
667
865
|
const path = join(options.cwd, ".env.example");
|
|
@@ -711,36 +909,43 @@ function printNextSteps(log, answers, scriptAdded, cwd) {
|
|
|
711
909
|
"Next steps:",
|
|
712
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)"}.`,
|
|
713
911
|
` 2. Generate the types: ${command}`,
|
|
714
|
-
" 3. Use them:",
|
|
912
|
+
" 3. Use them, logging in with the config's auth:",
|
|
913
|
+
" import { loadAuth } from \"@cerios/salesforce-sobjectly/codegen\";",
|
|
715
914
|
` import { API_VERSION, type SObjectRegistry } from "./${answers.output.replace(/\.(ts|mts|cts)$/, "")}";`,
|
|
716
|
-
" const sf = new SalesforceClient<SObjectRegistry>({ apiVersion: API_VERSION, auth });"
|
|
915
|
+
" const sf = new SalesforceClient<SObjectRegistry>({ apiVersion: API_VERSION, auth: await loadAuth() });"
|
|
717
916
|
].join("\n"));
|
|
718
917
|
}
|
|
719
918
|
function formatList(items) {
|
|
720
919
|
if (items.length <= 1) return items.join("");
|
|
721
920
|
return `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
|
|
722
921
|
}
|
|
723
|
-
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;
|
|
724
923
|
var init_init = __esmMin((() => {
|
|
725
924
|
init_api_version();
|
|
726
925
|
init_load_config();
|
|
727
926
|
SOBJECT_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
728
927
|
NPM_SCRIPT = "sobjects:generate";
|
|
729
|
-
|
|
928
|
+
AUTH_FIELDS = {
|
|
730
929
|
clientCredentials: [
|
|
731
|
-
"SF_LOGIN_URL",
|
|
732
|
-
"SF_CLIENT_ID",
|
|
733
|
-
"SF_CLIENT_SECRET"
|
|
930
|
+
["loginUrl", "SF_LOGIN_URL"],
|
|
931
|
+
["clientId", "SF_CLIENT_ID"],
|
|
932
|
+
["clientSecret", "SF_CLIENT_SECRET"]
|
|
734
933
|
],
|
|
735
|
-
accessToken: ["SF_ACCESS_TOKEN", "SF_INSTANCE_URL"],
|
|
934
|
+
accessToken: [["accessToken", "SF_ACCESS_TOKEN"], ["instanceUrl", "SF_INSTANCE_URL"]],
|
|
736
935
|
jwtBearer: [
|
|
737
|
-
"SF_LOGIN_URL",
|
|
738
|
-
"SF_CLIENT_ID",
|
|
739
|
-
"SF_USERNAME",
|
|
740
|
-
"SF_PRIVATE_KEY_PATH"
|
|
936
|
+
["loginUrl", "SF_LOGIN_URL"],
|
|
937
|
+
["clientId", "SF_CLIENT_ID"],
|
|
938
|
+
["username", "SF_USERNAME"],
|
|
939
|
+
["privateKeyPath", "SF_PRIVATE_KEY_PATH"]
|
|
741
940
|
],
|
|
742
941
|
sfCli: []
|
|
743
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
|
+
};
|
|
744
949
|
AUTH_CHOICES = [
|
|
745
950
|
{
|
|
746
951
|
value: "clientCredentials",
|
|
@@ -759,13 +964,24 @@ var init_init = __esmMin((() => {
|
|
|
759
964
|
label: "JWT bearer (certificate-based, runs as a user)"
|
|
760
965
|
}
|
|
761
966
|
];
|
|
762
|
-
PICKLIST_CHOICES = [
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
967
|
+
PICKLIST_CHOICES = [
|
|
968
|
+
{
|
|
969
|
+
value: "union",
|
|
970
|
+
label: "Union of values, e.g. \"New\" | \"Closed\" (type-safe)"
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
value: "string",
|
|
974
|
+
label: "Plain string"
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
value: "const",
|
|
978
|
+
label: "Union plus a named constant per picklist, e.g. CaseStatus.Closed"
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
value: "enum",
|
|
982
|
+
label: "TypeScript enum per picklist (restricted picklists only accept enum members)"
|
|
983
|
+
}
|
|
984
|
+
];
|
|
769
985
|
FORMAT_CHOICES = [{
|
|
770
986
|
value: "ts",
|
|
771
987
|
label: "TypeScript (sobjectly.config.ts, type-checked with defineConfig)"
|
|
@@ -932,7 +1148,7 @@ async function buildSource(input, options) {
|
|
|
932
1148
|
const env = options.env ?? process.env;
|
|
933
1149
|
const outputPath = isAbsolute(config.output) ? config.output : resolve(options.cwd ?? process.cwd(), config.output);
|
|
934
1150
|
const client = new SalesforceClient({
|
|
935
|
-
auth: resolveAuth(config.auth, env),
|
|
1151
|
+
auth: resolveAuth(config.auth, env, { warn: (message) => logger.warn(message) }),
|
|
936
1152
|
apiVersion,
|
|
937
1153
|
transport: config.transport,
|
|
938
1154
|
retry: true
|
|
@@ -985,39 +1201,114 @@ function normalizeSource(source) {
|
|
|
985
1201
|
}
|
|
986
1202
|
return result;
|
|
987
1203
|
}
|
|
988
|
-
/**
|
|
989
|
-
|
|
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 = {}) {
|
|
990
1211
|
const setting = auth ?? { type: "clientCredentials" };
|
|
991
1212
|
if ("getToken" in setting) return setting;
|
|
992
|
-
const
|
|
993
|
-
|
|
994
|
-
|
|
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);
|
|
995
1218
|
return value;
|
|
996
1219
|
};
|
|
997
1220
|
switch (setting.type) {
|
|
998
|
-
case "accessToken":
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
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
|
+
}
|
|
1009
1263
|
default: throw new Error(`Unknown codegen auth type "${setting.type}".`);
|
|
1010
1264
|
}
|
|
1011
1265
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
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).`);
|
|
1021
1312
|
}
|
|
1022
1313
|
async function resolveSObjectNames(client, config, logger) {
|
|
1023
1314
|
const exclude = new Set((config.exclude ?? []).map((name) => name.toLowerCase()));
|
|
@@ -1087,24 +1378,26 @@ async function renameWithRetry(from, to) {
|
|
|
1087
1378
|
await new Promise((resolve) => setTimeout(resolve, 50 * attempt));
|
|
1088
1379
|
}
|
|
1089
1380
|
}
|
|
1090
|
-
var silentLogger;
|
|
1381
|
+
var silentLogger, PRIVATE_KEY_SOURCES, ENV_PLACEHOLDER;
|
|
1091
1382
|
var init_codegen = __esmMin((() => {
|
|
1092
1383
|
init_providers();
|
|
1093
1384
|
init_sf_cli();
|
|
1094
1385
|
init_client();
|
|
1095
1386
|
init_generator();
|
|
1387
|
+
init_load_config();
|
|
1096
1388
|
init_validate_config();
|
|
1097
1389
|
init_config();
|
|
1098
1390
|
init_type_mapper();
|
|
1099
|
-
init_load_config();
|
|
1100
1391
|
init_init();
|
|
1101
1392
|
init_prompter();
|
|
1102
1393
|
silentLogger = {
|
|
1103
1394
|
info: () => void 0,
|
|
1104
1395
|
warn: () => void 0
|
|
1105
1396
|
};
|
|
1397
|
+
PRIVATE_KEY_SOURCES = [["privateKey", "SF_PRIVATE_KEY"], ["privateKeyPath", "SF_PRIVATE_KEY_PATH"]];
|
|
1398
|
+
ENV_PLACEHOLDER = /^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/;
|
|
1106
1399
|
}));
|
|
1107
1400
|
//#endregion
|
|
1108
|
-
export {
|
|
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 };
|
|
1109
1402
|
|
|
1110
|
-
//# sourceMappingURL=codegen-
|
|
1403
|
+
//# sourceMappingURL=codegen-0L2ebG9j.mjs.map
|