@tenderprompt/cli 0.1.36 → 0.1.37
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 +107 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
3
4
|
import { readFileSync } from 'node:fs';
|
|
4
5
|
import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
5
6
|
import os from 'node:os';
|
|
@@ -164,6 +165,12 @@ class TenderCliChildProcessError extends Error {
|
|
|
164
165
|
this.stderr = input.stderr;
|
|
165
166
|
}
|
|
166
167
|
}
|
|
168
|
+
class TenderCliDependencyInstallError extends TenderCliChildProcessError {
|
|
169
|
+
constructor(input) {
|
|
170
|
+
super(input);
|
|
171
|
+
this.name = 'TenderCliDependencyInstallError';
|
|
172
|
+
}
|
|
173
|
+
}
|
|
167
174
|
const DEFAULT_PROFILE_NAME = 'default';
|
|
168
175
|
const DEFAULT_BASE_URL = 'https://app.tenderprompt.com';
|
|
169
176
|
const ARTIFACT_SOURCE_EXPORT_MAX_FILES = 1000;
|
|
@@ -12288,6 +12295,85 @@ function redactSensitiveText(value, secrets = []) {
|
|
|
12288
12295
|
.replace(/\b(authorization\s*[:=]\s*(?:Bearer\s+)?)([^\s'"]+)/gi, '$1[REDACTED]')
|
|
12289
12296
|
.replace(/\b(x-shopify-access-token\s*[:=]\s*)([^\s'"]+)/gi, '$1[REDACTED]');
|
|
12290
12297
|
}
|
|
12298
|
+
const SHOPIFY_SOURCE_DEPENDENCY_STATE_VERSION = 1;
|
|
12299
|
+
const SHOPIFY_SOURCE_DEPENDENCY_STATE_FILE = '.tender-shopify-dependencies.json';
|
|
12300
|
+
function dependencyInstallChildEnv(runtime) {
|
|
12301
|
+
const env = shopifyCliChildEnv(runtime);
|
|
12302
|
+
for (const key of Object.keys(env)) {
|
|
12303
|
+
const normalized = key.toUpperCase();
|
|
12304
|
+
if (/(?:TOKEN|SECRET|PASSWORD|PASSWD|AUTHORIZATION|COOKIE|API_KEY|PRIVATE_KEY|CREDENTIAL)/.test(normalized)) {
|
|
12305
|
+
delete env[key];
|
|
12306
|
+
}
|
|
12307
|
+
}
|
|
12308
|
+
return {
|
|
12309
|
+
...env,
|
|
12310
|
+
NPM_CONFIG_USERCONFIG: '/dev/null',
|
|
12311
|
+
};
|
|
12312
|
+
}
|
|
12313
|
+
async function prepareShopifySourceDependencies(input) {
|
|
12314
|
+
const packageJsonPath = path.join(input.dir, 'package.json');
|
|
12315
|
+
if (!(await fileExists(packageJsonPath))) {
|
|
12316
|
+
return {
|
|
12317
|
+
status: 'not_required',
|
|
12318
|
+
packageManager: null,
|
|
12319
|
+
lockfile: null,
|
|
12320
|
+
installed: false,
|
|
12321
|
+
};
|
|
12322
|
+
}
|
|
12323
|
+
const lockfileName = 'package-lock.json';
|
|
12324
|
+
const lockfilePath = path.join(input.dir, lockfileName);
|
|
12325
|
+
if (!(await fileExists(lockfilePath))) {
|
|
12326
|
+
throw new TenderCliUsageError('Missing package-lock.json. Shopify connector source with package.json must commit a lockfile before validation or deployment.');
|
|
12327
|
+
}
|
|
12328
|
+
const dependencyStateHash = createHash('sha256')
|
|
12329
|
+
.update(await readFile(packageJsonPath))
|
|
12330
|
+
.update('\0')
|
|
12331
|
+
.update(await readFile(lockfilePath))
|
|
12332
|
+
.digest('hex');
|
|
12333
|
+
const statePath = path.join(input.dir, 'node_modules', SHOPIFY_SOURCE_DEPENDENCY_STATE_FILE);
|
|
12334
|
+
try {
|
|
12335
|
+
const state = JSON.parse(await readFile(statePath, 'utf8'));
|
|
12336
|
+
if (typeof state === 'object' &&
|
|
12337
|
+
state !== null &&
|
|
12338
|
+
'version' in state &&
|
|
12339
|
+
state.version === SHOPIFY_SOURCE_DEPENDENCY_STATE_VERSION &&
|
|
12340
|
+
'dependencyStateHash' in state &&
|
|
12341
|
+
state.dependencyStateHash === dependencyStateHash) {
|
|
12342
|
+
return {
|
|
12343
|
+
status: 'ready',
|
|
12344
|
+
packageManager: 'npm',
|
|
12345
|
+
lockfile: lockfileName,
|
|
12346
|
+
installed: false,
|
|
12347
|
+
};
|
|
12348
|
+
}
|
|
12349
|
+
}
|
|
12350
|
+
catch {
|
|
12351
|
+
// A missing or stale marker means the locked dependency tree must be rebuilt.
|
|
12352
|
+
}
|
|
12353
|
+
const runner = input.runtime.commandRunner ?? defaultCommandRunner;
|
|
12354
|
+
const args = ['ci', '--ignore-scripts'];
|
|
12355
|
+
const result = await runner('npm', args, {
|
|
12356
|
+
cwd: input.dir,
|
|
12357
|
+
env: dependencyInstallChildEnv(input.runtime),
|
|
12358
|
+
});
|
|
12359
|
+
if (result.exitCode !== 0) {
|
|
12360
|
+
throw new TenderCliDependencyInstallError({
|
|
12361
|
+
command: 'npm',
|
|
12362
|
+
args,
|
|
12363
|
+
exitCode: result.exitCode,
|
|
12364
|
+
stdout: redactSensitiveText(result.stdout),
|
|
12365
|
+
stderr: redactSensitiveText(result.stderr),
|
|
12366
|
+
});
|
|
12367
|
+
}
|
|
12368
|
+
await mkdir(path.dirname(statePath), { recursive: true });
|
|
12369
|
+
await writeFile(statePath, `${JSON.stringify({ version: SHOPIFY_SOURCE_DEPENDENCY_STATE_VERSION, dependencyStateHash })}\n`, 'utf8');
|
|
12370
|
+
return {
|
|
12371
|
+
status: 'ready',
|
|
12372
|
+
packageManager: 'npm',
|
|
12373
|
+
lockfile: lockfileName,
|
|
12374
|
+
installed: true,
|
|
12375
|
+
};
|
|
12376
|
+
}
|
|
12291
12377
|
async function runShopifyCliCommand(input) {
|
|
12292
12378
|
const runner = input.runtime.commandRunner ?? defaultCommandRunner;
|
|
12293
12379
|
const invocation = shopifyCliCommand(input.args);
|
|
@@ -12534,6 +12620,7 @@ async function runConnectorsShopifySourceValidate(command, io, runtime) {
|
|
|
12534
12620
|
]);
|
|
12535
12621
|
return 0;
|
|
12536
12622
|
}
|
|
12623
|
+
const dependencies = await prepareShopifySourceDependencies({ dir, runtime });
|
|
12537
12624
|
const validationToken = await resolveShopifyCliTokenEnvironment({
|
|
12538
12625
|
command,
|
|
12539
12626
|
sourceArtifactId,
|
|
@@ -12557,7 +12644,14 @@ async function runConnectorsShopifySourceValidate(command, io, runtime) {
|
|
|
12557
12644
|
exitCode: result.exitCode,
|
|
12558
12645
|
stdout: result.stdout,
|
|
12559
12646
|
stderr: result.stderr,
|
|
12560
|
-
|
|
12647
|
+
dependencies,
|
|
12648
|
+
}, [
|
|
12649
|
+
`connector_id: ${command.connectorId}`,
|
|
12650
|
+
`source_artifact_id: ${sourceArtifactId}`,
|
|
12651
|
+
`source_dir: ${dir}`,
|
|
12652
|
+
`dependencies: ${dependencies.status === 'ready' ? (dependencies.installed ? 'installed' : 'cached') : 'not_required'}`,
|
|
12653
|
+
'validation: passed',
|
|
12654
|
+
]);
|
|
12561
12655
|
return 0;
|
|
12562
12656
|
}
|
|
12563
12657
|
async function runConnectorsShopifySourceDeploy(command, io, runtime) {
|
|
@@ -12595,6 +12689,7 @@ async function runConnectorsShopifySourceDeploy(command, io, runtime) {
|
|
|
12595
12689
|
]);
|
|
12596
12690
|
return 0;
|
|
12597
12691
|
}
|
|
12692
|
+
const dependencies = await prepareShopifySourceDependencies({ dir, runtime });
|
|
12598
12693
|
const deployToken = await resolveShopifyCliTokenEnvironment({
|
|
12599
12694
|
command,
|
|
12600
12695
|
sourceArtifactId,
|
|
@@ -12612,7 +12707,14 @@ async function runConnectorsShopifySourceDeploy(command, io, runtime) {
|
|
|
12612
12707
|
exitCode: result.exitCode,
|
|
12613
12708
|
stdout: result.stdout,
|
|
12614
12709
|
stderr: result.stderr,
|
|
12615
|
-
|
|
12710
|
+
dependencies,
|
|
12711
|
+
}, [
|
|
12712
|
+
`connector_id: ${command.connectorId}`,
|
|
12713
|
+
`source_artifact_id: ${sourceArtifactId}`,
|
|
12714
|
+
`source_dir: ${dir}`,
|
|
12715
|
+
`dependencies: ${dependencies.status === 'ready' ? (dependencies.installed ? 'installed' : 'cached') : 'not_required'}`,
|
|
12716
|
+
'deploy: completed',
|
|
12717
|
+
]);
|
|
12616
12718
|
return 0;
|
|
12617
12719
|
}
|
|
12618
12720
|
async function runConnectorsShopifyDelete(command, io, runtime) {
|
|
@@ -13457,6 +13559,9 @@ function cliErrorMessage(error) {
|
|
|
13457
13559
|
return String(error);
|
|
13458
13560
|
}
|
|
13459
13561
|
function cliErrorCode(error) {
|
|
13562
|
+
if (error instanceof TenderCliDependencyInstallError) {
|
|
13563
|
+
return 'dependency_install_failed';
|
|
13564
|
+
}
|
|
13460
13565
|
if (error instanceof TenderCliChildProcessError) {
|
|
13461
13566
|
return 'child_process_failed';
|
|
13462
13567
|
}
|