@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 CHANGED
@@ -9,7 +9,7 @@ A type-safe Salesforce REST API client for TypeScript. It generates types for yo
9
9
 
10
10
  ## ✨ Key Features
11
11
 
12
- - **Generated sObject types**: `sobjectly generate` reads describe metadata and writes a read type, a create input and an update input for every sObject. Required fields, restricted picklists and relationships all come from your org.
12
+ - **Generated sObject types**: `sobjectly generate` reads describe metadata and writes a read type, a create input and an update input for every sObject. Required fields, restricted picklists and relationships all come from your org. Picklists can also become named constants or enums, e.g. `CaseStatus.Working`.
13
13
  - **Typed SOQL builder**: field names are checked and autocompleted. The query result only contains the fields you selected, so `record.Phone` is a compile error unless you selected `Phone`.
14
14
  - **Relationship queries**: `selectRelated("Account", "Name")` and `selectChild("Contacts", c => c.select("Email"))` produce typed nested results.
15
15
  - **The whole REST API**: sObject CRUD, upsert by external id, query and queryAll with pagination, SOSL, Composite, Composite Graph, sObject Tree, sObject Collections, invocable actions and Flows, the Tooling API, Apex REST and Bulk API 2.0. Anything else is reachable through `request<T>()`.
@@ -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-DEVZQTR7.cjs");
3
- const require_codegen = require("./codegen-BgDgU2RR.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");
@@ -24,7 +24,7 @@ Options for init (skip the matching questions; useful in scripts):
24
24
  --sobjects <list> Comma-separated sObject API names
25
25
  --auth <type> clientCredentials | sfCli | accessToken | jwtBearer
26
26
  --target-org <alias> Salesforce CLI org alias (with --auth sfCli)
27
- --picklists <mode> union | string
27
+ --picklists <mode> union | string | const | enum
28
28
  --format <format> ts | json
29
29
  -y, --yes Use the suggested answer for every other question (needs --api-version)
30
30
  -f, --force Replace an existing config without asking
@@ -111,7 +111,7 @@ function initPreset(values) {
111
111
  "jwtBearer"
112
112
  ]);
113
113
  if (values["target-org"] !== void 0) preset.targetOrg = values["target-org"];
114
- const picklists = oneOf("--picklists", values.picklists, ["union", "string"]);
114
+ const picklists = oneOf("--picklists", values.picklists, require_codegen.PICKLIST_MODES);
115
115
  const format = oneOf("--format", values.format, ["ts", "json"]);
116
116
  return {
117
117
  ...preset,
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.cjs","names":["parseArgs","readlinePrompter","runInit","normalizeApiVersion","parseSObjects","resolve","existsSync","findConfigFiles","loadConfig","checkGenerated","generate"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/* oxlint-disable no-console */\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\n\nimport { normalizeApiVersion } from \"./api-version\";\nimport { checkGenerated, findConfigFiles, generate, loadConfig } from \"./codegen/index\";\nimport { type InitAnswers, parseSObjects, runInit } from \"./codegen/init\";\nimport { readlinePrompter } from \"./codegen/prompter\";\n\nconst HELP = `Usage: sobjectly <command> [options]\n\nCommands:\n init Create a sobjectly.config file by answering a few questions\n generate Generate TypeScript types for Salesforce sObjects (default)\n\nOptions for generate:\n -c, --config <path> Config file (default: sobjectly.config.ts or sobjectly.config.json)\n -e, --env-file <path> Load environment variables from a .env file first\n --check Don't write; exit with 1 when the generated file is out of date\n (formatting-only differences don't count)\n --stdout Print the generated source instead of writing it\n\nOptions for init (skip the matching questions; useful in scripts):\n --api-version <v> Salesforce API version, e.g. v66.0\n --output <path> Generated types file, e.g. src/generated/sobjects.ts\n --sobjects <list> Comma-separated sObject API names\n --auth <type> clientCredentials | sfCli | accessToken | jwtBearer\n --target-org <alias> Salesforce CLI org alias (with --auth sfCli)\n --picklists <mode> union | string\n --format <format> ts | json\n -y, --yes Use the suggested answer for every other question (needs --api-version)\n -f, --force Replace an existing config without asking\n\n -h, --help Show this help\n`;\n\nconst options = {\n\tconfig: { type: \"string\", short: \"c\" },\n\t\"env-file\": { type: \"string\", short: \"e\" },\n\t\"api-version\": { type: \"string\" },\n\toutput: { type: \"string\" },\n\tsobjects: { type: \"string\" },\n\tauth: { type: \"string\" },\n\tpicklists: { type: \"string\" },\n\tformat: { type: \"string\" },\n\tcheck: { type: \"boolean\" },\n\tstdout: { type: \"boolean\" },\n\t\"target-org\": { type: \"string\" },\n\tyes: { type: \"boolean\", short: \"y\" },\n\tforce: { type: \"boolean\", short: \"f\" },\n\thelp: { type: \"boolean\", short: \"h\" },\n} as const;\n\ninterface Values {\n\tconfig?: string;\n\t\"env-file\"?: string;\n\t\"api-version\"?: string;\n\toutput?: string;\n\tsobjects?: string;\n\tauth?: string;\n\tpicklists?: string;\n\tformat?: string;\n\tcheck?: boolean;\n\tstdout?: boolean;\n\t\"target-org\"?: string;\n\tyes?: boolean;\n\tforce?: boolean;\n\thelp?: boolean;\n}\n\nasync function main(argv: string[]): Promise<number> {\n\tconst { values, positionals } = parseArgs({ args: argv, allowPositionals: true, options });\n\tconst command = positionals[0] ?? \"generate\";\n\tif (values.help) {\n\t\tconsole.log(HELP);\n\t\treturn 0;\n\t}\n\tif (command === \"init\") {\n\t\treturn init(values);\n\t}\n\tif (command === \"generate\") {\n\t\treturn runGenerate(values);\n\t}\n\tconsole.error(`Unknown command \"${command}\".\\n\\n${HELP}`);\n\treturn 1;\n}\n\nasync function init(values: Values): Promise<number> {\n\tconst preset = initPreset(values);\n\tconst prompter = readlinePrompter();\n\ttry {\n\t\tawait runInit({\n\t\t\tcwd: process.cwd(),\n\t\t\tprompter,\n\t\t\tlog: (message) => console.log(message),\n\t\t\tpreset,\n\t\t\tyes: values.yes,\n\t\t\tforce: values.force,\n\t\t});\n\t\treturn 0;\n\t} finally {\n\t\tprompter.close();\n\t}\n}\n\nfunction initPreset(values: Values): Partial<InitAnswers> {\n\tconst preset: Partial<InitAnswers> = {};\n\tif (values[\"api-version\"] !== undefined) {\n\t\tconst apiVersion = normalizeApiVersion(values[\"api-version\"]);\n\t\tif (!apiVersion) {\n\t\t\tthrow new Error(`Invalid --api-version \"${values[\"api-version\"]}\". Expected a value like v66.0.`);\n\t\t}\n\t\tpreset.apiVersion = apiVersion;\n\t}\n\tif (values.output !== undefined) {\n\t\tpreset.output = values.output;\n\t}\n\tif (values.sobjects !== undefined) {\n\t\tpreset.sobjects = parseSObjects(values.sobjects);\n\t}\n\tconst auth = oneOf(\"--auth\", values.auth, [\"clientCredentials\", \"sfCli\", \"accessToken\", \"jwtBearer\"] as const);\n\tif (values[\"target-org\"] !== undefined) {\n\t\tpreset.targetOrg = values[\"target-org\"];\n\t}\n\tconst picklists = oneOf(\"--picklists\", values.picklists, [\"union\", \"string\"] as const);\n\tconst format = oneOf(\"--format\", values.format, [\"ts\", \"json\"] as const);\n\treturn { ...preset, ...(auth && { auth }), ...(picklists && { picklists }), ...(format && { format }) };\n}\n\nfunction oneOf<T extends string>(flag: string, value: string | undefined, allowed: readonly T[]): T | undefined {\n\tif (value === undefined) {\n\t\treturn undefined;\n\t}\n\tconst match = allowed.find((item) => item === value);\n\tif (!match) {\n\t\tthrow new Error(`Invalid ${flag} \"${value}\". Expected one of: ${allowed.join(\", \")}.`);\n\t}\n\treturn match;\n}\n\nasync function runGenerate(values: Values): Promise<number> {\n\tif (values[\"env-file\"]) {\n\t\tconst envFile = resolve(values[\"env-file\"]);\n\t\tif (!existsSync(envFile)) {\n\t\t\tconsole.error(`Env file not found: ${envFile}`);\n\t\t\treturn 1;\n\t\t}\n\t\tprocess.loadEnvFile(envFile);\n\t}\n\tconst found = findConfigFiles();\n\tif (!values.config && found.length > 1) {\n\t\tconsole.warn(`warning: found ${found.join(\" and \")}; using ${found[0]}. Remove the other one.`);\n\t}\n\tconst configPath = values.config ? resolve(values.config) : found[0];\n\tif (!configPath) {\n\t\tconsole.error('No sobjectly config file found. Run \"npx sobjectly init\" to create one, or pass --config.');\n\t\treturn 1;\n\t}\n\tconst { config, directory } = await loadConfig(configPath);\n\t// With --stdout the source goes to stdout, so progress goes to stderr.\n\tconst log = values.stdout\n\t\t? (message: string): void => console.error(message)\n\t\t: (message: string): void => console.log(message);\n\tconst logger = { info: log, warn: (message: string): void => console.warn(`warning: ${message}`) };\n\tif (values.check) {\n\t\treturn reportCheck(await checkGenerated(config, { cwd: directory, logger }));\n\t}\n\tconst result = await generate(config, { cwd: directory, logger, write: !values.stdout });\n\tif (values.stdout) {\n\t\tprocess.stdout.write(result.source);\n\t}\n\tif (result.skipped.length > 0) {\n\t\tconsole.warn(`Skipped ${result.skipped.length} sObject(s): ${result.skipped.map((item) => item.name).join(\", \")}`);\n\t}\n\treturn 0;\n}\n\nfunction reportCheck(result: Awaited<ReturnType<typeof checkGenerated>>): number {\n\tif (result.upToDate) {\n\t\tconsole.log(`${result.outputPath} is up to date.`);\n\t\treturn 0;\n\t}\n\tif (result.reason === \"missing\") {\n\t\tconsole.error(`${result.outputPath} does not exist. Run \"sobjectly generate\".`);\n\t\treturn 1;\n\t}\n\tconst details = [\n\t\tresult.added.length > 0 ? `added: ${result.added.join(\", \")}` : \"\",\n\t\tresult.removed.length > 0 ? `removed: ${result.removed.join(\", \")}` : \"\",\n\t\tresult.changed.length > 0 ? `changed: ${result.changed.join(\", \")}` : \"\",\n\t].filter((detail) => detail.length > 0);\n\tconsole.error(\n\t\t`${result.outputPath} is out of date${details.length > 0 ? ` (${details.join(\"; \")})` : \"\"}. Run \"sobjectly generate\".`,\n\t);\n\treturn 1;\n}\n\nmain(process.argv.slice(2))\n\t.then((code) => {\n\t\tprocess.exitCode = code;\n\t})\n\t.catch((error: unknown) => {\n\t\tconsole.error(error instanceof Error ? error.message : error);\n\t\tprocess.exitCode = 1;\n\t});\n"],"mappings":";;;;;;;AAWA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;AA2Bb,MAAM,UAAU;CACf,QAAQ;EAAE,MAAM;EAAU,OAAO;CAAI;CACrC,YAAY;EAAE,MAAM;EAAU,OAAO;CAAI;CACzC,eAAe,EAAE,MAAM,SAAS;CAChC,QAAQ,EAAE,MAAM,SAAS;CACzB,UAAU,EAAE,MAAM,SAAS;CAC3B,MAAM,EAAE,MAAM,SAAS;CACvB,WAAW,EAAE,MAAM,SAAS;CAC5B,QAAQ,EAAE,MAAM,SAAS;CACzB,OAAO,EAAE,MAAM,UAAU;CACzB,QAAQ,EAAE,MAAM,UAAU;CAC1B,cAAc,EAAE,MAAM,SAAS;CAC/B,KAAK;EAAE,MAAM;EAAW,OAAO;CAAI;CACnC,OAAO;EAAE,MAAM;EAAW,OAAO;CAAI;CACrC,MAAM;EAAE,MAAM;EAAW,OAAO;CAAI;AACrC;AAmBA,eAAe,KAAK,MAAiC;CACpD,MAAM,EAAE,QAAQ,iBAAA,GAAgBA,UAAAA,UAAAA,CAAU;EAAE,MAAM;EAAM,kBAAkB;EAAM;CAAQ,CAAC;CACzF,MAAM,UAAU,YAAY,MAAM;CAClC,IAAI,OAAO,MAAM;EAChB,QAAQ,IAAI,IAAI;EAChB,OAAO;CACR;CACA,IAAI,YAAY,QACf,OAAO,KAAK,MAAM;CAEnB,IAAI,YAAY,YACf,OAAO,YAAY,MAAM;CAE1B,QAAQ,MAAM,oBAAoB,QAAQ,QAAQ,MAAM;CACxD,OAAO;AACR;AAEA,eAAe,KAAK,QAAiC;CACpD,MAAM,SAAS,WAAW,MAAM;CAChC,MAAM,WAAWC,gBAAAA,iBAAiB;CAClC,IAAI;EACH,MAAMC,gBAAAA,QAAQ;GACb,KAAK,QAAQ,IAAI;GACjB;GACA,MAAM,YAAY,QAAQ,IAAI,OAAO;GACrC;GACA,KAAK,OAAO;GACZ,OAAO,OAAO;EACf,CAAC;EACD,OAAO;CACR,UAAU;EACT,SAAS,MAAM;CAChB;AACD;AAEA,SAAS,WAAW,QAAsC;CACzD,MAAM,SAA+B,CAAC;CACtC,IAAI,OAAO,mBAAmB,KAAA,GAAW;EACxC,MAAM,aAAaC,eAAAA,oBAAoB,OAAO,cAAc;EAC5D,IAAI,CAAC,YACJ,MAAM,IAAI,MAAM,0BAA0B,OAAO,eAAe,gCAAgC;EAEjG,OAAO,aAAa;CACrB;CACA,IAAI,OAAO,WAAW,KAAA,GACrB,OAAO,SAAS,OAAO;CAExB,IAAI,OAAO,aAAa,KAAA,GACvB,OAAO,WAAWC,gBAAAA,cAAc,OAAO,QAAQ;CAEhD,MAAM,OAAO,MAAM,UAAU,OAAO,MAAM;EAAC;EAAqB;EAAS;EAAe;CAAW,CAAU;CAC7G,IAAI,OAAO,kBAAkB,KAAA,GAC5B,OAAO,YAAY,OAAO;CAE3B,MAAM,YAAY,MAAM,eAAe,OAAO,WAAW,CAAC,SAAS,QAAQ,CAAU;CACrF,MAAM,SAAS,MAAM,YAAY,OAAO,QAAQ,CAAC,MAAM,MAAM,CAAU;CACvE,OAAO;EAAE,GAAG;EAAQ,GAAI,QAAQ,EAAE,KAAK;EAAI,GAAI,aAAa,EAAE,UAAU;EAAI,GAAI,UAAU,EAAE,OAAO;CAAG;AACvG;AAEA,SAAS,MAAwB,MAAc,OAA2B,SAAsC;CAC/G,IAAI,UAAU,KAAA,GACb;CAED,MAAM,QAAQ,QAAQ,MAAM,SAAS,SAAS,KAAK;CACnD,IAAI,CAAC,OACJ,MAAM,IAAI,MAAM,WAAW,KAAK,IAAI,MAAM,sBAAsB,QAAQ,KAAK,IAAI,EAAE,EAAE;CAEtF,OAAO;AACR;AAEA,eAAe,YAAY,QAAiC;CAC3D,IAAI,OAAO,aAAa;EACvB,MAAM,WAAA,GAAUC,UAAAA,QAAAA,CAAQ,OAAO,WAAW;EAC1C,IAAI,EAAA,GAACC,QAAAA,WAAAA,CAAW,OAAO,GAAG;GACzB,QAAQ,MAAM,uBAAuB,SAAS;GAC9C,OAAO;EACR;EACA,QAAQ,YAAY,OAAO;CAC5B;CACA,MAAM,QAAQC,gBAAAA,gBAAgB;CAC9B,IAAI,CAAC,OAAO,UAAU,MAAM,SAAS,GACpC,QAAQ,KAAK,kBAAkB,MAAM,KAAK,OAAO,EAAE,UAAU,MAAM,GAAG,wBAAwB;CAE/F,MAAM,aAAa,OAAO,UAAA,GAASF,UAAAA,QAAAA,CAAQ,OAAO,MAAM,IAAI,MAAM;CAClE,IAAI,CAAC,YAAY;EAChB,QAAQ,MAAM,6FAA2F;EACzG,OAAO;CACR;CACA,MAAM,EAAE,QAAQ,cAAc,MAAMG,gBAAAA,WAAW,UAAU;CAKzD,MAAM,SAAS;EAAE,MAHL,OAAO,UACf,YAA0B,QAAQ,MAAM,OAAO,KAC/C,YAA0B,QAAQ,IAAI,OAAO;EACrB,OAAO,YAA0B,QAAQ,KAAK,YAAY,SAAS;CAAE;CACjG,IAAI,OAAO,OACV,OAAO,YAAY,MAAMC,gBAAAA,eAAe,QAAQ;EAAE,KAAK;EAAW;CAAO,CAAC,CAAC;CAE5E,MAAM,SAAS,MAAMC,gBAAAA,SAAS,QAAQ;EAAE,KAAK;EAAW;EAAQ,OAAO,CAAC,OAAO;CAAO,CAAC;CACvF,IAAI,OAAO,QACV,QAAQ,OAAO,MAAM,OAAO,MAAM;CAEnC,IAAI,OAAO,QAAQ,SAAS,GAC3B,QAAQ,KAAK,WAAW,OAAO,QAAQ,OAAO,eAAe,OAAO,QAAQ,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG;CAElH,OAAO;AACR;AAEA,SAAS,YAAY,QAA4D;CAChF,IAAI,OAAO,UAAU;EACpB,QAAQ,IAAI,GAAG,OAAO,WAAW,gBAAgB;EACjD,OAAO;CACR;CACA,IAAI,OAAO,WAAW,WAAW;EAChC,QAAQ,MAAM,GAAG,OAAO,WAAW,2CAA2C;EAC9E,OAAO;CACR;CACA,MAAM,UAAU;EACf,OAAO,MAAM,SAAS,IAAI,UAAU,OAAO,MAAM,KAAK,IAAI,MAAM;EAChE,OAAO,QAAQ,SAAS,IAAI,YAAY,OAAO,QAAQ,KAAK,IAAI,MAAM;EACtE,OAAO,QAAQ,SAAS,IAAI,YAAY,OAAO,QAAQ,KAAK,IAAI,MAAM;CACvE,CAAC,CAAC,QAAQ,WAAW,OAAO,SAAS,CAAC;CACtC,QAAQ,MACP,GAAG,OAAO,WAAW,iBAAiB,QAAQ,SAAS,IAAI,KAAK,QAAQ,KAAK,IAAI,EAAE,KAAK,GAAG,4BAC5F;CACA,OAAO;AACR;AAEA,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,CACzB,MAAM,SAAS;CACf,QAAQ,WAAW;AACpB,CAAC,CAAC,CACD,OAAO,UAAmB;CAC1B,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;CAC5D,QAAQ,WAAW;AACpB,CAAC"}
1
+ {"version":3,"file":"cli.cjs","names":["parseArgs","readlinePrompter","runInit","normalizeApiVersion","parseSObjects","PICKLIST_MODES","resolve","existsSync","findConfigFiles","loadConfig","checkGenerated","generate"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/* oxlint-disable no-console */\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\n\nimport { normalizeApiVersion } from \"./api-version\";\nimport { checkGenerated, findConfigFiles, generate, loadConfig } from \"./codegen/index\";\nimport { type InitAnswers, parseSObjects, runInit } from \"./codegen/init\";\nimport { readlinePrompter } from \"./codegen/prompter\";\nimport { PICKLIST_MODES } from \"./codegen/validate-config\";\n\nconst HELP = `Usage: sobjectly <command> [options]\n\nCommands:\n init Create a sobjectly.config file by answering a few questions\n generate Generate TypeScript types for Salesforce sObjects (default)\n\nOptions for generate:\n -c, --config <path> Config file (default: sobjectly.config.ts or sobjectly.config.json)\n -e, --env-file <path> Load environment variables from a .env file first\n --check Don't write; exit with 1 when the generated file is out of date\n (formatting-only differences don't count)\n --stdout Print the generated source instead of writing it\n\nOptions for init (skip the matching questions; useful in scripts):\n --api-version <v> Salesforce API version, e.g. v66.0\n --output <path> Generated types file, e.g. src/generated/sobjects.ts\n --sobjects <list> Comma-separated sObject API names\n --auth <type> clientCredentials | sfCli | accessToken | jwtBearer\n --target-org <alias> Salesforce CLI org alias (with --auth sfCli)\n --picklists <mode> union | string | const | enum\n --format <format> ts | json\n -y, --yes Use the suggested answer for every other question (needs --api-version)\n -f, --force Replace an existing config without asking\n\n -h, --help Show this help\n`;\n\nconst options = {\n\tconfig: { type: \"string\", short: \"c\" },\n\t\"env-file\": { type: \"string\", short: \"e\" },\n\t\"api-version\": { type: \"string\" },\n\toutput: { type: \"string\" },\n\tsobjects: { type: \"string\" },\n\tauth: { type: \"string\" },\n\tpicklists: { type: \"string\" },\n\tformat: { type: \"string\" },\n\tcheck: { type: \"boolean\" },\n\tstdout: { type: \"boolean\" },\n\t\"target-org\": { type: \"string\" },\n\tyes: { type: \"boolean\", short: \"y\" },\n\tforce: { type: \"boolean\", short: \"f\" },\n\thelp: { type: \"boolean\", short: \"h\" },\n} as const;\n\ninterface Values {\n\tconfig?: string;\n\t\"env-file\"?: string;\n\t\"api-version\"?: string;\n\toutput?: string;\n\tsobjects?: string;\n\tauth?: string;\n\tpicklists?: string;\n\tformat?: string;\n\tcheck?: boolean;\n\tstdout?: boolean;\n\t\"target-org\"?: string;\n\tyes?: boolean;\n\tforce?: boolean;\n\thelp?: boolean;\n}\n\nasync function main(argv: string[]): Promise<number> {\n\tconst { values, positionals } = parseArgs({ args: argv, allowPositionals: true, options });\n\tconst command = positionals[0] ?? \"generate\";\n\tif (values.help) {\n\t\tconsole.log(HELP);\n\t\treturn 0;\n\t}\n\tif (command === \"init\") {\n\t\treturn init(values);\n\t}\n\tif (command === \"generate\") {\n\t\treturn runGenerate(values);\n\t}\n\tconsole.error(`Unknown command \"${command}\".\\n\\n${HELP}`);\n\treturn 1;\n}\n\nasync function init(values: Values): Promise<number> {\n\tconst preset = initPreset(values);\n\tconst prompter = readlinePrompter();\n\ttry {\n\t\tawait runInit({\n\t\t\tcwd: process.cwd(),\n\t\t\tprompter,\n\t\t\tlog: (message) => console.log(message),\n\t\t\tpreset,\n\t\t\tyes: values.yes,\n\t\t\tforce: values.force,\n\t\t});\n\t\treturn 0;\n\t} finally {\n\t\tprompter.close();\n\t}\n}\n\nfunction initPreset(values: Values): Partial<InitAnswers> {\n\tconst preset: Partial<InitAnswers> = {};\n\tif (values[\"api-version\"] !== undefined) {\n\t\tconst apiVersion = normalizeApiVersion(values[\"api-version\"]);\n\t\tif (!apiVersion) {\n\t\t\tthrow new Error(`Invalid --api-version \"${values[\"api-version\"]}\". Expected a value like v66.0.`);\n\t\t}\n\t\tpreset.apiVersion = apiVersion;\n\t}\n\tif (values.output !== undefined) {\n\t\tpreset.output = values.output;\n\t}\n\tif (values.sobjects !== undefined) {\n\t\tpreset.sobjects = parseSObjects(values.sobjects);\n\t}\n\tconst auth = oneOf(\"--auth\", values.auth, [\"clientCredentials\", \"sfCli\", \"accessToken\", \"jwtBearer\"] as const);\n\tif (values[\"target-org\"] !== undefined) {\n\t\tpreset.targetOrg = values[\"target-org\"];\n\t}\n\tconst picklists = oneOf(\"--picklists\", values.picklists, PICKLIST_MODES);\n\tconst format = oneOf(\"--format\", values.format, [\"ts\", \"json\"] as const);\n\treturn { ...preset, ...(auth && { auth }), ...(picklists && { picklists }), ...(format && { format }) };\n}\n\nfunction oneOf<T extends string>(flag: string, value: string | undefined, allowed: readonly T[]): T | undefined {\n\tif (value === undefined) {\n\t\treturn undefined;\n\t}\n\tconst match = allowed.find((item) => item === value);\n\tif (!match) {\n\t\tthrow new Error(`Invalid ${flag} \"${value}\". Expected one of: ${allowed.join(\", \")}.`);\n\t}\n\treturn match;\n}\n\nasync function runGenerate(values: Values): Promise<number> {\n\tif (values[\"env-file\"]) {\n\t\tconst envFile = resolve(values[\"env-file\"]);\n\t\tif (!existsSync(envFile)) {\n\t\t\tconsole.error(`Env file not found: ${envFile}`);\n\t\t\treturn 1;\n\t\t}\n\t\tprocess.loadEnvFile(envFile);\n\t}\n\tconst found = findConfigFiles();\n\tif (!values.config && found.length > 1) {\n\t\tconsole.warn(`warning: found ${found.join(\" and \")}; using ${found[0]}. Remove the other one.`);\n\t}\n\tconst configPath = values.config ? resolve(values.config) : found[0];\n\tif (!configPath) {\n\t\tconsole.error('No sobjectly config file found. Run \"npx sobjectly init\" to create one, or pass --config.');\n\t\treturn 1;\n\t}\n\tconst { config, directory } = await loadConfig(configPath);\n\t// With --stdout the source goes to stdout, so progress goes to stderr.\n\tconst log = values.stdout\n\t\t? (message: string): void => console.error(message)\n\t\t: (message: string): void => console.log(message);\n\tconst logger = { info: log, warn: (message: string): void => console.warn(`warning: ${message}`) };\n\tif (values.check) {\n\t\treturn reportCheck(await checkGenerated(config, { cwd: directory, logger }));\n\t}\n\tconst result = await generate(config, { cwd: directory, logger, write: !values.stdout });\n\tif (values.stdout) {\n\t\tprocess.stdout.write(result.source);\n\t}\n\tif (result.skipped.length > 0) {\n\t\tconsole.warn(`Skipped ${result.skipped.length} sObject(s): ${result.skipped.map((item) => item.name).join(\", \")}`);\n\t}\n\treturn 0;\n}\n\nfunction reportCheck(result: Awaited<ReturnType<typeof checkGenerated>>): number {\n\tif (result.upToDate) {\n\t\tconsole.log(`${result.outputPath} is up to date.`);\n\t\treturn 0;\n\t}\n\tif (result.reason === \"missing\") {\n\t\tconsole.error(`${result.outputPath} does not exist. Run \"sobjectly generate\".`);\n\t\treturn 1;\n\t}\n\tconst details = [\n\t\tresult.added.length > 0 ? `added: ${result.added.join(\", \")}` : \"\",\n\t\tresult.removed.length > 0 ? `removed: ${result.removed.join(\", \")}` : \"\",\n\t\tresult.changed.length > 0 ? `changed: ${result.changed.join(\", \")}` : \"\",\n\t].filter((detail) => detail.length > 0);\n\tconsole.error(\n\t\t`${result.outputPath} is out of date${details.length > 0 ? ` (${details.join(\"; \")})` : \"\"}. Run \"sobjectly generate\".`,\n\t);\n\treturn 1;\n}\n\nmain(process.argv.slice(2))\n\t.then((code) => {\n\t\tprocess.exitCode = code;\n\t})\n\t.catch((error: unknown) => {\n\t\tconsole.error(error instanceof Error ? error.message : error);\n\t\tprocess.exitCode = 1;\n\t});\n"],"mappings":";;;;;;;AAYA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;AA2Bb,MAAM,UAAU;CACf,QAAQ;EAAE,MAAM;EAAU,OAAO;CAAI;CACrC,YAAY;EAAE,MAAM;EAAU,OAAO;CAAI;CACzC,eAAe,EAAE,MAAM,SAAS;CAChC,QAAQ,EAAE,MAAM,SAAS;CACzB,UAAU,EAAE,MAAM,SAAS;CAC3B,MAAM,EAAE,MAAM,SAAS;CACvB,WAAW,EAAE,MAAM,SAAS;CAC5B,QAAQ,EAAE,MAAM,SAAS;CACzB,OAAO,EAAE,MAAM,UAAU;CACzB,QAAQ,EAAE,MAAM,UAAU;CAC1B,cAAc,EAAE,MAAM,SAAS;CAC/B,KAAK;EAAE,MAAM;EAAW,OAAO;CAAI;CACnC,OAAO;EAAE,MAAM;EAAW,OAAO;CAAI;CACrC,MAAM;EAAE,MAAM;EAAW,OAAO;CAAI;AACrC;AAmBA,eAAe,KAAK,MAAiC;CACpD,MAAM,EAAE,QAAQ,iBAAA,GAAgBA,UAAAA,UAAAA,CAAU;EAAE,MAAM;EAAM,kBAAkB;EAAM;CAAQ,CAAC;CACzF,MAAM,UAAU,YAAY,MAAM;CAClC,IAAI,OAAO,MAAM;EAChB,QAAQ,IAAI,IAAI;EAChB,OAAO;CACR;CACA,IAAI,YAAY,QACf,OAAO,KAAK,MAAM;CAEnB,IAAI,YAAY,YACf,OAAO,YAAY,MAAM;CAE1B,QAAQ,MAAM,oBAAoB,QAAQ,QAAQ,MAAM;CACxD,OAAO;AACR;AAEA,eAAe,KAAK,QAAiC;CACpD,MAAM,SAAS,WAAW,MAAM;CAChC,MAAM,WAAWC,gBAAAA,iBAAiB;CAClC,IAAI;EACH,MAAMC,gBAAAA,QAAQ;GACb,KAAK,QAAQ,IAAI;GACjB;GACA,MAAM,YAAY,QAAQ,IAAI,OAAO;GACrC;GACA,KAAK,OAAO;GACZ,OAAO,OAAO;EACf,CAAC;EACD,OAAO;CACR,UAAU;EACT,SAAS,MAAM;CAChB;AACD;AAEA,SAAS,WAAW,QAAsC;CACzD,MAAM,SAA+B,CAAC;CACtC,IAAI,OAAO,mBAAmB,KAAA,GAAW;EACxC,MAAM,aAAaC,eAAAA,oBAAoB,OAAO,cAAc;EAC5D,IAAI,CAAC,YACJ,MAAM,IAAI,MAAM,0BAA0B,OAAO,eAAe,gCAAgC;EAEjG,OAAO,aAAa;CACrB;CACA,IAAI,OAAO,WAAW,KAAA,GACrB,OAAO,SAAS,OAAO;CAExB,IAAI,OAAO,aAAa,KAAA,GACvB,OAAO,WAAWC,gBAAAA,cAAc,OAAO,QAAQ;CAEhD,MAAM,OAAO,MAAM,UAAU,OAAO,MAAM;EAAC;EAAqB;EAAS;EAAe;CAAW,CAAU;CAC7G,IAAI,OAAO,kBAAkB,KAAA,GAC5B,OAAO,YAAY,OAAO;CAE3B,MAAM,YAAY,MAAM,eAAe,OAAO,WAAWC,gBAAAA,cAAc;CACvE,MAAM,SAAS,MAAM,YAAY,OAAO,QAAQ,CAAC,MAAM,MAAM,CAAU;CACvE,OAAO;EAAE,GAAG;EAAQ,GAAI,QAAQ,EAAE,KAAK;EAAI,GAAI,aAAa,EAAE,UAAU;EAAI,GAAI,UAAU,EAAE,OAAO;CAAG;AACvG;AAEA,SAAS,MAAwB,MAAc,OAA2B,SAAsC;CAC/G,IAAI,UAAU,KAAA,GACb;CAED,MAAM,QAAQ,QAAQ,MAAM,SAAS,SAAS,KAAK;CACnD,IAAI,CAAC,OACJ,MAAM,IAAI,MAAM,WAAW,KAAK,IAAI,MAAM,sBAAsB,QAAQ,KAAK,IAAI,EAAE,EAAE;CAEtF,OAAO;AACR;AAEA,eAAe,YAAY,QAAiC;CAC3D,IAAI,OAAO,aAAa;EACvB,MAAM,WAAA,GAAUC,UAAAA,QAAAA,CAAQ,OAAO,WAAW;EAC1C,IAAI,EAAA,GAACC,QAAAA,WAAAA,CAAW,OAAO,GAAG;GACzB,QAAQ,MAAM,uBAAuB,SAAS;GAC9C,OAAO;EACR;EACA,QAAQ,YAAY,OAAO;CAC5B;CACA,MAAM,QAAQC,gBAAAA,gBAAgB;CAC9B,IAAI,CAAC,OAAO,UAAU,MAAM,SAAS,GACpC,QAAQ,KAAK,kBAAkB,MAAM,KAAK,OAAO,EAAE,UAAU,MAAM,GAAG,wBAAwB;CAE/F,MAAM,aAAa,OAAO,UAAA,GAASF,UAAAA,QAAAA,CAAQ,OAAO,MAAM,IAAI,MAAM;CAClE,IAAI,CAAC,YAAY;EAChB,QAAQ,MAAM,6FAA2F;EACzG,OAAO;CACR;CACA,MAAM,EAAE,QAAQ,cAAc,MAAMG,gBAAAA,WAAW,UAAU;CAKzD,MAAM,SAAS;EAAE,MAHL,OAAO,UACf,YAA0B,QAAQ,MAAM,OAAO,KAC/C,YAA0B,QAAQ,IAAI,OAAO;EACrB,OAAO,YAA0B,QAAQ,KAAK,YAAY,SAAS;CAAE;CACjG,IAAI,OAAO,OACV,OAAO,YAAY,MAAMC,gBAAAA,eAAe,QAAQ;EAAE,KAAK;EAAW;CAAO,CAAC,CAAC;CAE5E,MAAM,SAAS,MAAMC,gBAAAA,SAAS,QAAQ;EAAE,KAAK;EAAW;EAAQ,OAAO,CAAC,OAAO;CAAO,CAAC;CACvF,IAAI,OAAO,QACV,QAAQ,OAAO,MAAM,OAAO,MAAM;CAEnC,IAAI,OAAO,QAAQ,SAAS,GAC3B,QAAQ,KAAK,WAAW,OAAO,QAAQ,OAAO,eAAe,OAAO,QAAQ,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG;CAElH,OAAO;AACR;AAEA,SAAS,YAAY,QAA4D;CAChF,IAAI,OAAO,UAAU;EACpB,QAAQ,IAAI,GAAG,OAAO,WAAW,gBAAgB;EACjD,OAAO;CACR;CACA,IAAI,OAAO,WAAW,WAAW;EAChC,QAAQ,MAAM,GAAG,OAAO,WAAW,2CAA2C;EAC9E,OAAO;CACR;CACA,MAAM,UAAU;EACf,OAAO,MAAM,SAAS,IAAI,UAAU,OAAO,MAAM,KAAK,IAAI,MAAM;EAChE,OAAO,QAAQ,SAAS,IAAI,YAAY,OAAO,QAAQ,KAAK,IAAI,MAAM;EACtE,OAAO,QAAQ,SAAS,IAAI,YAAY,OAAO,QAAQ,KAAK,IAAI,MAAM;CACvE,CAAC,CAAC,QAAQ,WAAW,OAAO,SAAS,CAAC;CACtC,QAAQ,MACP,GAAG,OAAO,WAAW,iBAAiB,QAAQ,SAAS,IAAI,KAAK,QAAQ,KAAK,IAAI,EAAE,KAAK,GAAG,4BAC5F;CACA,OAAO;AACR;AAEA,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,CACzB,MAAM,SAAS;CACf,QAAQ,WAAW;AACpB,CAAC,CAAC,CACD,OAAO,UAAmB;CAC1B,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;CAC5D,QAAQ,WAAW;AACpB,CAAC"}
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-CtWtdkJ0.mjs";
3
- import { 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-CSx0WAtK.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";
@@ -10,6 +10,7 @@ var require_cli = /* @__PURE__ */ __commonJSMin((() => {
10
10
  init_codegen();
11
11
  init_init();
12
12
  init_prompter();
13
+ init_validate_config();
13
14
  const HELP = `Usage: sobjectly <command> [options]
14
15
 
15
16
  Commands:
@@ -29,7 +30,7 @@ Options for init (skip the matching questions; useful in scripts):
29
30
  --sobjects <list> Comma-separated sObject API names
30
31
  --auth <type> clientCredentials | sfCli | accessToken | jwtBearer
31
32
  --target-org <alias> Salesforce CLI org alias (with --auth sfCli)
32
- --picklists <mode> union | string
33
+ --picklists <mode> union | string | const | enum
33
34
  --format <format> ts | json
34
35
  -y, --yes Use the suggested answer for every other question (needs --api-version)
35
36
  -f, --force Replace an existing config without asking
@@ -116,7 +117,7 @@ Options for init (skip the matching questions; useful in scripts):
116
117
  "jwtBearer"
117
118
  ]);
118
119
  if (values["target-org"] !== void 0) preset.targetOrg = values["target-org"];
119
- const picklists = oneOf("--picklists", values.picklists, ["union", "string"]);
120
+ const picklists = oneOf("--picklists", values.picklists, PICKLIST_MODES);
120
121
  const format = oneOf("--format", values.format, ["ts", "json"]);
121
122
  return {
122
123
  ...preset,
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/* oxlint-disable no-console */\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\n\nimport { normalizeApiVersion } from \"./api-version\";\nimport { checkGenerated, findConfigFiles, generate, loadConfig } from \"./codegen/index\";\nimport { type InitAnswers, parseSObjects, runInit } from \"./codegen/init\";\nimport { readlinePrompter } from \"./codegen/prompter\";\n\nconst HELP = `Usage: sobjectly <command> [options]\n\nCommands:\n init Create a sobjectly.config file by answering a few questions\n generate Generate TypeScript types for Salesforce sObjects (default)\n\nOptions for generate:\n -c, --config <path> Config file (default: sobjectly.config.ts or sobjectly.config.json)\n -e, --env-file <path> Load environment variables from a .env file first\n --check Don't write; exit with 1 when the generated file is out of date\n (formatting-only differences don't count)\n --stdout Print the generated source instead of writing it\n\nOptions for init (skip the matching questions; useful in scripts):\n --api-version <v> Salesforce API version, e.g. v66.0\n --output <path> Generated types file, e.g. src/generated/sobjects.ts\n --sobjects <list> Comma-separated sObject API names\n --auth <type> clientCredentials | sfCli | accessToken | jwtBearer\n --target-org <alias> Salesforce CLI org alias (with --auth sfCli)\n --picklists <mode> union | string\n --format <format> ts | json\n -y, --yes Use the suggested answer for every other question (needs --api-version)\n -f, --force Replace an existing config without asking\n\n -h, --help Show this help\n`;\n\nconst options = {\n\tconfig: { type: \"string\", short: \"c\" },\n\t\"env-file\": { type: \"string\", short: \"e\" },\n\t\"api-version\": { type: \"string\" },\n\toutput: { type: \"string\" },\n\tsobjects: { type: \"string\" },\n\tauth: { type: \"string\" },\n\tpicklists: { type: \"string\" },\n\tformat: { type: \"string\" },\n\tcheck: { type: \"boolean\" },\n\tstdout: { type: \"boolean\" },\n\t\"target-org\": { type: \"string\" },\n\tyes: { type: \"boolean\", short: \"y\" },\n\tforce: { type: \"boolean\", short: \"f\" },\n\thelp: { type: \"boolean\", short: \"h\" },\n} as const;\n\ninterface Values {\n\tconfig?: string;\n\t\"env-file\"?: string;\n\t\"api-version\"?: string;\n\toutput?: string;\n\tsobjects?: string;\n\tauth?: string;\n\tpicklists?: string;\n\tformat?: string;\n\tcheck?: boolean;\n\tstdout?: boolean;\n\t\"target-org\"?: string;\n\tyes?: boolean;\n\tforce?: boolean;\n\thelp?: boolean;\n}\n\nasync function main(argv: string[]): Promise<number> {\n\tconst { values, positionals } = parseArgs({ args: argv, allowPositionals: true, options });\n\tconst command = positionals[0] ?? \"generate\";\n\tif (values.help) {\n\t\tconsole.log(HELP);\n\t\treturn 0;\n\t}\n\tif (command === \"init\") {\n\t\treturn init(values);\n\t}\n\tif (command === \"generate\") {\n\t\treturn runGenerate(values);\n\t}\n\tconsole.error(`Unknown command \"${command}\".\\n\\n${HELP}`);\n\treturn 1;\n}\n\nasync function init(values: Values): Promise<number> {\n\tconst preset = initPreset(values);\n\tconst prompter = readlinePrompter();\n\ttry {\n\t\tawait runInit({\n\t\t\tcwd: process.cwd(),\n\t\t\tprompter,\n\t\t\tlog: (message) => console.log(message),\n\t\t\tpreset,\n\t\t\tyes: values.yes,\n\t\t\tforce: values.force,\n\t\t});\n\t\treturn 0;\n\t} finally {\n\t\tprompter.close();\n\t}\n}\n\nfunction initPreset(values: Values): Partial<InitAnswers> {\n\tconst preset: Partial<InitAnswers> = {};\n\tif (values[\"api-version\"] !== undefined) {\n\t\tconst apiVersion = normalizeApiVersion(values[\"api-version\"]);\n\t\tif (!apiVersion) {\n\t\t\tthrow new Error(`Invalid --api-version \"${values[\"api-version\"]}\". Expected a value like v66.0.`);\n\t\t}\n\t\tpreset.apiVersion = apiVersion;\n\t}\n\tif (values.output !== undefined) {\n\t\tpreset.output = values.output;\n\t}\n\tif (values.sobjects !== undefined) {\n\t\tpreset.sobjects = parseSObjects(values.sobjects);\n\t}\n\tconst auth = oneOf(\"--auth\", values.auth, [\"clientCredentials\", \"sfCli\", \"accessToken\", \"jwtBearer\"] as const);\n\tif (values[\"target-org\"] !== undefined) {\n\t\tpreset.targetOrg = values[\"target-org\"];\n\t}\n\tconst picklists = oneOf(\"--picklists\", values.picklists, [\"union\", \"string\"] as const);\n\tconst format = oneOf(\"--format\", values.format, [\"ts\", \"json\"] as const);\n\treturn { ...preset, ...(auth && { auth }), ...(picklists && { picklists }), ...(format && { format }) };\n}\n\nfunction oneOf<T extends string>(flag: string, value: string | undefined, allowed: readonly T[]): T | undefined {\n\tif (value === undefined) {\n\t\treturn undefined;\n\t}\n\tconst match = allowed.find((item) => item === value);\n\tif (!match) {\n\t\tthrow new Error(`Invalid ${flag} \"${value}\". Expected one of: ${allowed.join(\", \")}.`);\n\t}\n\treturn match;\n}\n\nasync function runGenerate(values: Values): Promise<number> {\n\tif (values[\"env-file\"]) {\n\t\tconst envFile = resolve(values[\"env-file\"]);\n\t\tif (!existsSync(envFile)) {\n\t\t\tconsole.error(`Env file not found: ${envFile}`);\n\t\t\treturn 1;\n\t\t}\n\t\tprocess.loadEnvFile(envFile);\n\t}\n\tconst found = findConfigFiles();\n\tif (!values.config && found.length > 1) {\n\t\tconsole.warn(`warning: found ${found.join(\" and \")}; using ${found[0]}. Remove the other one.`);\n\t}\n\tconst configPath = values.config ? resolve(values.config) : found[0];\n\tif (!configPath) {\n\t\tconsole.error('No sobjectly config file found. Run \"npx sobjectly init\" to create one, or pass --config.');\n\t\treturn 1;\n\t}\n\tconst { config, directory } = await loadConfig(configPath);\n\t// With --stdout the source goes to stdout, so progress goes to stderr.\n\tconst log = values.stdout\n\t\t? (message: string): void => console.error(message)\n\t\t: (message: string): void => console.log(message);\n\tconst logger = { info: log, warn: (message: string): void => console.warn(`warning: ${message}`) };\n\tif (values.check) {\n\t\treturn reportCheck(await checkGenerated(config, { cwd: directory, logger }));\n\t}\n\tconst result = await generate(config, { cwd: directory, logger, write: !values.stdout });\n\tif (values.stdout) {\n\t\tprocess.stdout.write(result.source);\n\t}\n\tif (result.skipped.length > 0) {\n\t\tconsole.warn(`Skipped ${result.skipped.length} sObject(s): ${result.skipped.map((item) => item.name).join(\", \")}`);\n\t}\n\treturn 0;\n}\n\nfunction reportCheck(result: Awaited<ReturnType<typeof checkGenerated>>): number {\n\tif (result.upToDate) {\n\t\tconsole.log(`${result.outputPath} is up to date.`);\n\t\treturn 0;\n\t}\n\tif (result.reason === \"missing\") {\n\t\tconsole.error(`${result.outputPath} does not exist. Run \"sobjectly generate\".`);\n\t\treturn 1;\n\t}\n\tconst details = [\n\t\tresult.added.length > 0 ? `added: ${result.added.join(\", \")}` : \"\",\n\t\tresult.removed.length > 0 ? `removed: ${result.removed.join(\", \")}` : \"\",\n\t\tresult.changed.length > 0 ? `changed: ${result.changed.join(\", \")}` : \"\",\n\t].filter((detail) => detail.length > 0);\n\tconsole.error(\n\t\t`${result.outputPath} is out of date${details.length > 0 ? ` (${details.join(\"; \")})` : \"\"}. Run \"sobjectly generate\".`,\n\t);\n\treturn 1;\n}\n\nmain(process.argv.slice(2))\n\t.then((code) => {\n\t\tprocess.exitCode = code;\n\t})\n\t.catch((error: unknown) => {\n\t\tconsole.error(error instanceof Error ? error.message : error);\n\t\tprocess.exitCode = 1;\n\t});\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/* oxlint-disable no-console */\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\n\nimport { normalizeApiVersion } from \"./api-version\";\nimport { checkGenerated, findConfigFiles, generate, loadConfig } from \"./codegen/index\";\nimport { type InitAnswers, parseSObjects, runInit } from \"./codegen/init\";\nimport { readlinePrompter } from \"./codegen/prompter\";\nimport { PICKLIST_MODES } from \"./codegen/validate-config\";\n\nconst HELP = `Usage: sobjectly <command> [options]\n\nCommands:\n init Create a sobjectly.config file by answering a few questions\n generate Generate TypeScript types for Salesforce sObjects (default)\n\nOptions for generate:\n -c, --config <path> Config file (default: sobjectly.config.ts or sobjectly.config.json)\n -e, --env-file <path> Load environment variables from a .env file first\n --check Don't write; exit with 1 when the generated file is out of date\n (formatting-only differences don't count)\n --stdout Print the generated source instead of writing it\n\nOptions for init (skip the matching questions; useful in scripts):\n --api-version <v> Salesforce API version, e.g. v66.0\n --output <path> Generated types file, e.g. src/generated/sobjects.ts\n --sobjects <list> Comma-separated sObject API names\n --auth <type> clientCredentials | sfCli | accessToken | jwtBearer\n --target-org <alias> Salesforce CLI org alias (with --auth sfCli)\n --picklists <mode> union | string | const | enum\n --format <format> ts | json\n -y, --yes Use the suggested answer for every other question (needs --api-version)\n -f, --force Replace an existing config without asking\n\n -h, --help Show this help\n`;\n\nconst options = {\n\tconfig: { type: \"string\", short: \"c\" },\n\t\"env-file\": { type: \"string\", short: \"e\" },\n\t\"api-version\": { type: \"string\" },\n\toutput: { type: \"string\" },\n\tsobjects: { type: \"string\" },\n\tauth: { type: \"string\" },\n\tpicklists: { type: \"string\" },\n\tformat: { type: \"string\" },\n\tcheck: { type: \"boolean\" },\n\tstdout: { type: \"boolean\" },\n\t\"target-org\": { type: \"string\" },\n\tyes: { type: \"boolean\", short: \"y\" },\n\tforce: { type: \"boolean\", short: \"f\" },\n\thelp: { type: \"boolean\", short: \"h\" },\n} as const;\n\ninterface Values {\n\tconfig?: string;\n\t\"env-file\"?: string;\n\t\"api-version\"?: string;\n\toutput?: string;\n\tsobjects?: string;\n\tauth?: string;\n\tpicklists?: string;\n\tformat?: string;\n\tcheck?: boolean;\n\tstdout?: boolean;\n\t\"target-org\"?: string;\n\tyes?: boolean;\n\tforce?: boolean;\n\thelp?: boolean;\n}\n\nasync function main(argv: string[]): Promise<number> {\n\tconst { values, positionals } = parseArgs({ args: argv, allowPositionals: true, options });\n\tconst command = positionals[0] ?? \"generate\";\n\tif (values.help) {\n\t\tconsole.log(HELP);\n\t\treturn 0;\n\t}\n\tif (command === \"init\") {\n\t\treturn init(values);\n\t}\n\tif (command === \"generate\") {\n\t\treturn runGenerate(values);\n\t}\n\tconsole.error(`Unknown command \"${command}\".\\n\\n${HELP}`);\n\treturn 1;\n}\n\nasync function init(values: Values): Promise<number> {\n\tconst preset = initPreset(values);\n\tconst prompter = readlinePrompter();\n\ttry {\n\t\tawait runInit({\n\t\t\tcwd: process.cwd(),\n\t\t\tprompter,\n\t\t\tlog: (message) => console.log(message),\n\t\t\tpreset,\n\t\t\tyes: values.yes,\n\t\t\tforce: values.force,\n\t\t});\n\t\treturn 0;\n\t} finally {\n\t\tprompter.close();\n\t}\n}\n\nfunction initPreset(values: Values): Partial<InitAnswers> {\n\tconst preset: Partial<InitAnswers> = {};\n\tif (values[\"api-version\"] !== undefined) {\n\t\tconst apiVersion = normalizeApiVersion(values[\"api-version\"]);\n\t\tif (!apiVersion) {\n\t\t\tthrow new Error(`Invalid --api-version \"${values[\"api-version\"]}\". Expected a value like v66.0.`);\n\t\t}\n\t\tpreset.apiVersion = apiVersion;\n\t}\n\tif (values.output !== undefined) {\n\t\tpreset.output = values.output;\n\t}\n\tif (values.sobjects !== undefined) {\n\t\tpreset.sobjects = parseSObjects(values.sobjects);\n\t}\n\tconst auth = oneOf(\"--auth\", values.auth, [\"clientCredentials\", \"sfCli\", \"accessToken\", \"jwtBearer\"] as const);\n\tif (values[\"target-org\"] !== undefined) {\n\t\tpreset.targetOrg = values[\"target-org\"];\n\t}\n\tconst picklists = oneOf(\"--picklists\", values.picklists, PICKLIST_MODES);\n\tconst format = oneOf(\"--format\", values.format, [\"ts\", \"json\"] as const);\n\treturn { ...preset, ...(auth && { auth }), ...(picklists && { picklists }), ...(format && { format }) };\n}\n\nfunction oneOf<T extends string>(flag: string, value: string | undefined, allowed: readonly T[]): T | undefined {\n\tif (value === undefined) {\n\t\treturn undefined;\n\t}\n\tconst match = allowed.find((item) => item === value);\n\tif (!match) {\n\t\tthrow new Error(`Invalid ${flag} \"${value}\". Expected one of: ${allowed.join(\", \")}.`);\n\t}\n\treturn match;\n}\n\nasync function runGenerate(values: Values): Promise<number> {\n\tif (values[\"env-file\"]) {\n\t\tconst envFile = resolve(values[\"env-file\"]);\n\t\tif (!existsSync(envFile)) {\n\t\t\tconsole.error(`Env file not found: ${envFile}`);\n\t\t\treturn 1;\n\t\t}\n\t\tprocess.loadEnvFile(envFile);\n\t}\n\tconst found = findConfigFiles();\n\tif (!values.config && found.length > 1) {\n\t\tconsole.warn(`warning: found ${found.join(\" and \")}; using ${found[0]}. Remove the other one.`);\n\t}\n\tconst configPath = values.config ? resolve(values.config) : found[0];\n\tif (!configPath) {\n\t\tconsole.error('No sobjectly config file found. Run \"npx sobjectly init\" to create one, or pass --config.');\n\t\treturn 1;\n\t}\n\tconst { config, directory } = await loadConfig(configPath);\n\t// With --stdout the source goes to stdout, so progress goes to stderr.\n\tconst log = values.stdout\n\t\t? (message: string): void => console.error(message)\n\t\t: (message: string): void => console.log(message);\n\tconst logger = { info: log, warn: (message: string): void => console.warn(`warning: ${message}`) };\n\tif (values.check) {\n\t\treturn reportCheck(await checkGenerated(config, { cwd: directory, logger }));\n\t}\n\tconst result = await generate(config, { cwd: directory, logger, write: !values.stdout });\n\tif (values.stdout) {\n\t\tprocess.stdout.write(result.source);\n\t}\n\tif (result.skipped.length > 0) {\n\t\tconsole.warn(`Skipped ${result.skipped.length} sObject(s): ${result.skipped.map((item) => item.name).join(\", \")}`);\n\t}\n\treturn 0;\n}\n\nfunction reportCheck(result: Awaited<ReturnType<typeof checkGenerated>>): number {\n\tif (result.upToDate) {\n\t\tconsole.log(`${result.outputPath} is up to date.`);\n\t\treturn 0;\n\t}\n\tif (result.reason === \"missing\") {\n\t\tconsole.error(`${result.outputPath} does not exist. Run \"sobjectly generate\".`);\n\t\treturn 1;\n\t}\n\tconst details = [\n\t\tresult.added.length > 0 ? `added: ${result.added.join(\", \")}` : \"\",\n\t\tresult.removed.length > 0 ? `removed: ${result.removed.join(\", \")}` : \"\",\n\t\tresult.changed.length > 0 ? `changed: ${result.changed.join(\", \")}` : \"\",\n\t].filter((detail) => detail.length > 0);\n\tconsole.error(\n\t\t`${result.outputPath} is out of date${details.length > 0 ? ` (${details.join(\"; \")})` : \"\"}. Run \"sobjectly generate\".`,\n\t);\n\treturn 1;\n}\n\nmain(process.argv.slice(2))\n\t.then((code) => {\n\t\tprocess.exitCode = code;\n\t})\n\t.catch((error: unknown) => {\n\t\tconsole.error(error instanceof Error ? error.message : error);\n\t\tprocess.exitCode = 1;\n\t});\n"],"mappings":"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"}