@hs-x/cli 0.4.1 → 0.4.2-next.1
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 +7 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +5 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/command-catalog.d.ts +2 -2
- package/dist/command-catalog.d.ts.map +1 -1
- package/dist/command-catalog.js +1 -0
- package/dist/command-catalog.js.map +1 -1
- package/dist/commands/account.d.ts.map +1 -1
- package/dist/commands/account.js +28 -4
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/api.d.ts.map +1 -1
- package/dist/commands/api.js +4 -3
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +36 -1
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/connect.js +5 -5
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/deploy.d.ts +3 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +51 -145
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +20 -0
- package/dist/commands/help-command.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +39 -9
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/project-lifecycle-schema.d.ts +67 -0
- package/dist/commands/project-lifecycle-schema.d.ts.map +1 -0
- package/dist/commands/project-lifecycle-schema.js +143 -0
- package/dist/commands/project-lifecycle-schema.js.map +1 -0
- package/dist/commands/project-lifecycle.d.ts +61 -0
- package/dist/commands/project-lifecycle.d.ts.map +1 -0
- package/dist/commands/project-lifecycle.js +641 -0
- package/dist/commands/project-lifecycle.js.map +1 -0
- package/dist/commands/project.d.ts +37 -0
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +77 -0
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/react-health.d.ts +73 -0
- package/dist/commands/react-health.d.ts.map +1 -0
- package/dist/commands/react-health.js +677 -0
- package/dist/commands/react-health.js.map +1 -0
- package/dist/commands/react.d.ts +71 -0
- package/dist/commands/react.d.ts.map +1 -0
- package/dist/commands/react.js +884 -0
- package/dist/commands/react.js.map +1 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/control-plane-tenant-provisioning.d.ts.map +1 -1
- package/dist/control-plane-tenant-provisioning.js +9 -0
- package/dist/control-plane-tenant-provisioning.js.map +1 -1
- package/dist/errors-registry.d.ts.map +1 -1
- package/dist/errors-registry.js +54 -4
- package/dist/errors-registry.js.map +1 -1
- package/dist/hubspot-developer-client.d.ts +4 -3
- package/dist/hubspot-developer-client.d.ts.map +1 -1
- package/dist/hubspot-developer-client.js +15 -11
- package/dist/hubspot-developer-client.js.map +1 -1
- package/dist/hubspot-project-archive.d.ts.map +1 -1
- package/dist/hubspot-project-archive.js +15 -1
- package/dist/hubspot-project-archive.js.map +1 -1
- package/dist/hubspot-project-lifecycle.d.ts +64 -0
- package/dist/hubspot-project-lifecycle.d.ts.map +1 -0
- package/dist/hubspot-project-lifecycle.js +227 -0
- package/dist/hubspot-project-lifecycle.js.map +1 -0
- package/dist/hubspot-project-workspaces.d.ts +10 -0
- package/dist/hubspot-project-workspaces.d.ts.map +1 -0
- package/dist/hubspot-project-workspaces.js +224 -0
- package/dist/hubspot-project-workspaces.js.map +1 -0
- package/dist/init/templates.d.ts +1 -0
- package/dist/init/templates.d.ts.map +1 -1
- package/dist/init/templates.js +11 -8
- package/dist/init/templates.js.map +1 -1
- package/dist/reporter/style.d.ts.map +1 -1
- package/dist/reporter/style.js +10 -1
- package/dist/reporter/style.js.map +1 -1
- package/package.json +12 -9
package/dist/commands/deploy.js
CHANGED
|
@@ -9,6 +9,7 @@ import * as Options from '@effect/cli/Options';
|
|
|
9
9
|
import { cloudflareResourceName, generateHubSpotRuntimeProject, generateProjectArtifacts, planPortalSchemaManagement, planWorkerCronTriggers, renderAlchemyProgram, renderCloudflareWorkerEntrypoint, stampMigratedRunServerlessShimOrigin, } from '@hs-x/codegen';
|
|
10
10
|
import { HttpClientRequest, Schema, schemas, signDeploymentAttestationGrant } from '@hs-x/types';
|
|
11
11
|
import { validateProject } from '@hs-x/validator';
|
|
12
|
+
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
12
13
|
import { Effect, Option } from 'effect';
|
|
13
14
|
import { isLinked } from '../account-store.js';
|
|
14
15
|
import { exitWith } from '../cli-error.js';
|
|
@@ -26,6 +27,7 @@ import { resolveDeployTargets } from '../deploy-targets.js';
|
|
|
26
27
|
import { executeCliHttp } from '../effect-http.js';
|
|
27
28
|
import { DirectHubSpotAccountResolutionError, createDeployHubSpotDeveloperClient, resolveDirectHubSpotContext, } from '../hubspot-developer-client.js';
|
|
28
29
|
import { HubSpotProjectArchiveSourceError, fingerprintHubSpotArchiveSource, writeLocalHubSpotProjectArchive, } from '../hubspot-project-archive.js';
|
|
30
|
+
import { deployHubSpotProjectBuild, waitForHubSpotAutoDeploy, waitForHubSpotBuildStatus, } from '../hubspot-project-lifecycle.js';
|
|
29
31
|
import { detectLocalProjectMode, readHubSpotProjectDescriptor, validateHubSpotProject, } from '../hubspot-project.js';
|
|
30
32
|
import { hydrateAncestorEnv } from '../load-env.js';
|
|
31
33
|
import { LocalProjectPickerCancelled, resolveLocalProject } from '../local-project-picker.js';
|
|
@@ -487,6 +489,9 @@ async function waitForHealthyControlPlaneDrift({ controlPlaneUrl, projectId, dep
|
|
|
487
489
|
} while (Date.now() - startedAt < timeoutMs);
|
|
488
490
|
throw new Error(`Timed out waiting for deploy ${deployId} to become healthy; latest drift state was ${lastState}${lastReason ? `: ${lastReason}` : ''}.`);
|
|
489
491
|
}
|
|
492
|
+
function sleep(ms) {
|
|
493
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
494
|
+
}
|
|
490
495
|
function isRecord(value) {
|
|
491
496
|
return typeof value === 'object' && value !== null;
|
|
492
497
|
}
|
|
@@ -648,6 +653,7 @@ async function executeHubSpotDirectDeployCommand({ argv, root, json, }) {
|
|
|
648
653
|
'--portal-schema-live',
|
|
649
654
|
'--portal-schema-fixture',
|
|
650
655
|
'--local-hubspot-schema',
|
|
656
|
+
'--diagnostic-card-signature-capture',
|
|
651
657
|
].find((flag) => includesCliFlag(argv, flag));
|
|
652
658
|
if (unsupported) {
|
|
653
659
|
return inputValidationError({
|
|
@@ -1032,6 +1038,7 @@ export async function deployCommand({ argv, root, json, }) {
|
|
|
1032
1038
|
const cloudflareDeploy = argv.includes('--cloudflare-deploy');
|
|
1033
1039
|
const cloudflareDryRun = argv.includes('--cloudflare-dry-run');
|
|
1034
1040
|
const explicitCloudflareDeployRequested = cloudflareDeploy || cloudflareDryRun;
|
|
1041
|
+
const diagnosticCardSignatureCapture = argv.includes('--diagnostic-card-signature-capture');
|
|
1035
1042
|
const noManageSchema = argv.includes('--no-manage-schema');
|
|
1036
1043
|
const localControlPlane = argv.includes('--local-control-plane');
|
|
1037
1044
|
const recordLocal = argv.includes('--record-local');
|
|
@@ -1684,6 +1691,7 @@ export async function deployCommand({ argv, root, json, }) {
|
|
|
1684
1691
|
? 'plan'
|
|
1685
1692
|
: 'local-artifacts',
|
|
1686
1693
|
deploymentMode,
|
|
1694
|
+
diagnosticCardSignatureCapture,
|
|
1687
1695
|
targets: {
|
|
1688
1696
|
cloudflare: {
|
|
1689
1697
|
requested: cloudflareDeployRequested,
|
|
@@ -1941,6 +1949,15 @@ function buildDeploySummaryRows(input) {
|
|
|
1941
1949
|
value: input.plan.deploymentMode,
|
|
1942
1950
|
},
|
|
1943
1951
|
];
|
|
1952
|
+
if (input.plan.diagnosticCardSignatureCapture) {
|
|
1953
|
+
rows.push({
|
|
1954
|
+
key: 'card signature capture',
|
|
1955
|
+
value: 'enabled for this deploy',
|
|
1956
|
+
status: 'warn',
|
|
1957
|
+
detail: 'exact signed card requests will be written to Worker logs',
|
|
1958
|
+
hint: 'Capture one test request, then immediately redeploy without --diagnostic-card-signature-capture.',
|
|
1959
|
+
});
|
|
1960
|
+
}
|
|
1944
1961
|
if (input.controlPlanePlan) {
|
|
1945
1962
|
rows.push({
|
|
1946
1963
|
key: 'deploy',
|
|
@@ -2738,6 +2755,8 @@ async function executeCloudflareWorkerDeploy({ argv, root, worker, index, allowC
|
|
|
2738
2755
|
await writeFile(entrypointPath, renderCloudflareWorkerEntrypoint({
|
|
2739
2756
|
workerImportPath: relativeImportPath(dirname(entrypointPath), workerSourcePath),
|
|
2740
2757
|
requireActiveCardInstall: appConfig.auth === 'oauth',
|
|
2758
|
+
...(appConfig.install ? { installSuccessUrl: appConfig.install.successUrl } : {}),
|
|
2759
|
+
diagnosticCardSignatureCapture: argv.includes('--diagnostic-card-signature-capture'),
|
|
2741
2760
|
// Tenant D1/KV and the grant secret are shared across the linked app's
|
|
2742
2761
|
// Workers. Wire the matching routes on every linked Worker even though
|
|
2743
2762
|
// revision-bound heartbeat/attestation remains primary-only below.
|
|
@@ -3886,6 +3905,8 @@ export async function readHsxAppConfig(root) {
|
|
|
3886
3905
|
}
|
|
3887
3906
|
}
|
|
3888
3907
|
}
|
|
3908
|
+
if (loaded?.install)
|
|
3909
|
+
assertInstallSuccessUrl(loaded.install.successUrl);
|
|
3889
3910
|
return {
|
|
3890
3911
|
appName: loaded?.name ?? /name\s*:\s*["'`]([^"'`]+)["'`]/.exec(raw)?.[1] ?? basename(root),
|
|
3891
3912
|
// No regex fallback for description: a raw-text match could pick up a
|
|
@@ -3907,6 +3928,7 @@ export async function readHsxAppConfig(root) {
|
|
|
3907
3928
|
...(loaded?.rateLimits !== undefined ? { rateLimits: loaded.rateLimits } : {}),
|
|
3908
3929
|
...(loaded?.alerts !== undefined ? { alerts: loaded.alerts } : {}),
|
|
3909
3930
|
...(loaded?.redaction !== undefined ? { redaction: loaded.redaction } : {}),
|
|
3931
|
+
...(loaded?.install !== undefined ? { install: loaded.install } : {}),
|
|
3910
3932
|
// Helper-based declarations are only recoverable from the loaded module
|
|
3911
3933
|
// (the literal parser cannot evaluate card(...) or mcpServer(...) calls).
|
|
3912
3934
|
cards: loaded?.cards ?? [],
|
|
@@ -3969,6 +3991,20 @@ async function loadHsxAppConfigModule(root) {
|
|
|
3969
3991
|
? app
|
|
3970
3992
|
: undefined;
|
|
3971
3993
|
}
|
|
3994
|
+
function assertInstallSuccessUrl(value) {
|
|
3995
|
+
let url;
|
|
3996
|
+
try {
|
|
3997
|
+
url = new URL(value);
|
|
3998
|
+
}
|
|
3999
|
+
catch {
|
|
4000
|
+
throw new Error('install.successUrl must be an absolute HTTPS URL.');
|
|
4001
|
+
}
|
|
4002
|
+
const localHttp = url.protocol === 'http:' &&
|
|
4003
|
+
(url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]');
|
|
4004
|
+
if ((url.protocol !== 'https:' && !localHttp) || url.username || url.password) {
|
|
4005
|
+
throw new Error('install.successUrl must use HTTPS without embedded credentials (localhost HTTP is allowed for development).');
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
3972
4008
|
function readStringArrayProperty(source, propertyName) {
|
|
3973
4009
|
const body = new RegExp(`${propertyName}\\s*:\\s*\\[([\\s\\S]*?)\\]`).exec(source)?.[1];
|
|
3974
4010
|
if (!body) {
|
|
@@ -4251,14 +4287,15 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4251
4287
|
await client.projects.ensureProject({ projectName });
|
|
4252
4288
|
const hsproject = await readHubSpotProjectConfig(root);
|
|
4253
4289
|
const configuredPlatformVersion = typeof hsproject.platformVersion === 'string' ? hsproject.platformVersion : undefined;
|
|
4290
|
+
const platformVersion = prepared?.platformVersion ??
|
|
4291
|
+
resolveFlag(argv, '--platform-version') ??
|
|
4292
|
+
configuredPlatformVersion ??
|
|
4293
|
+
'2026.03';
|
|
4254
4294
|
const upload = await client.projects.upload({
|
|
4255
4295
|
projectName,
|
|
4256
4296
|
archivePath,
|
|
4257
4297
|
message: prepared?.buildMessage ?? resolveFlag(argv, '--message') ?? 'HS-X HubSpot-only deploy',
|
|
4258
|
-
platformVersion
|
|
4259
|
-
resolveFlag(argv, '--platform-version') ??
|
|
4260
|
-
configuredPlatformVersion ??
|
|
4261
|
-
'2026.03',
|
|
4298
|
+
platformVersion,
|
|
4262
4299
|
intermediateRepresentation,
|
|
4263
4300
|
skipAutoDeploy: uploadOnly,
|
|
4264
4301
|
});
|
|
@@ -4288,13 +4325,13 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4288
4325
|
// therefore a strict build-only result.
|
|
4289
4326
|
const autoDeployExpected = !uploadOnly && autoDeployEnabled === true && readStatus(buildStatus) === 'SUCCESS';
|
|
4290
4327
|
const autoDeployStatus = autoDeployExpected
|
|
4291
|
-
? await waitForHubSpotAutoDeploy({
|
|
4328
|
+
? (await waitForHubSpotAutoDeploy({
|
|
4292
4329
|
client,
|
|
4293
4330
|
projectName,
|
|
4294
4331
|
buildId: upload.buildId,
|
|
4295
4332
|
buildStatus,
|
|
4296
4333
|
timeoutMs,
|
|
4297
|
-
})
|
|
4334
|
+
})).status
|
|
4298
4335
|
: undefined;
|
|
4299
4336
|
return {
|
|
4300
4337
|
projectName,
|
|
@@ -4311,25 +4348,17 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4311
4348
|
local,
|
|
4312
4349
|
};
|
|
4313
4350
|
}
|
|
4314
|
-
const
|
|
4351
|
+
const deployed = await deployHubSpotProjectBuild({
|
|
4352
|
+
client,
|
|
4315
4353
|
projectName,
|
|
4316
4354
|
buildId: upload.buildId,
|
|
4317
4355
|
force: prepared?.force ?? argv.includes('--force'),
|
|
4318
|
-
|
|
4319
|
-
const deployResultType = readStringProperty(deploy, 'buildResultType');
|
|
4320
|
-
if (deployResultType === 'DEPLOY_BLOCKED') {
|
|
4321
|
-
throw new Error(describeBlockedHubSpotDeploy(deploy));
|
|
4322
|
-
}
|
|
4323
|
-
const deployId = readNumericProperty(deploy, 'deployId') ?? readNumericProperty(deploy, 'id');
|
|
4324
|
-
if (deployId === undefined) {
|
|
4325
|
-
throw new Error(`HubSpot returned ${deployResultType ?? 'an unrecognized response'} without a deploy id.`);
|
|
4326
|
-
}
|
|
4327
|
-
const deployStatus = await waitForHubSpotDeployStatus({
|
|
4328
|
-
client,
|
|
4329
|
-
projectName,
|
|
4330
|
-
deployId,
|
|
4356
|
+
legacy: isLegacyProject(platformVersion),
|
|
4331
4357
|
timeoutMs,
|
|
4358
|
+
executeDeploy: (request) => withTransientDeployRetry(() => client.projects.deployBuild(request)),
|
|
4332
4359
|
});
|
|
4360
|
+
const deployId = deployed.deployId;
|
|
4361
|
+
const deployStatus = deployed.status;
|
|
4333
4362
|
const appId = await optionalHubSpotAppId(client, projectName, appUid);
|
|
4334
4363
|
if (persistBinding) {
|
|
4335
4364
|
await persistHubSpotAppBinding(root, {
|
|
@@ -4361,96 +4390,6 @@ async function optionalHubSpotAppId(client, projectName, appUid) {
|
|
|
4361
4390
|
return 0;
|
|
4362
4391
|
}
|
|
4363
4392
|
}
|
|
4364
|
-
/**
|
|
4365
|
-
* Poll the auto-deploy triggered by a successful build until it reaches a
|
|
4366
|
-
* terminal state. The build status carries the deploy task locator
|
|
4367
|
-
* (deployStatusTaskLocator.id); absent/transient lookups resolve undefined —
|
|
4368
|
-
* the caller treats that as "could not verify", never as success.
|
|
4369
|
-
*/
|
|
4370
|
-
async function waitForHubSpotAutoDeploy({ client, projectName, buildId, buildStatus, timeoutMs = 60_000, intervalMs = 2_000, }) {
|
|
4371
|
-
const deadline = Date.now() + timeoutMs;
|
|
4372
|
-
let latestBuildStatus = buildStatus;
|
|
4373
|
-
let deployId = readHubSpotDeployLocator(latestBuildStatus);
|
|
4374
|
-
let last;
|
|
4375
|
-
while (Date.now() < deadline) {
|
|
4376
|
-
if (deployId === undefined) {
|
|
4377
|
-
try {
|
|
4378
|
-
latestBuildStatus = await client.projects.getBuildStatus({ projectName, buildId });
|
|
4379
|
-
deployId = readHubSpotDeployLocator(latestBuildStatus);
|
|
4380
|
-
}
|
|
4381
|
-
catch {
|
|
4382
|
-
// The build may be visible before its auto-deploy locator. Keep trying
|
|
4383
|
-
// until the same bounded timeout instead of declaring success.
|
|
4384
|
-
}
|
|
4385
|
-
if (deployId === undefined) {
|
|
4386
|
-
await sleep(intervalMs);
|
|
4387
|
-
continue;
|
|
4388
|
-
}
|
|
4389
|
-
}
|
|
4390
|
-
try {
|
|
4391
|
-
last = await client.projects.getDeployStatus({ projectName, deployId });
|
|
4392
|
-
}
|
|
4393
|
-
catch {
|
|
4394
|
-
last = undefined;
|
|
4395
|
-
}
|
|
4396
|
-
const status = readStatus(last);
|
|
4397
|
-
if (status && !isHubSpotDeployInProgress(status)) {
|
|
4398
|
-
return last;
|
|
4399
|
-
}
|
|
4400
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
4401
|
-
}
|
|
4402
|
-
return last;
|
|
4403
|
-
}
|
|
4404
|
-
async function waitForHubSpotDeployStatus({ client, projectName, deployId, timeoutMs, intervalMs = 1_000, }) {
|
|
4405
|
-
const deadline = Date.now() + timeoutMs;
|
|
4406
|
-
let latest;
|
|
4407
|
-
do {
|
|
4408
|
-
latest = await client.projects.getDeployStatus({ projectName, deployId });
|
|
4409
|
-
const status = readStatus(latest);
|
|
4410
|
-
if (status && !isHubSpotDeployInProgress(status))
|
|
4411
|
-
return latest;
|
|
4412
|
-
await sleep(intervalMs);
|
|
4413
|
-
} while (Date.now() < deadline);
|
|
4414
|
-
return latest;
|
|
4415
|
-
}
|
|
4416
|
-
function isHubSpotDeployInProgress(status) {
|
|
4417
|
-
return new Set([
|
|
4418
|
-
'PENDING',
|
|
4419
|
-
'QUEUED',
|
|
4420
|
-
'BUILDING',
|
|
4421
|
-
'DEPLOYING',
|
|
4422
|
-
'PROCESSING',
|
|
4423
|
-
'STARTED',
|
|
4424
|
-
'IN_PROGRESS',
|
|
4425
|
-
]).has(status.toUpperCase());
|
|
4426
|
-
}
|
|
4427
|
-
function readHubSpotDeployLocator(value) {
|
|
4428
|
-
if (!isRecord(value) || !isRecord(value.deployStatusTaskLocator))
|
|
4429
|
-
return undefined;
|
|
4430
|
-
const id = value.deployStatusTaskLocator.id;
|
|
4431
|
-
if (typeof id === 'number')
|
|
4432
|
-
return id;
|
|
4433
|
-
if (typeof id !== 'string')
|
|
4434
|
-
return undefined;
|
|
4435
|
-
const parsed = Number.parseInt(id, 10);
|
|
4436
|
-
return Number.isNaN(parsed) ? undefined : parsed;
|
|
4437
|
-
}
|
|
4438
|
-
async function waitForHubSpotBuildStatus({ client, projectName, buildId, timeoutMs, intervalMs, }) {
|
|
4439
|
-
const startedAt = Date.now();
|
|
4440
|
-
let latest;
|
|
4441
|
-
do {
|
|
4442
|
-
latest = await client.projects.getBuildStatus({ projectName, buildId });
|
|
4443
|
-
const status = readStatus(latest);
|
|
4444
|
-
if (status === 'SUCCESS' || status === 'FAILURE') {
|
|
4445
|
-
return latest;
|
|
4446
|
-
}
|
|
4447
|
-
await sleep(intervalMs);
|
|
4448
|
-
} while (Date.now() - startedAt < timeoutMs);
|
|
4449
|
-
return latest;
|
|
4450
|
-
}
|
|
4451
|
-
function sleep(ms) {
|
|
4452
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4453
|
-
}
|
|
4454
4393
|
async function readHubSpotProjectIntermediateRepresentation(root) {
|
|
4455
4394
|
const hsproject = await readHubSpotProjectConfig(root);
|
|
4456
4395
|
const srcDir = typeof hsproject.srcDir === 'string' ? hsproject.srcDir : 'src';
|
|
@@ -4561,41 +4500,6 @@ async function collectHubSpotMetaFiles(root) {
|
|
|
4561
4500
|
await walk(root);
|
|
4562
4501
|
return files.sort();
|
|
4563
4502
|
}
|
|
4564
|
-
function readNumericProperty(value, key) {
|
|
4565
|
-
if (!isRecord(value))
|
|
4566
|
-
return undefined;
|
|
4567
|
-
const property = value[key];
|
|
4568
|
-
if (typeof property === 'number')
|
|
4569
|
-
return property;
|
|
4570
|
-
if (typeof property !== 'string')
|
|
4571
|
-
return undefined;
|
|
4572
|
-
const parsed = Number.parseInt(property, 10);
|
|
4573
|
-
return Number.isNaN(parsed) ? undefined : parsed;
|
|
4574
|
-
}
|
|
4575
|
-
function readStringProperty(value, key) {
|
|
4576
|
-
return isRecord(value) && typeof value[key] === 'string' ? value[key] : undefined;
|
|
4577
|
-
}
|
|
4578
|
-
function describeBlockedHubSpotDeploy(value) {
|
|
4579
|
-
if (!isRecord(value))
|
|
4580
|
-
return 'HubSpot blocked the deploy.';
|
|
4581
|
-
const candidates = [value.issues, value.blockingIssues, value.errors, value.message];
|
|
4582
|
-
const details = candidates.flatMap((candidate) => {
|
|
4583
|
-
if (typeof candidate === 'string')
|
|
4584
|
-
return [candidate];
|
|
4585
|
-
if (!Array.isArray(candidate))
|
|
4586
|
-
return [];
|
|
4587
|
-
return candidate.map((item) => {
|
|
4588
|
-
if (typeof item === 'string')
|
|
4589
|
-
return item;
|
|
4590
|
-
if (!isRecord(item))
|
|
4591
|
-
return String(item);
|
|
4592
|
-
return String(item.message ?? item.reason ?? item.description ?? JSON.stringify(item));
|
|
4593
|
-
});
|
|
4594
|
-
});
|
|
4595
|
-
return details.length > 0
|
|
4596
|
-
? `HubSpot blocked the deploy: ${details.join('; ')}`
|
|
4597
|
-
: 'HubSpot blocked the deploy. Re-run with --force only after reviewing its removal warnings.';
|
|
4598
|
-
}
|
|
4599
4503
|
function readBooleanProperty(value, key) {
|
|
4600
4504
|
return isRecord(value) && typeof value[key] === 'boolean' ? value[key] : undefined;
|
|
4601
4505
|
}
|
|
@@ -5364,6 +5268,7 @@ const deployOptions = {
|
|
|
5364
5268
|
heartbeat: Options.boolean('heartbeat').pipe(Options.withDefault(false)), // --heartbeat
|
|
5365
5269
|
noHeartbeat: Options.boolean('no-heartbeat').pipe(Options.withDefault(false)), // --no-heartbeat
|
|
5366
5270
|
useEnv: Options.boolean('use-env').pipe(Options.withDefault(false)), // --use-env
|
|
5271
|
+
diagnosticCardSignatureCapture: Options.boolean('diagnostic-card-signature-capture').pipe(Options.withDefault(false)),
|
|
5367
5272
|
// Declared explicitly: without it @effect/cli treats `--no-record` as the
|
|
5368
5273
|
// negation of an undeclared `record` boolean and fails routing with a
|
|
5369
5274
|
// confusing root-level "Invalid subcommand" error (the flag is documented).
|
|
@@ -5428,6 +5333,7 @@ const deployBaseCmd = Command.make('deploy', deployOptions, (opts) => runHandler
|
|
|
5428
5333
|
flag('--heartbeat', opts.heartbeat);
|
|
5429
5334
|
flag('--no-heartbeat', opts.noHeartbeat);
|
|
5430
5335
|
flag('--use-env', opts.useEnv);
|
|
5336
|
+
flag('--diagnostic-card-signature-capture', opts.diagnosticCardSignatureCapture);
|
|
5431
5337
|
flag('--no-record', opts.noRecord);
|
|
5432
5338
|
flag('--portal-schema-live', opts.portalSchemaLive);
|
|
5433
5339
|
flag('--local-hubspot-schema', opts.localHubspotSchema);
|