diff --git a/src/utils/deploy.ts b/src/utils/deploy.ts index 8fdd80e4..b777119b 100644 --- a/src/utils/deploy.ts +++ b/src/utils/deploy.ts @@ -24,6 +24,7 @@ import { ComponentStatus, DeployResult, DestructiveChangesType, + expandDataspaceScopedComponentSet, FileResponseSuccess, MetadataApiDeploy, MetadataApiDeployOptions, @@ -119,6 +120,33 @@ export async function buildComponentSet(opts: Partial, stl?: Sour }); } +/** + * Whether any requested component uses the Data Cloud dataspace-scoped adapter strategy + * (CalculatedInsight, DataModelObject). This is the gate for the dataspace-only dependency + * expansion below — every other deploy short-circuits before touching that code path. + */ +const hasDataspaceScopedComponents = (requested: ComponentSet): boolean => + [...requested.getSourceComponents()].some((c) => c.type.strategies?.adapter === 'dataspaceScoped'); + +/** + * Data Cloud dataspace-scoped types (CalculatedInsight, DataModelObject) declare their + * dependencies inline (a CI `dependsOn` its DataModelObject(s)). When the user asks to deploy such a + * component, the referenced dependencies must ride along in the same deploy, but nothing else in the + * project should. This resolves the whole project, then returns the requested set expanded with just + * the transitive dataspace-scoped dependency closure. + * + * Only call this when {@link hasDataspaceScopedComponents} is true — it is not a no-op for ordinary + * deploys (it resolves the entire project). + */ +async function expandDataspaceScopedDependencies( + requested: ComponentSet, + registry?: RegistryAccess +): Promise { + // Resolve the full project so dependsOn references (by entityPayload.name) can be located. + const full = await ComponentSetBuilder.build({ sourcepath: await getPackageDirs() }); + return expandDataspaceScopedComponentSet(full, requested, registry); +} + export async function executeDeploy( opts: Partial, project?: SfProject, @@ -166,6 +194,11 @@ export async function executeDeploy( registry = stl.registry; componentSet = await buildComponentSet(opts, stl); + // Data Cloud only: dataspace-scoped components (CI/DMO) pull their inline dependency closure + // into the same deploy. Every other deploy skips this entirely and leaves componentSet as-is. + if (hasDataspaceScopedComponents(componentSet)) { + componentSet = await expandDataspaceScopedDependencies(componentSet, registry); + } if (componentSet.size === 0) { if (opts['source-dir'] ?? opts.manifest ?? opts.metadata ?? throwOnEmpty) { // the user specified something to deploy, but there isn't anything