@hs-x/cli 0.4.7 → 0.4.8
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/cloudflare-auth.js +3 -3
- package/dist/cloudflare-auth.js.map +1 -1
- package/dist/cloudflare-oauth.d.ts.map +1 -1
- package/dist/cloudflare-oauth.js +3 -1
- package/dist/cloudflare-oauth.js.map +1 -1
- package/dist/cloudflare-workers-logs.d.ts +38 -0
- package/dist/cloudflare-workers-logs.d.ts.map +1 -0
- package/dist/cloudflare-workers-logs.js +297 -0
- package/dist/cloudflare-workers-logs.js.map +1 -0
- package/dist/commands/control-plane-read.d.ts.map +1 -1
- package/dist/commands/control-plane-read.js +55 -12
- package/dist/commands/control-plane-read.js.map +1 -1
- package/dist/commands/deploy.d.ts +14 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +78 -15
- package/dist/commands/deploy.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/package.json +1 -1
package/dist/commands/deploy.js
CHANGED
|
@@ -27,6 +27,7 @@ import { createControlPlaneTenantProvisioningAuthority, } from '../control-plane
|
|
|
27
27
|
import { captureDeployRevision } from '../deploy-revision-capture.js';
|
|
28
28
|
import { resolveDeployTargets } from '../deploy-targets.js';
|
|
29
29
|
import { executeCliHttp } from '../effect-http.js';
|
|
30
|
+
import { discoverHubSpotAccounts } from '../hubspot-auth.js';
|
|
30
31
|
import { DirectHubSpotAccountResolutionError, createDeployHubSpotDeveloperClient, resolveDirectHubSpotContext, } from '../hubspot-developer-client.js';
|
|
31
32
|
import { HubSpotProjectArchiveSourceError, fingerprintHubSpotArchiveSource, writeLocalHubSpotProjectArchive, } from '../hubspot-project-archive.js';
|
|
32
33
|
import { deployHubSpotProjectBuild, readHubSpotSubbuildStatuses, waitForHubSpotAutoDeploy, waitForHubSpotBuildStatus, } from '../hubspot-project-lifecycle.js';
|
|
@@ -1486,7 +1487,7 @@ export async function deployCommand({ argv, root, json, }) {
|
|
|
1486
1487
|
projectId: controlPlanePlan.projectId,
|
|
1487
1488
|
environment: resolveFlag(argv, '--env') ?? resolveFlag(argv, '--environment') ?? 'production',
|
|
1488
1489
|
})
|
|
1489
|
-
: (readOptionalHubSpotAppId(resolveFlag(argv, '--hubspot-app-id') ?? process.env.HSX_HUBSPOT_APP_ID) ?? (await
|
|
1490
|
+
: (readOptionalHubSpotAppId(resolveFlag(argv, '--hubspot-app-id') ?? process.env.HSX_HUBSPOT_APP_ID) ?? (await readPersistedHubSpotAppIdForDeploy(argv, root)));
|
|
1490
1491
|
const uploadFirstOrigin = cloudflareDeployRequested &&
|
|
1491
1492
|
!cloudflareDryRun &&
|
|
1492
1493
|
!planOnly &&
|
|
@@ -2940,7 +2941,7 @@ async function executeCloudflareWorkerDeploy({ argv, root, worker, index, allowC
|
|
|
2940
2941
|
// Resolution: flag → env → the binding persisted by the last successful
|
|
2941
2942
|
// upload (.hs-x/hubspot.json). Users should never have to replay an app id
|
|
2942
2943
|
// the CLI already learned (owner directive, run-008).
|
|
2943
|
-
const hubspotAppId = readOptionalHubSpotAppId(resolveFlag(argv, '--hubspot-app-id') ?? process.env.HSX_HUBSPOT_APP_ID) ?? (await
|
|
2944
|
+
const hubspotAppId = readOptionalHubSpotAppId(resolveFlag(argv, '--hubspot-app-id') ?? process.env.HSX_HUBSPOT_APP_ID) ?? (await readPersistedHubSpotAppIdForDeploy(argv, root));
|
|
2944
2945
|
const installRuntimeBinding = hubspotAppId
|
|
2945
2946
|
? controlPlaneUrl
|
|
2946
2947
|
? await ensureDeployInstallRuntimeBinding({
|
|
@@ -3069,7 +3070,10 @@ async function executeCloudflareWorkerDeploy({ argv, root, worker, index, allowC
|
|
|
3069
3070
|
...(installRuntimeBinding
|
|
3070
3071
|
? { installKvNamespaceId: installRuntimeBinding.installKvNamespaceId }
|
|
3071
3072
|
: {}),
|
|
3072
|
-
|
|
3073
|
+
// Workers Logs is the observability source for both deployment modes.
|
|
3074
|
+
// Checkpoint remains linked-only and is added separately below.
|
|
3075
|
+
observability: true,
|
|
3076
|
+
...(controlPlaneUrl ? { checkpointDataset: 'hsx_checkpoint' } : {}),
|
|
3073
3077
|
...(controlPlaneUrl ? { versionMetadataBinding: 'CF_VERSION_METADATA' } : {}),
|
|
3074
3078
|
...(tenantDataPlane
|
|
3075
3079
|
? {
|
|
@@ -4784,6 +4788,14 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4784
4788
|
throw error;
|
|
4785
4789
|
}
|
|
4786
4790
|
const buildState = readStatus(buildStatus) ?? 'UNKNOWN';
|
|
4791
|
+
// Legacy ~/.hscli/config.yml accounts can authenticate and upload without
|
|
4792
|
+
// exposing their developer-account id through the selected account object.
|
|
4793
|
+
// HubSpot's build response is authoritative for that same id; retain it so
|
|
4794
|
+
// the app-auth handoff and later zero-selector log reads do not disappear.
|
|
4795
|
+
const resolvedDeveloperAccountId = resolveHubSpotDeveloperAccountIdFromBuild({
|
|
4796
|
+
developerAccountId,
|
|
4797
|
+
buildStatus,
|
|
4798
|
+
});
|
|
4787
4799
|
buildStep?.[buildState === 'SUCCESS' ? 'ok' : 'fail'](`${buildState} · ${elapsedSince(buildStartedAt)}`);
|
|
4788
4800
|
const autoDeployEnabled = readBooleanProperty(buildStatus, 'isAutoDeployEnabled');
|
|
4789
4801
|
if (uploadOnly || readStatus(buildStatus) !== 'SUCCESS' || autoDeployEnabled) {
|
|
@@ -4794,7 +4806,7 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4794
4806
|
await persistHubSpotAppBinding(root, {
|
|
4795
4807
|
appId,
|
|
4796
4808
|
projectName,
|
|
4797
|
-
developerAccountId,
|
|
4809
|
+
developerAccountId: resolvedDeveloperAccountId,
|
|
4798
4810
|
});
|
|
4799
4811
|
// Build SUCCESS does NOT mean the app shipped: HubSpot's auto-deploy can
|
|
4800
4812
|
// still fail (found live: "Apps are not allowed to have 0 redirect URLs"
|
|
@@ -4833,7 +4845,7 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4833
4845
|
archivePath,
|
|
4834
4846
|
appId,
|
|
4835
4847
|
appUid,
|
|
4836
|
-
developerAccountId,
|
|
4848
|
+
developerAccountId: resolvedDeveloperAccountId,
|
|
4837
4849
|
buildId: upload.buildId,
|
|
4838
4850
|
deployId: undefined,
|
|
4839
4851
|
buildStatus,
|
|
@@ -4875,7 +4887,7 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4875
4887
|
await persistHubSpotAppBinding(root, {
|
|
4876
4888
|
appId,
|
|
4877
4889
|
projectName,
|
|
4878
|
-
developerAccountId,
|
|
4890
|
+
developerAccountId: resolvedDeveloperAccountId,
|
|
4879
4891
|
});
|
|
4880
4892
|
}
|
|
4881
4893
|
return {
|
|
@@ -4883,7 +4895,7 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4883
4895
|
archivePath,
|
|
4884
4896
|
appId,
|
|
4885
4897
|
appUid,
|
|
4886
|
-
developerAccountId,
|
|
4898
|
+
developerAccountId: resolvedDeveloperAccountId,
|
|
4887
4899
|
buildId: upload.buildId,
|
|
4888
4900
|
deployId,
|
|
4889
4901
|
buildStatus,
|
|
@@ -4894,12 +4906,27 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4894
4906
|
};
|
|
4895
4907
|
}
|
|
4896
4908
|
async function optionalHubSpotAppId(client, projectName, appUid) {
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
}
|
|
4900
|
-
|
|
4901
|
-
|
|
4909
|
+
return resolveHubSpotAppIdWithRetry({
|
|
4910
|
+
resolve: () => client.projects.resolveAppId(appUid === undefined ? { projectName } : { projectName, appUid }),
|
|
4911
|
+
});
|
|
4912
|
+
}
|
|
4913
|
+
/** @internal Exported for deterministic eventual-consistency regressions. */
|
|
4914
|
+
export async function resolveHubSpotAppIdWithRetry(input) {
|
|
4915
|
+
const attempts = Math.max(1, input.attempts ?? 4);
|
|
4916
|
+
const retryDelayMs = Math.max(0, input.retryDelayMs ?? 500);
|
|
4917
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
4918
|
+
try {
|
|
4919
|
+
const appId = await input.resolve();
|
|
4920
|
+
if (appId > 0)
|
|
4921
|
+
return appId;
|
|
4922
|
+
}
|
|
4923
|
+
catch {
|
|
4924
|
+
// A newly-created app can lag its successful build/deploy metadata.
|
|
4925
|
+
}
|
|
4926
|
+
if (attempt < attempts && retryDelayMs > 0)
|
|
4927
|
+
await sleep(retryDelayMs);
|
|
4902
4928
|
}
|
|
4929
|
+
return 0;
|
|
4903
4930
|
}
|
|
4904
4931
|
async function readHubSpotProjectIntermediateRepresentation(root) {
|
|
4905
4932
|
const hsproject = await readHubSpotProjectConfig(root);
|
|
@@ -5064,8 +5091,32 @@ async function readPersistedHubSpotAppBinding(root, expectedProjectName) {
|
|
|
5064
5091
|
return undefined;
|
|
5065
5092
|
}
|
|
5066
5093
|
}
|
|
5067
|
-
async function readPersistedHubSpotAppId(root, expectedProjectName) {
|
|
5068
|
-
|
|
5094
|
+
async function readPersistedHubSpotAppId(root, expectedProjectName, expectedDeveloperAccountId) {
|
|
5095
|
+
const binding = await readPersistedHubSpotAppBinding(root, expectedProjectName);
|
|
5096
|
+
if (!binding)
|
|
5097
|
+
return undefined;
|
|
5098
|
+
return hubSpotAppBindingMatchesDeveloperAccount(binding.developerAccountId, expectedDeveloperAccountId)
|
|
5099
|
+
? binding.appId
|
|
5100
|
+
: undefined;
|
|
5101
|
+
}
|
|
5102
|
+
/** @internal Exported for deterministic account-switch regressions. */
|
|
5103
|
+
export function hubSpotAppBindingMatchesDeveloperAccount(persistedDeveloperAccountId, selectedDeveloperAccountId) {
|
|
5104
|
+
if (!selectedDeveloperAccountId)
|
|
5105
|
+
return true;
|
|
5106
|
+
return persistedDeveloperAccountId === selectedDeveloperAccountId;
|
|
5107
|
+
}
|
|
5108
|
+
async function resolveHubSpotDeployDeveloperAccountId(argv, root) {
|
|
5109
|
+
const explicit = resolveFlag(argv, '--developer-account-id') ?? process.env.HSX_HUBSPOT_DEVELOPER_ACCOUNT_ID;
|
|
5110
|
+
if (explicit?.trim())
|
|
5111
|
+
return explicit.trim();
|
|
5112
|
+
const configPath = resolveFlag(argv, '--config');
|
|
5113
|
+
const discovered = await discoverHubSpotAccounts(root, configPath ? { configPath } : {});
|
|
5114
|
+
const selected = discovered?.accounts.find((account) => account.isDefault) ??
|
|
5115
|
+
(discovered?.accounts.length === 1 ? discovered.accounts[0] : undefined);
|
|
5116
|
+
return selected ? String(selected.portalId) : undefined;
|
|
5117
|
+
}
|
|
5118
|
+
async function readPersistedHubSpotAppIdForDeploy(argv, root) {
|
|
5119
|
+
return readPersistedHubSpotAppId(root, await resolveHubSpotProjectName(argv, root), await resolveHubSpotDeployDeveloperAccountId(argv, root));
|
|
5069
5120
|
}
|
|
5070
5121
|
/**
|
|
5071
5122
|
* Resolve the one HubSpot app a linked project already registered. The common
|
|
@@ -5076,7 +5127,7 @@ async function readPersistedHubSpotAppId(root, expectedProjectName) {
|
|
|
5076
5127
|
async function resolveHubSpotAppIdForDeploy(input) {
|
|
5077
5128
|
const explicit = readOptionalHubSpotAppId(resolveFlag(input.argv, '--hubspot-app-id') ?? process.env.HSX_HUBSPOT_APP_ID);
|
|
5078
5129
|
const projectName = await resolveHubSpotProjectName(input.argv, input.root);
|
|
5079
|
-
const persisted = await
|
|
5130
|
+
const persisted = await readPersistedHubSpotAppIdForDeploy(input.argv, input.root);
|
|
5080
5131
|
const selected = explicit ?? persisted;
|
|
5081
5132
|
if (selected || !input.controlPlaneUrl)
|
|
5082
5133
|
return selected;
|
|
@@ -5120,6 +5171,18 @@ async function resolveHubSpotAppAuthUrl(argv, root) {
|
|
|
5120
5171
|
function readStatus(value) {
|
|
5121
5172
|
return isRecord(value) && typeof value.status === 'string' ? value.status : undefined;
|
|
5122
5173
|
}
|
|
5174
|
+
/** @internal Exported for deterministic legacy-account deploy regressions. */
|
|
5175
|
+
export function resolveHubSpotDeveloperAccountIdFromBuild(input) {
|
|
5176
|
+
if (input.developerAccountId?.trim())
|
|
5177
|
+
return input.developerAccountId.trim();
|
|
5178
|
+
if (!isRecord(input.buildStatus))
|
|
5179
|
+
return undefined;
|
|
5180
|
+
const portalId = input.buildStatus.portalId;
|
|
5181
|
+
if (typeof portalId === 'number' && Number.isInteger(portalId) && portalId > 0) {
|
|
5182
|
+
return String(portalId);
|
|
5183
|
+
}
|
|
5184
|
+
return typeof portalId === 'string' && portalId.trim().length > 0 ? portalId.trim() : undefined;
|
|
5185
|
+
}
|
|
5123
5186
|
const readSubbuildStatuses = readHubSpotSubbuildStatuses;
|
|
5124
5187
|
const HUBSPOT_COMPONENT_TERMINAL_STATES = new Set(['SUCCESS', 'FAILURE', 'ERROR', 'CANCELLED']);
|
|
5125
5188
|
/** Emit each HubSpot component once, when it reaches a terminal build state. */
|