@tenderprompt/cli 0.1.34 → 0.1.35
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/dist/index.js +95 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32,6 +32,8 @@ function readCliPackageVersion() {
|
|
|
32
32
|
}
|
|
33
33
|
const CLI_PACKAGE_VERSION = readCliPackageVersion();
|
|
34
34
|
const GIT_COMMIT_SHA_PATTERN = /^[0-9a-f]{40}$/i;
|
|
35
|
+
const SHOPIFY_CLI_PACKAGE = '@shopify/cli@latest';
|
|
36
|
+
const SHOPIFY_CLI_BIN = 'shopify';
|
|
35
37
|
const ANALYTICS_AUTHORING_PLAYBOOK_ID = 'analytics-event-authoring';
|
|
36
38
|
const ANALYTICS_AUTHORING_COMMAND = 'tender app analytics authoring --json';
|
|
37
39
|
const ANALYTICS_AUTHORING_PLAYBOOK_COMMAND = `tender playbooks get ${ANALYTICS_AUTHORING_PLAYBOOK_ID} --json`;
|
|
@@ -145,6 +147,23 @@ class TenderCliConnectorsApiError extends Error {
|
|
|
145
147
|
this.example = example;
|
|
146
148
|
}
|
|
147
149
|
}
|
|
150
|
+
class TenderCliChildProcessError extends Error {
|
|
151
|
+
command;
|
|
152
|
+
args;
|
|
153
|
+
exitCode;
|
|
154
|
+
stdout;
|
|
155
|
+
stderr;
|
|
156
|
+
constructor(input) {
|
|
157
|
+
const detail = input.stderr.trim() || input.stdout.trim();
|
|
158
|
+
super([`${input.command} ${input.args.join(' ')} failed with exit code ${input.exitCode}.`, detail].filter(Boolean).join('\n'));
|
|
159
|
+
this.name = 'TenderCliChildProcessError';
|
|
160
|
+
this.command = input.command;
|
|
161
|
+
this.args = input.args;
|
|
162
|
+
this.exitCode = input.exitCode;
|
|
163
|
+
this.stdout = input.stdout;
|
|
164
|
+
this.stderr = input.stderr;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
148
167
|
const DEFAULT_PROFILE_NAME = 'default';
|
|
149
168
|
const DEFAULT_BASE_URL = 'https://app.tenderprompt.com';
|
|
150
169
|
const ARTIFACT_SOURCE_EXPORT_MAX_FILES = 1000;
|
|
@@ -592,7 +611,7 @@ function connectorsShopifySourceValidateHelp() {
|
|
|
592
611
|
return `Usage: tender connectors shopify source validate <connector-id> [--dir <path>] [--client-id <shopify-client-id>] [--execute] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
593
612
|
|
|
594
613
|
Without --execute, prints the exact Shopify CLI validation command. With
|
|
595
|
-
--execute, runs
|
|
614
|
+
the --execute flag, runs npm exec --yes --package @shopify/cli@latest -- shopify app config validate with npm lifecycle environment variables scrubbed.
|
|
596
615
|
|
|
597
616
|
Examples:
|
|
598
617
|
tender connectors shopify source validate conn_123 --dir ./shopify-app --execute --json`;
|
|
@@ -601,7 +620,7 @@ function connectorsShopifySourceDeployHelp() {
|
|
|
601
620
|
return `Usage: tender connectors shopify source deploy <connector-id> [--dir <path>] [--client-id <shopify-client-id>] [--version <tag>] [--message <text>] [--source-control-url <url>] [--allow-deletes] [--confirm deploy] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
602
621
|
|
|
603
622
|
Without --confirm deploy, prints the exact Shopify CLI deployment command. With
|
|
604
|
-
--confirm deploy, runs
|
|
623
|
+
the --confirm deploy flag, runs npm exec --yes --package @shopify/cli@latest -- shopify app deploy with npm lifecycle environment variables scrubbed. If
|
|
605
624
|
SHOPIFY_APP_AUTOMATION_TOKEN is not set locally, the CLI requests the
|
|
606
625
|
connector's stored App Automation Token and injects it only into the spawned
|
|
607
626
|
Shopify CLI child process.
|
|
@@ -12220,7 +12239,7 @@ spawned Shopify CLI child process.
|
|
|
12220
12239
|
## Validate
|
|
12221
12240
|
|
|
12222
12241
|
\`\`\`sh
|
|
12223
|
-
|
|
12242
|
+
npm exec --yes --package @shopify/cli@latest -- shopify app config validate --path . --json
|
|
12224
12243
|
\`\`\`
|
|
12225
12244
|
|
|
12226
12245
|
## Deploy
|
|
@@ -12482,8 +12501,6 @@ async function commitAndPushSourceFiles(input) {
|
|
|
12482
12501
|
}
|
|
12483
12502
|
function shopifyValidateArgs(input) {
|
|
12484
12503
|
return [
|
|
12485
|
-
'--yes',
|
|
12486
|
-
'@shopify/cli@latest',
|
|
12487
12504
|
'app',
|
|
12488
12505
|
'config',
|
|
12489
12506
|
'validate',
|
|
@@ -12495,8 +12512,6 @@ function shopifyValidateArgs(input) {
|
|
|
12495
12512
|
}
|
|
12496
12513
|
function shopifyDeployArgs(input) {
|
|
12497
12514
|
return [
|
|
12498
|
-
'--yes',
|
|
12499
|
-
'@shopify/cli@latest',
|
|
12500
12515
|
'app',
|
|
12501
12516
|
'deploy',
|
|
12502
12517
|
'--path',
|
|
@@ -12508,9 +12523,50 @@ function shopifyDeployArgs(input) {
|
|
|
12508
12523
|
...(input.sourceControlUrl ? ['--source-control-url', input.sourceControlUrl] : []),
|
|
12509
12524
|
];
|
|
12510
12525
|
}
|
|
12526
|
+
function shopifyCliCommand(args) {
|
|
12527
|
+
return {
|
|
12528
|
+
command: 'npm',
|
|
12529
|
+
args: ['exec', '--yes', '--package', SHOPIFY_CLI_PACKAGE, '--', SHOPIFY_CLI_BIN, ...args],
|
|
12530
|
+
};
|
|
12531
|
+
}
|
|
12532
|
+
function shopifyCliCommandLine(args) {
|
|
12533
|
+
const invocation = shopifyCliCommand(args);
|
|
12534
|
+
return commandLine(invocation.command, invocation.args);
|
|
12535
|
+
}
|
|
12511
12536
|
function commandLine(command, args) {
|
|
12512
12537
|
return [command, ...args.map(shellQuote)].join(' ');
|
|
12513
12538
|
}
|
|
12539
|
+
function shouldDropNestedNpmEnv(key) {
|
|
12540
|
+
const normalized = key.toLowerCase();
|
|
12541
|
+
return (normalized === 'init_cwd' ||
|
|
12542
|
+
normalized === 'npm_command' ||
|
|
12543
|
+
normalized === 'npm_config_argv' ||
|
|
12544
|
+
normalized === 'npm_config_call' ||
|
|
12545
|
+
normalized === 'npm_config_package' ||
|
|
12546
|
+
normalized === 'npm_execpath' ||
|
|
12547
|
+
normalized === 'npm_node_execpath' ||
|
|
12548
|
+
normalized.startsWith('npm_lifecycle_') ||
|
|
12549
|
+
normalized.startsWith('npm_package_'));
|
|
12550
|
+
}
|
|
12551
|
+
function sanitizeNestedNpmEnvironment(env) {
|
|
12552
|
+
const sanitized = {};
|
|
12553
|
+
for (const [key, value] of Object.entries(env)) {
|
|
12554
|
+
if (shouldDropNestedNpmEnv(key)) {
|
|
12555
|
+
continue;
|
|
12556
|
+
}
|
|
12557
|
+
sanitized[key] = value;
|
|
12558
|
+
}
|
|
12559
|
+
return sanitized;
|
|
12560
|
+
}
|
|
12561
|
+
function shopifyCliChildEnv(runtime, overrides = {}) {
|
|
12562
|
+
return {
|
|
12563
|
+
...sanitizeNestedNpmEnvironment({
|
|
12564
|
+
...process.env,
|
|
12565
|
+
...(runtime.env ?? {}),
|
|
12566
|
+
}),
|
|
12567
|
+
...overrides,
|
|
12568
|
+
};
|
|
12569
|
+
}
|
|
12514
12570
|
function redactSensitiveText(value, secrets = []) {
|
|
12515
12571
|
let redacted = value;
|
|
12516
12572
|
for (const secret of secrets) {
|
|
@@ -12524,11 +12580,12 @@ function redactSensitiveText(value, secrets = []) {
|
|
|
12524
12580
|
.replace(/\b(authorization\s*[:=]\s*(?:Bearer\s+)?)([^\s'"]+)/gi, '$1[REDACTED]')
|
|
12525
12581
|
.replace(/\b(x-shopify-access-token\s*[:=]\s*)([^\s'"]+)/gi, '$1[REDACTED]');
|
|
12526
12582
|
}
|
|
12527
|
-
async function
|
|
12583
|
+
async function runShopifyCliCommand(input) {
|
|
12528
12584
|
const runner = input.runtime.commandRunner ?? defaultCommandRunner;
|
|
12529
|
-
const
|
|
12585
|
+
const invocation = shopifyCliCommand(input.args);
|
|
12586
|
+
const result = await runner(invocation.command, invocation.args, {
|
|
12530
12587
|
cwd: input.cwd,
|
|
12531
|
-
|
|
12588
|
+
env: shopifyCliChildEnv(input.runtime, input.env),
|
|
12532
12589
|
});
|
|
12533
12590
|
const redactedResult = {
|
|
12534
12591
|
...result,
|
|
@@ -12536,12 +12593,13 @@ async function runNpxCommand(input) {
|
|
|
12536
12593
|
stderr: redactSensitiveText(result.stderr, input.redactions),
|
|
12537
12594
|
};
|
|
12538
12595
|
if (redactedResult.exitCode !== 0) {
|
|
12539
|
-
throw new
|
|
12540
|
-
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
.
|
|
12544
|
-
.
|
|
12596
|
+
throw new TenderCliChildProcessError({
|
|
12597
|
+
command: invocation.command,
|
|
12598
|
+
args: invocation.args,
|
|
12599
|
+
exitCode: redactedResult.exitCode,
|
|
12600
|
+
stdout: redactedResult.stdout,
|
|
12601
|
+
stderr: redactedResult.stderr,
|
|
12602
|
+
});
|
|
12545
12603
|
}
|
|
12546
12604
|
return redactedResult;
|
|
12547
12605
|
}
|
|
@@ -12570,10 +12628,8 @@ function localShopifyDeployToken(runtime) {
|
|
|
12570
12628
|
const token = env.SHOPIFY_APP_AUTOMATION_TOKEN;
|
|
12571
12629
|
return token?.trim() ? token.trim() : null;
|
|
12572
12630
|
}
|
|
12573
|
-
function childShopifyDeployEnv(
|
|
12631
|
+
function childShopifyDeployEnv(_runtime, token) {
|
|
12574
12632
|
return {
|
|
12575
|
-
...process.env,
|
|
12576
|
-
...(runtime.env ?? {}),
|
|
12577
12633
|
SHOPIFY_APP_AUTOMATION_TOKEN: token,
|
|
12578
12634
|
};
|
|
12579
12635
|
}
|
|
@@ -12682,8 +12738,8 @@ async function runConnectorsShopifySourceInit(command, io, runtime) {
|
|
|
12682
12738
|
sourceCheckout: checkout.sourceCheckout,
|
|
12683
12739
|
commit: gitCommit,
|
|
12684
12740
|
},
|
|
12685
|
-
validateCommand:
|
|
12686
|
-
deployCommand:
|
|
12741
|
+
validateCommand: shopifyCliCommandLine(shopifyValidateArgs({ dir, clientId: command.clientId })),
|
|
12742
|
+
deployCommand: shopifyCliCommandLine(shopifyDeployArgs({ dir, clientId: command.clientId, version: 'connector-source', message: null, sourceControlUrl: null, allowDeletes: false })),
|
|
12687
12743
|
};
|
|
12688
12744
|
printConnectorsPayload(command, io, result, [
|
|
12689
12745
|
`connector_id: ${command.connectorId}`,
|
|
@@ -12745,10 +12801,10 @@ async function runConnectorsShopifySourceValidate(command, io, runtime) {
|
|
|
12745
12801
|
}
|
|
12746
12802
|
}
|
|
12747
12803
|
if (!command.execute) {
|
|
12748
|
-
printConnectorsPayload(command, io, { ok: true, dryRun: true, command: command.command, connectorId: command.connectorId, sourceArtifactId, dir, shopifyCommand:
|
|
12804
|
+
printConnectorsPayload(command, io, { ok: true, dryRun: true, command: command.command, connectorId: command.connectorId, sourceArtifactId, dir, shopifyCommand: shopifyCliCommandLine(args) }, [`connector_id: ${command.connectorId}`, `source_artifact_id: ${sourceArtifactId}`, `source_dir: ${dir}`, `shopify_command: ${shopifyCliCommandLine(args)}`]);
|
|
12749
12805
|
return 0;
|
|
12750
12806
|
}
|
|
12751
|
-
const result = await
|
|
12807
|
+
const result = await runShopifyCliCommand({ args, cwd: dir, runtime });
|
|
12752
12808
|
printConnectorsPayload(command, io, { ok: true, command: command.command, connectorId: command.connectorId, sourceArtifactId, dir, exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr }, [`connector_id: ${command.connectorId}`, `source_artifact_id: ${sourceArtifactId}`, `source_dir: ${dir}`, 'validation: passed']);
|
|
12753
12809
|
return 0;
|
|
12754
12810
|
}
|
|
@@ -12769,7 +12825,7 @@ async function runConnectorsShopifySourceDeploy(command, io, runtime) {
|
|
|
12769
12825
|
allowDeletes: command.allowDeletes,
|
|
12770
12826
|
});
|
|
12771
12827
|
if (command.confirm !== 'deploy') {
|
|
12772
|
-
printConnectorsPayload(command, io, { ok: true, dryRun: true, command: command.command, connectorId: command.connectorId, sourceArtifactId, dir, shopifyCommand:
|
|
12828
|
+
printConnectorsPayload(command, io, { ok: true, dryRun: true, command: command.command, connectorId: command.connectorId, sourceArtifactId, dir, shopifyCommand: shopifyCliCommandLine(args), confirmRequired: 'deploy' }, [`connector_id: ${command.connectorId}`, `source_artifact_id: ${sourceArtifactId}`, `source_dir: ${dir}`, `shopify_command: ${shopifyCliCommandLine(args)}`, 'confirm_required: --confirm deploy']);
|
|
12773
12829
|
return 0;
|
|
12774
12830
|
}
|
|
12775
12831
|
const deployToken = await resolveShopifyDeployTokenEnvironment({
|
|
@@ -12779,7 +12835,7 @@ async function runConnectorsShopifySourceDeploy(command, io, runtime) {
|
|
|
12779
12835
|
runtime,
|
|
12780
12836
|
fetcher,
|
|
12781
12837
|
});
|
|
12782
|
-
const result = await
|
|
12838
|
+
const result = await runShopifyCliCommand({ args, cwd: dir, runtime, env: deployToken.env, redactions: deployToken.redactions });
|
|
12783
12839
|
printConnectorsPayload(command, io, { ok: true, command: command.command, connectorId: command.connectorId, sourceArtifactId, dir, exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr }, [`connector_id: ${command.connectorId}`, `source_artifact_id: ${sourceArtifactId}`, `source_dir: ${dir}`, 'deploy: completed']);
|
|
12784
12840
|
return 0;
|
|
12785
12841
|
}
|
|
@@ -13880,6 +13936,9 @@ function cliErrorMessage(error) {
|
|
|
13880
13936
|
return String(error);
|
|
13881
13937
|
}
|
|
13882
13938
|
function cliErrorCode(error) {
|
|
13939
|
+
if (error instanceof TenderCliChildProcessError) {
|
|
13940
|
+
return 'child_process_failed';
|
|
13941
|
+
}
|
|
13883
13942
|
if (error instanceof TenderCliDbApiError || error instanceof TenderCliAnalyticsApiError || error instanceof TenderCliConnectorsApiError) {
|
|
13884
13943
|
return error.reasonCode;
|
|
13885
13944
|
}
|
|
@@ -13967,6 +14026,16 @@ function cliErrorPayload(error, args, command) {
|
|
|
13967
14026
|
const scope = scopeForError(error, args, command);
|
|
13968
14027
|
const example = exampleForError(error, args, command);
|
|
13969
14028
|
const nextAction = nextActionForError(error);
|
|
14029
|
+
const childProcess = error instanceof TenderCliChildProcessError
|
|
14030
|
+
? {
|
|
14031
|
+
command: error.command,
|
|
14032
|
+
args: error.args,
|
|
14033
|
+
commandLine: commandLine(error.command, error.args),
|
|
14034
|
+
exitCode: error.exitCode,
|
|
14035
|
+
stdout: error.stdout,
|
|
14036
|
+
stderr: error.stderr,
|
|
14037
|
+
}
|
|
14038
|
+
: null;
|
|
13970
14039
|
return {
|
|
13971
14040
|
ok: false,
|
|
13972
14041
|
command: commandNameForError(args, command),
|
|
@@ -13975,6 +14044,7 @@ function cliErrorPayload(error, args, command) {
|
|
|
13975
14044
|
...(scope ? { scope } : {}),
|
|
13976
14045
|
...(nextAction ? { nextAction } : {}),
|
|
13977
14046
|
...(example ? { example } : {}),
|
|
14047
|
+
...(childProcess ? { childProcess } : {}),
|
|
13978
14048
|
};
|
|
13979
14049
|
}
|
|
13980
14050
|
export async function runTenderCli(args, io = {
|