@camunda8/cli 3.1.0 → 3.2.0-alpha.10
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/CONTEXT.md +7 -15
- package/EXAMPLES.md +253 -1
- package/PLUGIN-HELP.md +1 -1
- package/README.md +50 -180
- package/dist/command-dispatch.d.ts +1 -1
- package/dist/command-dispatch.d.ts.map +1 -1
- package/dist/command-dispatch.js +1 -1
- package/dist/command-dispatch.js.map +1 -1
- package/dist/commands/completion.d.ts +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +2 -3
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/deploy.d.ts +13 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +328 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/forms.d.ts +1 -1
- package/dist/commands/forms.d.ts.map +1 -1
- package/dist/commands/forms.js +8 -8
- package/dist/commands/forms.js.map +1 -1
- package/dist/commands/helpers/deploy-helpers.d.ts +120 -0
- package/dist/commands/helpers/deploy-helpers.d.ts.map +1 -0
- package/dist/{deployments.js → commands/helpers/deploy-helpers.js} +307 -155
- package/dist/commands/helpers/deploy-helpers.js.map +1 -0
- package/dist/commands/identity-authorizations.d.ts +5 -18
- package/dist/commands/identity-authorizations.d.ts.map +1 -1
- package/dist/commands/identity-authorizations.js +8 -10
- package/dist/commands/identity-authorizations.js.map +1 -1
- package/dist/commands/identity-groups.d.ts +5 -5
- package/dist/commands/identity-groups.d.ts.map +1 -1
- package/dist/commands/identity-groups.js +7 -8
- package/dist/commands/identity-groups.js.map +1 -1
- package/dist/commands/identity-mapping-rules.d.ts +5 -5
- package/dist/commands/identity-mapping-rules.d.ts.map +1 -1
- package/dist/commands/identity-mapping-rules.js +7 -8
- package/dist/commands/identity-mapping-rules.js.map +1 -1
- package/dist/commands/identity-roles.d.ts +5 -5
- package/dist/commands/identity-roles.d.ts.map +1 -1
- package/dist/commands/identity-roles.js +7 -8
- package/dist/commands/identity-roles.js.map +1 -1
- package/dist/commands/identity-tenants.d.ts +5 -5
- package/dist/commands/identity-tenants.d.ts.map +1 -1
- package/dist/commands/identity-tenants.js +7 -8
- package/dist/commands/identity-tenants.js.map +1 -1
- package/dist/commands/identity-users.d.ts +5 -5
- package/dist/commands/identity-users.d.ts.map +1 -1
- package/dist/commands/identity-users.js +7 -8
- package/dist/commands/identity-users.js.map +1 -1
- package/dist/commands/identity.d.ts +11 -31
- package/dist/commands/identity.d.ts.map +1 -1
- package/dist/commands/identity.js +15 -15
- package/dist/commands/identity.js.map +1 -1
- package/dist/commands/incidents.d.ts +3 -3
- package/dist/commands/incidents.d.ts.map +1 -1
- package/dist/commands/incidents.js +6 -6
- package/dist/commands/incidents.js.map +1 -1
- package/dist/commands/jobs.d.ts +4 -4
- package/dist/commands/jobs.d.ts.map +1 -1
- package/dist/commands/jobs.js +7 -7
- package/dist/commands/jobs.js.map +1 -1
- package/dist/commands/mcp-proxy.d.ts +1 -1
- package/dist/commands/mcp-proxy.d.ts.map +1 -1
- package/dist/commands/mcp-proxy.js +5 -9
- package/dist/commands/mcp-proxy.js.map +1 -1
- package/dist/commands/messages.d.ts +2 -2
- package/dist/commands/messages.d.ts.map +1 -1
- package/dist/commands/messages.js +4 -4
- package/dist/commands/messages.js.map +1 -1
- package/dist/commands/open.d.ts +4 -4
- package/dist/commands/open.d.ts.map +1 -1
- package/dist/commands/open.js +6 -6
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/plugins.d.ts +9 -9
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +2 -7
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/process-definitions.d.ts +2 -2
- package/dist/commands/process-definitions.d.ts.map +1 -1
- package/dist/commands/process-definitions.js +5 -5
- package/dist/commands/process-definitions.js.map +1 -1
- package/dist/commands/process-instances.d.ts +5 -5
- package/dist/commands/process-instances.d.ts.map +1 -1
- package/dist/commands/process-instances.js +8 -9
- package/dist/commands/process-instances.js.map +1 -1
- package/dist/commands/profiles.d.ts +4 -36
- package/dist/commands/profiles.d.ts.map +1 -1
- package/dist/commands/profiles.js +43 -41
- package/dist/commands/profiles.js.map +1 -1
- package/dist/commands/run.d.ts +2 -2
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +4 -4
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/search.d.ts +7 -7
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +9 -11
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/session.d.ts +4 -4
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +26 -5
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/topology.d.ts +1 -1
- package/dist/commands/topology.d.ts.map +1 -1
- package/dist/commands/topology.js +2 -2
- package/dist/commands/topology.js.map +1 -1
- package/dist/commands/user-tasks.d.ts +2 -2
- package/dist/commands/user-tasks.d.ts.map +1 -1
- package/dist/commands/user-tasks.js +5 -5
- package/dist/commands/user-tasks.js.map +1 -1
- package/dist/commands/variables.d.ts +1 -1
- package/dist/commands/variables.d.ts.map +1 -1
- package/dist/commands/variables.js +3 -3
- package/dist/commands/variables.js.map +1 -1
- package/dist/commands/watch.d.ts +2 -2
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +86 -19
- package/dist/commands/watch.js.map +1 -1
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js.map +1 -0
- package/dist/{config.d.ts → core/config.d.ts} +28 -2
- package/dist/core/config.d.ts.map +1 -0
- package/dist/{config.js → core/config.js} +61 -5
- package/dist/core/config.js.map +1 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/{runtime.js → core/runtime.js} +2 -2
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/update-check.d.ts.map +1 -0
- package/dist/core/update-check.js.map +1 -0
- package/dist/default-plugins/bpmn/README.md +12 -3
- package/dist/default-plugins/bpmn/c8ctl-plugin.js +7376 -108
- package/dist/default-plugins/bpmn/package.json +8 -1
- package/dist/default-plugins/cluster/c8ctl-plugin.js +66 -9
- package/dist/default-plugins/element-template/README.md +6 -3
- package/dist/default-plugins/element-template/c8ctl-plugin.js +10195 -229
- package/dist/default-plugins/element-template/docs/design.md +1 -1
- package/dist/default-plugins/element-template/package.json +11 -1
- package/dist/default-plugins/feel/c8ctl-plugin.js +14030 -584
- package/dist/default-plugins/feel/package.json +4 -1
- package/dist/{command-framework.d.ts → framework/command-framework.d.ts} +23 -9
- package/dist/framework/command-framework.d.ts.map +1 -0
- package/dist/{command-framework.js → framework/command-framework.js} +16 -29
- package/dist/framework/command-framework.js.map +1 -0
- package/dist/{command-registry.d.ts → framework/command-registry.d.ts} +35 -8
- package/dist/framework/command-registry.d.ts.map +1 -0
- package/dist/{command-registry.js → framework/command-registry.js} +74 -9
- package/dist/framework/command-registry.js.map +1 -0
- package/dist/{command-validation.d.ts → framework/command-validation.d.ts} +0 -14
- package/dist/framework/command-validation.d.ts.map +1 -0
- package/dist/{command-validation.js → framework/command-validation.js} +1 -34
- package/dist/framework/command-validation.js.map +1 -0
- package/dist/framework/index.d.ts +10 -0
- package/dist/framework/index.d.ts.map +1 -0
- package/dist/framework/index.js +16 -0
- package/dist/framework/index.js.map +1 -0
- package/dist/{plugin-loader.d.ts → framework/plugins/plugin-loader.d.ts} +30 -5
- package/dist/framework/plugins/plugin-loader.d.ts.map +1 -0
- package/dist/{plugin-loader.js → framework/plugins/plugin-loader.js} +26 -10
- package/dist/framework/plugins/plugin-loader.js.map +1 -0
- package/dist/framework/plugins/plugin-registry.d.ts.map +1 -0
- package/dist/{plugin-registry.js → framework/plugins/plugin-registry.js} +1 -1
- package/dist/framework/plugins/plugin-registry.js.map +1 -0
- package/dist/framework/plugins/plugin-version.d.ts.map +1 -0
- package/dist/framework/plugins/plugin-version.js.map +1 -0
- package/dist/{completion.d.ts → framework/ui/completion.d.ts} +2 -2
- package/dist/framework/ui/completion.d.ts.map +1 -0
- package/dist/{completion.js → framework/ui/completion.js} +7 -9
- package/dist/framework/ui/completion.js.map +1 -0
- package/dist/framework/ui/help.d.ts.map +1 -0
- package/dist/{help.js → framework/ui/help.js} +4 -4
- package/dist/framework/ui/help.js.map +1 -0
- package/dist/framework/ui/prompt.d.ts +132 -0
- package/dist/framework/ui/prompt.d.ts.map +1 -0
- package/dist/framework/ui/prompt.js +298 -0
- package/dist/framework/ui/prompt.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -20
- package/dist/index.js.map +1 -1
- package/dist/utils/command-local/deploy-version.d.ts +21 -0
- package/dist/utils/command-local/deploy-version.d.ts.map +1 -0
- package/dist/utils/command-local/deploy-version.js +31 -0
- package/dist/utils/command-local/deploy-version.js.map +1 -0
- package/dist/{mcp-proxy-helpers.d.ts → utils/command-local/mcp-proxy-helpers.d.ts} +1 -1
- package/dist/utils/command-local/mcp-proxy-helpers.d.ts.map +1 -0
- package/dist/{mcp-proxy-helpers.js → utils/command-local/mcp-proxy-helpers.js} +1 -1
- package/dist/utils/command-local/mcp-proxy-helpers.js.map +1 -0
- package/dist/utils/command-local/open-helpers.d.ts.map +1 -0
- package/dist/{open-helpers.js → utils/command-local/open-helpers.js} +2 -2
- package/dist/utils/command-local/open-helpers.js.map +1 -0
- package/dist/{search-helpers.d.ts → utils/command-local/search-helpers.d.ts} +1 -1
- package/dist/utils/command-local/search-helpers.d.ts.map +1 -0
- package/dist/utils/command-local/search-helpers.js.map +1 -0
- package/dist/utils/command-local/watch-constants.d.ts.map +1 -0
- package/dist/utils/command-local/watch-constants.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +16 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/shared/date-filter.d.ts.map +1 -0
- package/dist/utils/shared/date-filter.js.map +1 -0
- package/dist/{ignore.d.ts → utils/shared/ignore.d.ts} +19 -1
- package/dist/utils/shared/ignore.d.ts.map +1 -0
- package/dist/utils/shared/ignore.js +234 -0
- package/dist/utils/shared/ignore.js.map +1 -0
- package/dist/utils/shared/resource-extensions.d.ts.map +1 -0
- package/dist/utils/shared/resource-extensions.js.map +1 -0
- package/dist/utils/shared/validation.d.ts +23 -0
- package/dist/utils/shared/validation.d.ts.map +1 -0
- package/dist/utils/shared/validation.js +43 -0
- package/dist/utils/shared/validation.js.map +1 -0
- package/dist/vendor/bpmnlint.cjs +25907 -0
- package/package.json +12 -14
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/command-framework.d.ts.map +0 -1
- package/dist/command-framework.js.map +0 -1
- package/dist/command-registry.d.ts.map +0 -1
- package/dist/command-registry.js.map +0 -1
- package/dist/command-validation.d.ts.map +0 -1
- package/dist/command-validation.js.map +0 -1
- package/dist/commands/resource-extensions.d.ts.map +0 -1
- package/dist/commands/resource-extensions.js.map +0 -1
- package/dist/completion.d.ts.map +0 -1
- package/dist/completion.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/date-filter.d.ts.map +0 -1
- package/dist/date-filter.js.map +0 -1
- package/dist/default-plugins/bpmn/c8ctl-plugin.js.map +0 -1
- package/dist/default-plugins/bpmn/lint.js +0 -320
- package/dist/default-plugins/bpmn/lint.js.map +0 -1
- package/dist/default-plugins/element-template/c8ctl-plugin.js.map +0 -1
- package/dist/default-plugins/element-template/commands/apply.js +0 -336
- package/dist/default-plugins/element-template/commands/apply.js.map +0 -1
- package/dist/default-plugins/element-template/commands/get-properties.js +0 -344
- package/dist/default-plugins/element-template/commands/get-properties.js.map +0 -1
- package/dist/default-plugins/element-template/commands/get.js +0 -107
- package/dist/default-plugins/element-template/commands/get.js.map +0 -1
- package/dist/default-plugins/element-template/commands/info.js +0 -189
- package/dist/default-plugins/element-template/commands/info.js.map +0 -1
- package/dist/default-plugins/element-template/commands/search.js +0 -102
- package/dist/default-plugins/element-template/commands/search.js.map +0 -1
- package/dist/default-plugins/element-template/commands/sync.js +0 -36
- package/dist/default-plugins/element-template/commands/sync.js.map +0 -1
- package/dist/default-plugins/element-template/helpers.js +0 -429
- package/dist/default-plugins/element-template/helpers.js.map +0 -1
- package/dist/default-plugins/element-template/marketplace.js +0 -586
- package/dist/default-plugins/element-template/marketplace.js.map +0 -1
- package/dist/default-plugins/element-template/template-ref.js +0 -232
- package/dist/default-plugins/element-template/template-ref.js.map +0 -1
- package/dist/default-plugins/feel/c8ctl-plugin.js.map +0 -1
- package/dist/default-plugins/hello-world/README.md +0 -161
- package/dist/default-plugins/hello-world/c8ctl-plugin.js +0 -69
- package/dist/default-plugins/hello-world/package.json +0 -8
- package/dist/deployments.d.ts +0 -42
- package/dist/deployments.d.ts.map +0 -1
- package/dist/deployments.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/help.d.ts.map +0 -1
- package/dist/help.js.map +0 -1
- package/dist/ignore.d.ts.map +0 -1
- package/dist/ignore.js +0 -101
- package/dist/ignore.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/mcp-proxy-helpers.d.ts.map +0 -1
- package/dist/mcp-proxy-helpers.js.map +0 -1
- package/dist/open-helpers.d.ts.map +0 -1
- package/dist/open-helpers.js.map +0 -1
- package/dist/plugin-loader.d.ts.map +0 -1
- package/dist/plugin-loader.js.map +0 -1
- package/dist/plugin-registry.d.ts.map +0 -1
- package/dist/plugin-registry.js.map +0 -1
- package/dist/plugin-version.d.ts.map +0 -1
- package/dist/plugin-version.js.map +0 -1
- package/dist/runtime.d.ts.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/search-helpers.d.ts.map +0 -1
- package/dist/search-helpers.js.map +0 -1
- package/dist/update-check.d.ts.map +0 -1
- package/dist/update-check.js.map +0 -1
- package/dist/watch-constants.d.ts.map +0 -1
- package/dist/watch-constants.js.map +0 -1
- /package/dist/{client.d.ts → core/client.d.ts} +0 -0
- /package/dist/{client.js → core/client.js} +0 -0
- /package/dist/{errors.d.ts → core/errors.d.ts} +0 -0
- /package/dist/{errors.js → core/errors.js} +0 -0
- /package/dist/{logger.d.ts → core/logger.d.ts} +0 -0
- /package/dist/{logger.js → core/logger.js} +0 -0
- /package/dist/{runtime.d.ts → core/runtime.d.ts} +0 -0
- /package/dist/{update-check.d.ts → core/update-check.d.ts} +0 -0
- /package/dist/{update-check.js → core/update-check.js} +0 -0
- /package/dist/{plugin-registry.d.ts → framework/plugins/plugin-registry.d.ts} +0 -0
- /package/dist/{plugin-version.d.ts → framework/plugins/plugin-version.d.ts} +0 -0
- /package/dist/{plugin-version.js → framework/plugins/plugin-version.js} +0 -0
- /package/dist/{help.d.ts → framework/ui/help.d.ts} +0 -0
- /package/dist/{open-helpers.d.ts → utils/command-local/open-helpers.d.ts} +0 -0
- /package/dist/{search-helpers.js → utils/command-local/search-helpers.js} +0 -0
- /package/dist/{watch-constants.d.ts → utils/command-local/watch-constants.d.ts} +0 -0
- /package/dist/{watch-constants.js → utils/command-local/watch-constants.js} +0 -0
- /package/dist/{date-filter.d.ts → utils/shared/date-filter.d.ts} +0 -0
- /package/dist/{date-filter.js → utils/shared/date-filter.js} +0 -0
- /package/dist/{commands → utils/shared}/resource-extensions.d.ts +0 -0
- /package/dist/{commands → utils/shared}/resource-extensions.js +0 -0
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shared deployment helpers — resource collection, deployment execution,
|
|
3
|
+
* and process-application detection.
|
|
4
|
+
*
|
|
5
|
+
* Consumed by:
|
|
6
|
+
* - `src/commands/deploy.ts` (the `deployCommand` handler)
|
|
7
|
+
* - `src/commands/watch.ts` (change-triggered re-deploys)
|
|
3
8
|
*/
|
|
4
|
-
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
5
|
-
import { basename, dirname, extname, join, relative } from "node:path";
|
|
9
|
+
import { existsSync, readdirSync, readFileSync, realpathSync, statSync, } from "node:fs";
|
|
10
|
+
import { basename, dirname, extname, join, relative, resolve } from "node:path";
|
|
6
11
|
import { TenantId } from "@camunda8/orchestration-cluster-api";
|
|
7
|
-
import { createClient } from "
|
|
8
|
-
import {
|
|
9
|
-
import { ALL_DEPLOYABLE_EXTENSIONS, DEPLOYABLE_EXTENSIONS, } from "./commands/resource-extensions.js";
|
|
10
|
-
import { resolveTenantId } from "./config.js";
|
|
11
|
-
import { normalizeToError, SilentError } from "./errors.js";
|
|
12
|
-
import { isIgnored, loadIgnoreRules, resolveIgnoreBaseDir } from "./ignore.js";
|
|
13
|
-
import { getLogger, isRecord } from "./logger.js";
|
|
14
|
-
import { c8ctl } from "./runtime.js";
|
|
12
|
+
import { createClient, getLogger, isRecord, normalizeToError, resolveTenantId, SilentError, } from "../../core/index.js";
|
|
13
|
+
import { DEPLOYABLE_EXTENSIONS, isIgnored, loadDeployAlwaysRules, loadIgnoreRules, meetsMinExtensionVersion, resolveIgnoreBaseDir, } from "../../utils/index.js";
|
|
15
14
|
const PROCESS_APPLICATION_FILE = ".process-application";
|
|
16
15
|
/**
|
|
17
16
|
* Helper to output messages that respect JSON mode for Unix pipe compatibility
|
|
18
17
|
*/
|
|
19
|
-
function logMessage(message) {
|
|
20
|
-
if (
|
|
18
|
+
export function logMessage(message) {
|
|
19
|
+
if (getLogger().mode === "json") {
|
|
21
20
|
console.error(JSON.stringify({ type: "message", message }));
|
|
22
21
|
}
|
|
23
22
|
else {
|
|
@@ -29,13 +28,38 @@ function logMessage(message) {
|
|
|
29
28
|
* Shared between the dry-run preview and the execute path so the
|
|
30
29
|
* message stays consistent. See https://github.com/camunda/c8ctl/issues/350
|
|
31
30
|
*/
|
|
32
|
-
function logSkippedExtensions(skippedExtensions) {
|
|
31
|
+
export function logSkippedExtensions(skippedExtensions) {
|
|
33
32
|
if (skippedExtensions.size === 0)
|
|
34
33
|
return;
|
|
35
34
|
const exts = [...skippedExtensions].sort().join(", ");
|
|
36
35
|
logMessage(`Skipped files with extensions not in the allow-list (${exts}). ` +
|
|
37
36
|
`Use --extensions=<ext> to add specific types, or --all-extensions to include all server-supported types.`);
|
|
38
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Check whether the connected Camunda server supports extended file extensions.
|
|
40
|
+
* Returns `true` for 8.10+, `false` for older versions.
|
|
41
|
+
* Falls back to `false` on any error (network, auth, unparseable version)
|
|
42
|
+
* so unsupported resource types are not deployed to older clusters.
|
|
43
|
+
*/
|
|
44
|
+
export async function checkServerSupportsExtensions(client) {
|
|
45
|
+
const logger = getLogger();
|
|
46
|
+
try {
|
|
47
|
+
const topology = await client.getTopology();
|
|
48
|
+
const version = String(topology.gatewayVersion ?? "");
|
|
49
|
+
const result = meetsMinExtensionVersion(version);
|
|
50
|
+
if (result === null) {
|
|
51
|
+
logger.warn(`Could not parse server version "${version}" — assuming extended extensions are NOT supported.`);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
logger.warn("Could not reach the server to check its version (topology call failed).");
|
|
58
|
+
logger.warn("This can happen with OAuth/SaaS clusters before the first token is fetched, " +
|
|
59
|
+
"or if the server is not yet ready. Assuming extended extensions are NOT supported.");
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
39
63
|
/**
|
|
40
64
|
* Extract process/decision IDs from BPMN/DMN files to detect duplicates
|
|
41
65
|
*/
|
|
@@ -68,7 +92,12 @@ function isBuildingBlockFolder(path) {
|
|
|
68
92
|
*/
|
|
69
93
|
function hasProcessApplicationFile(dirPath) {
|
|
70
94
|
const paFilePath = join(dirPath, PROCESS_APPLICATION_FILE);
|
|
71
|
-
|
|
95
|
+
try {
|
|
96
|
+
return statSync(paFilePath).isFile();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
72
101
|
}
|
|
73
102
|
/**
|
|
74
103
|
* Find the root building block or process application folder by traversing up the path
|
|
@@ -78,11 +107,6 @@ function findGroupRoot(filePath, basePath) {
|
|
|
78
107
|
let currentDir = dirname(filePath);
|
|
79
108
|
// Traverse up the directory tree until we reach or go outside basePath
|
|
80
109
|
while (true) {
|
|
81
|
-
// Check if we've gone outside the basePath
|
|
82
|
-
const rel = relative(basePath, currentDir);
|
|
83
|
-
if (rel.startsWith("..") || rel === "") {
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
110
|
// Check if this directory is a building block
|
|
87
111
|
if (isBuildingBlockFolder(currentDir)) {
|
|
88
112
|
return { type: "bb", root: currentDir };
|
|
@@ -91,6 +115,11 @@ function findGroupRoot(filePath, basePath) {
|
|
|
91
115
|
if (hasProcessApplicationFile(currentDir)) {
|
|
92
116
|
return { type: "pa", root: currentDir };
|
|
93
117
|
}
|
|
118
|
+
// Check if we've reached or gone outside the basePath
|
|
119
|
+
const rel = relative(basePath, currentDir);
|
|
120
|
+
if (rel.startsWith("..") || rel === "") {
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
94
123
|
// Move up one level
|
|
95
124
|
const parentDir = dirname(currentDir);
|
|
96
125
|
if (parentDir === currentDir)
|
|
@@ -99,6 +128,33 @@ function findGroupRoot(filePath, basePath) {
|
|
|
99
128
|
}
|
|
100
129
|
return { type: null, root: null };
|
|
101
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Walk up from `startDir` looking for a `.process-application` marker
|
|
133
|
+
* file. Returns the directory that contains the marker, or `null` if
|
|
134
|
+
* none is found before reaching the filesystem root.
|
|
135
|
+
*
|
|
136
|
+
* `startDir` may be a file path — the walk starts from its parent
|
|
137
|
+
* directory in that case (the initial `hasProcessApplicationFile` call
|
|
138
|
+
* harmlessly returns false for non-directories).
|
|
139
|
+
*
|
|
140
|
+
* Unlike `findGroupRoot()` (which tags individual files for display),
|
|
141
|
+
* this function determines the *deploy scope*: when a PA root is found,
|
|
142
|
+
* `collectResourcesForPaths` expands the input to the PA root so that
|
|
143
|
+
* the entire application is deployed.
|
|
144
|
+
*/
|
|
145
|
+
export function findProcessApplicationRoot(startDir) {
|
|
146
|
+
let currentDir = resolve(startDir);
|
|
147
|
+
while (true) {
|
|
148
|
+
if (hasProcessApplicationFile(currentDir)) {
|
|
149
|
+
return currentDir;
|
|
150
|
+
}
|
|
151
|
+
const parentDir = dirname(currentDir);
|
|
152
|
+
if (parentDir === currentDir)
|
|
153
|
+
break; // Reached filesystem root
|
|
154
|
+
currentDir = parentDir;
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
102
158
|
/**
|
|
103
159
|
* Recursively collect resource files from a directory.
|
|
104
160
|
*
|
|
@@ -109,15 +165,16 @@ function findGroupRoot(filePath, basePath) {
|
|
|
109
165
|
* @param skippedExtensions - Mutable set that accumulates extensions
|
|
110
166
|
* skipped during directory walks, so the caller can log them.
|
|
111
167
|
*/
|
|
112
|
-
function collectResourceFiles(dirPath, collected = [], basePath, ig, ignoreBaseDir, force, extensionList, skippedExtensions) {
|
|
168
|
+
function collectResourceFiles(dirPath, collected = [], basePath, ig, ignoreBaseDir, force, extensionList, skippedExtensions, skippedFiles, deployAlways) {
|
|
113
169
|
if (!existsSync(dirPath)) {
|
|
114
170
|
return collected;
|
|
115
171
|
}
|
|
116
|
-
|
|
172
|
+
const stat = statSync(dirPath);
|
|
173
|
+
// Set basePath to a directory on first call — when the initial input
|
|
174
|
+
// is a file, use its parent so findGroupRoot can walk up correctly.
|
|
117
175
|
if (!basePath) {
|
|
118
|
-
basePath = dirPath;
|
|
176
|
+
basePath = stat.isFile() ? dirname(dirPath) : dirPath;
|
|
119
177
|
}
|
|
120
|
-
const stat = statSync(dirPath);
|
|
121
178
|
if (stat.isFile()) {
|
|
122
179
|
if (ig && ignoreBaseDir && isIgnored(ig, dirPath, ignoreBaseDir)) {
|
|
123
180
|
return collected;
|
|
@@ -176,10 +233,21 @@ function collectResourceFiles(dirPath, collected = [], basePath, ig, ignoreBaseD
|
|
|
176
233
|
if (!force &&
|
|
177
234
|
extensionList &&
|
|
178
235
|
!extensionList.includes(extname(fullPath))) {
|
|
236
|
+
// Check deploy-always negation rules from .c8ignore
|
|
237
|
+
if (deployAlways &&
|
|
238
|
+
ignoreBaseDir &&
|
|
239
|
+
isIgnored(deployAlways, fullPath, ignoreBaseDir)) {
|
|
240
|
+
// File matches a !path negation — include it
|
|
241
|
+
files.push(fullPath);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
179
244
|
if (skippedExtensions) {
|
|
180
245
|
const ext = extname(fullPath);
|
|
181
246
|
skippedExtensions.add(ext || "<no extension>");
|
|
182
247
|
}
|
|
248
|
+
if (skippedFiles) {
|
|
249
|
+
skippedFiles.push(fullPath);
|
|
250
|
+
}
|
|
183
251
|
return;
|
|
184
252
|
}
|
|
185
253
|
files.push(fullPath);
|
|
@@ -199,11 +267,11 @@ function collectResourceFiles(dirPath, collected = [], basePath, ig, ignoreBaseD
|
|
|
199
267
|
});
|
|
200
268
|
// Process building block folders first (prioritized)
|
|
201
269
|
bbFolders.forEach((bbFolder) => {
|
|
202
|
-
collectResourceFiles(bbFolder, collected, basePath, ig, ignoreBaseDir, force, extensionList, skippedExtensions);
|
|
270
|
+
collectResourceFiles(bbFolder, collected, basePath, ig, ignoreBaseDir, force, extensionList, skippedExtensions, skippedFiles, deployAlways);
|
|
203
271
|
});
|
|
204
272
|
// Then process regular folders
|
|
205
273
|
regularFolders.forEach((regularFolder) => {
|
|
206
|
-
collectResourceFiles(regularFolder, collected, basePath, ig, ignoreBaseDir, force, extensionList, skippedExtensions);
|
|
274
|
+
collectResourceFiles(regularFolder, collected, basePath, ig, ignoreBaseDir, force, extensionList, skippedExtensions, skippedFiles, deployAlways);
|
|
207
275
|
});
|
|
208
276
|
}
|
|
209
277
|
return collected;
|
|
@@ -235,32 +303,118 @@ function findDuplicateDefinitionIds(resources) {
|
|
|
235
303
|
* @param extensionList - Active allow-list for directory discovery.
|
|
236
304
|
* Defaults to `DEPLOYABLE_EXTENSIONS` (.bpmn, .dmn, .form).
|
|
237
305
|
*/
|
|
238
|
-
function collectResourcesForPaths(paths, force, extensionList = DEPLOYABLE_EXTENSIONS
|
|
306
|
+
export function collectResourcesForPaths(paths, force, extensionList = DEPLOYABLE_EXTENSIONS,
|
|
307
|
+
/** When false, skip loading deploy-always negation rules from .c8ignore.
|
|
308
|
+
* Used to suppress them on servers <8.10 that don't support extended extensions. */
|
|
309
|
+
loadDeployAlways = true) {
|
|
239
310
|
if (paths.length === 0) {
|
|
240
311
|
throw new Error("No paths provided. Use: c8 deploy <path> or c8 deploy (for current directory)");
|
|
241
312
|
}
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
|
|
313
|
+
// ── Process-application auto-detection (#227) ──────────────────────
|
|
314
|
+
// For each directory path, walk up looking for a .process-application
|
|
315
|
+
// marker. If found, expand to the PA root so the entire application
|
|
316
|
+
// is deployed — matching Desktop Modeler behaviour.
|
|
317
|
+
// File paths are NOT expanded so that watch-mode single-file deploys
|
|
318
|
+
// remain scoped to the changed file.
|
|
319
|
+
const effectivePaths = [];
|
|
320
|
+
const seenRoots = new Set();
|
|
321
|
+
for (const p of paths) {
|
|
322
|
+
const abs = resolve(p);
|
|
323
|
+
let isFile = false;
|
|
324
|
+
try {
|
|
325
|
+
isFile = statSync(abs).isFile();
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
// Path does not exist — skip PA detection and keep the
|
|
329
|
+
// absolute path so collectResourceFiles (which silently
|
|
330
|
+
// skips missing paths) falls through to the "No deployable
|
|
331
|
+
// files found" guard.
|
|
332
|
+
effectivePaths.push(abs);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (isFile) {
|
|
336
|
+
effectivePaths.push(abs);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const paRoot = findProcessApplicationRoot(abs);
|
|
340
|
+
if (paRoot) {
|
|
341
|
+
// Deduplicate: multiple input dirs inside the same PA should
|
|
342
|
+
// only trigger one resource walk from the PA root. Use
|
|
343
|
+
// realpathSync for the dedup key to handle symlinks/case.
|
|
344
|
+
let canonical = paRoot;
|
|
345
|
+
try {
|
|
346
|
+
canonical = realpathSync(paRoot);
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
// Best-effort fallback.
|
|
350
|
+
}
|
|
351
|
+
if (!seenRoots.has(canonical)) {
|
|
352
|
+
seenRoots.add(canonical);
|
|
353
|
+
effectivePaths.push(paRoot);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
effectivePaths.push(abs);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// Load .c8ignore rules from the effective target directory (which may
|
|
361
|
+
// be the PA root) so that `c8 deploy <target>` picks up the .c8ignore
|
|
362
|
+
// inside the target. (#258)
|
|
363
|
+
const ignoreBaseDir = resolveIgnoreBaseDir(effectivePaths);
|
|
245
364
|
const ig = loadIgnoreRules(ignoreBaseDir);
|
|
365
|
+
// Load !path negation patterns from .c8ignore. Files matching a
|
|
366
|
+
// negation bypass extension filtering ("deploy them always").
|
|
367
|
+
// Skipped on servers <8.10 where extended extensions aren't supported.
|
|
368
|
+
const deployAlways = loadDeployAlways
|
|
369
|
+
? loadDeployAlwaysRules(ignoreBaseDir)
|
|
370
|
+
: null;
|
|
246
371
|
const resources = [];
|
|
247
372
|
const skippedExtensions = new Set();
|
|
248
|
-
|
|
249
|
-
|
|
373
|
+
const skippedFiles = [];
|
|
374
|
+
effectivePaths.forEach((path) => {
|
|
375
|
+
collectResourceFiles(path, resources, undefined, ig, ignoreBaseDir, force, extensionList, skippedExtensions, skippedFiles, deployAlways ?? undefined);
|
|
250
376
|
});
|
|
251
|
-
|
|
377
|
+
// Deduplicate resources by canonical path — can happen when an explicit
|
|
378
|
+
// file path is also covered by a PA-root or scoped-directory walk, or
|
|
379
|
+
// when the same file is reachable via symlinks. The canonical path is
|
|
380
|
+
// used only as the dedup key; the original path/name are preserved for
|
|
381
|
+
// display and relative-path calculations.
|
|
382
|
+
const seen = new Set();
|
|
383
|
+
const deduped = [];
|
|
384
|
+
for (const r of resources) {
|
|
385
|
+
let canonical = r.path;
|
|
386
|
+
try {
|
|
387
|
+
canonical = realpathSync(r.path);
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
// Best-effort: fall back to the original path if realpath
|
|
391
|
+
// fails (e.g. broken symlink).
|
|
392
|
+
}
|
|
393
|
+
if (!seen.has(canonical)) {
|
|
394
|
+
seen.add(canonical);
|
|
395
|
+
deduped.push(r);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (deduped.length === 0) {
|
|
252
399
|
logSkippedExtensions(skippedExtensions);
|
|
253
|
-
throw new Error(
|
|
400
|
+
throw new Error(skippedFiles.length > 0
|
|
401
|
+
? `No files with allowed extensions found. ${skippedFiles.length} file(s) were skipped (${[...skippedExtensions].sort().join(", ")}). Use --force to include all files, or --extensions to expand the allow-list.`
|
|
402
|
+
: "No deployable files found in the specified paths");
|
|
254
403
|
}
|
|
255
|
-
return {
|
|
404
|
+
return {
|
|
405
|
+
resources: deduped,
|
|
406
|
+
skippedExtensions,
|
|
407
|
+
skippedFiles,
|
|
408
|
+
effectivePaths,
|
|
409
|
+
};
|
|
256
410
|
}
|
|
257
411
|
/**
|
|
258
412
|
* Internal helper: deploy the given paths to the cluster and render the
|
|
259
413
|
* result table. Used by `deployCommand` (the standard CLI entry point)
|
|
260
414
|
* and by `watchCommand` (for change-triggered re-deploys).
|
|
261
415
|
*
|
|
262
|
-
* Does NOT consult
|
|
263
|
-
* `deployCommand` handler so the
|
|
416
|
+
* Does NOT consult dry-run state — dry-run handling lives in the
|
|
417
|
+
* `deployCommand` handler so the context's `ctx.dryRun()` helper owns
|
|
264
418
|
* preview emission. Watch never triggers a dry-run, so this split also
|
|
265
419
|
* removes a footgun where a stale dry-run flag could suppress a watch
|
|
266
420
|
* deploy.
|
|
@@ -273,15 +427,16 @@ export async function deployResources(paths, options) {
|
|
|
273
427
|
// straight to the framework's `handleCommandError`. Only the actual
|
|
274
428
|
// HTTP deploy call (further down) is wrapped in a catch that routes
|
|
275
429
|
// through `handleDeploymentError` for rich Problem-Detail rendering.
|
|
276
|
-
const { resources, skippedExtensions } = collectResourcesForPaths(paths, options.force, options.extensionList ?? DEPLOYABLE_EXTENSIONS);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
//
|
|
281
|
-
|
|
430
|
+
const { resources, skippedExtensions, effectivePaths } = collectResourcesForPaths(paths, options.force, options.extensionList ?? DEPLOYABLE_EXTENSIONS, options.loadDeployAlways ?? true);
|
|
431
|
+
if (!options.suppressSkippedLog) {
|
|
432
|
+
logSkippedExtensions(skippedExtensions);
|
|
433
|
+
}
|
|
434
|
+
// Use the effective paths (which may have been expanded to a PA root)
|
|
435
|
+
// for relative path calculation so display paths make sense.
|
|
436
|
+
const basePaths = effectivePaths;
|
|
282
437
|
const client = createClient(options.profile);
|
|
283
438
|
// Calculate relative paths for display
|
|
284
|
-
const basePath = basePaths.length === 1 ? basePaths[0] : process.cwd();
|
|
439
|
+
const basePath = options.basePath ?? (basePaths.length === 1 ? basePaths[0] : process.cwd());
|
|
285
440
|
resources.forEach((r) => {
|
|
286
441
|
r.relativePath = relative(basePath, r.path) || r.name;
|
|
287
442
|
});
|
|
@@ -341,7 +496,19 @@ export async function deployResources(paths, options) {
|
|
|
341
496
|
// Create a mapping from definition ID to resource file for later reference
|
|
342
497
|
const definitionIdToResource = new Map();
|
|
343
498
|
const formNameToResource = new Map();
|
|
499
|
+
// Map basename → ResourceFile[]: multiple files can share a basename
|
|
500
|
+
// across directories (e.g. sub-a/model.dmn, sub-b/model.dmn). When
|
|
501
|
+
// the API returns a resourceName, we pop the first matching entry so
|
|
502
|
+
// each response record resolves to a distinct local file.
|
|
503
|
+
const resourcesByName = new Map();
|
|
344
504
|
resources.forEach((r) => {
|
|
505
|
+
const existing = resourcesByName.get(r.name);
|
|
506
|
+
if (existing) {
|
|
507
|
+
existing.push(r);
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
resourcesByName.set(r.name, [r]);
|
|
511
|
+
}
|
|
345
512
|
const ext = extname(r.path);
|
|
346
513
|
if (ext === ".bpmn" || ext === ".dmn") {
|
|
347
514
|
const defId = extractDefinitionId(r.content, ext);
|
|
@@ -350,11 +517,28 @@ export async function deployResources(paths, options) {
|
|
|
350
517
|
}
|
|
351
518
|
}
|
|
352
519
|
else if (ext === ".form") {
|
|
353
|
-
// Forms are matched by
|
|
354
|
-
|
|
520
|
+
// Forms are matched by their internal ID from the JSON content.
|
|
521
|
+
// Fall back to filename (without extension) if the ID can't be parsed.
|
|
522
|
+
let formId = basename(r.name, ".form");
|
|
523
|
+
try {
|
|
524
|
+
const parsed = JSON.parse(r.content.toString("utf-8"));
|
|
525
|
+
if (isRecord(parsed) && typeof parsed.id === "string") {
|
|
526
|
+
formId = parsed.id;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
catch {
|
|
530
|
+
// Not valid JSON — use filename
|
|
531
|
+
}
|
|
355
532
|
formNameToResource.set(formId, r);
|
|
356
533
|
}
|
|
357
534
|
});
|
|
535
|
+
/** Pop the first resource with a matching basename, or return undefined. */
|
|
536
|
+
function popResourceByName(name) {
|
|
537
|
+
const bucket = resourcesByName.get(name);
|
|
538
|
+
if (!bucket || bucket.length === 0)
|
|
539
|
+
return undefined;
|
|
540
|
+
return bucket.shift();
|
|
541
|
+
}
|
|
358
542
|
// ─── API call ────────────────────────────────────────────────────────
|
|
359
543
|
// Only this section is wrapped in a catch that routes through
|
|
360
544
|
// `handleDeploymentError`. Pre-API errors above bubble to the
|
|
@@ -408,7 +592,7 @@ export async function deployResources(paths, options) {
|
|
|
408
592
|
if (options.signal?.aborted) {
|
|
409
593
|
return;
|
|
410
594
|
}
|
|
411
|
-
handleDeploymentError(error, resources, logger, options.continueOnError, options.continueOnUserError);
|
|
595
|
+
handleDeploymentError(error, resources, logger, options.continueOnError, options.continueOnUserError, options.verbose === true);
|
|
412
596
|
// `handleDeploymentError` either throws (terminal) or returns
|
|
413
597
|
// (continue-on-error). On the continue path, skip the success
|
|
414
598
|
// render below — there's no result to render.
|
|
@@ -417,27 +601,80 @@ export async function deployResources(paths, options) {
|
|
|
417
601
|
options.signal?.removeEventListener("abort", onAbort);
|
|
418
602
|
logger.success("Deployment successful", result.deploymentKey.toString());
|
|
419
603
|
// Normalize all deployed resources into a common structure
|
|
604
|
+
const knownResources = new Set();
|
|
420
605
|
const allResources = [
|
|
421
|
-
...result.processes.map((proc) =>
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
606
|
+
...result.processes.map((proc) => {
|
|
607
|
+
const resource = definitionIdToResource.get(proc.processDefinitionId);
|
|
608
|
+
if (resource)
|
|
609
|
+
knownResources.add(resource);
|
|
610
|
+
return {
|
|
611
|
+
type: "Process",
|
|
612
|
+
id: proc.processDefinitionId,
|
|
613
|
+
version: proc.processDefinitionVersion,
|
|
614
|
+
key: proc.processDefinitionKey.toString(),
|
|
615
|
+
resource,
|
|
616
|
+
};
|
|
617
|
+
}),
|
|
618
|
+
...result.decisions.map((dec) => {
|
|
619
|
+
const resource = definitionIdToResource.get(dec.decisionDefinitionId || "");
|
|
620
|
+
if (resource)
|
|
621
|
+
knownResources.add(resource);
|
|
622
|
+
return {
|
|
623
|
+
type: "Decision",
|
|
624
|
+
id: dec.decisionDefinitionId || "-",
|
|
625
|
+
version: dec.version ?? "-",
|
|
626
|
+
key: dec.decisionDefinitionKey?.toString() || "-",
|
|
627
|
+
resource,
|
|
628
|
+
};
|
|
629
|
+
}),
|
|
630
|
+
...result.decisionRequirements.map((dr) => {
|
|
631
|
+
const resource = popResourceByName(dr.resourceName || "");
|
|
632
|
+
if (resource)
|
|
633
|
+
knownResources.add(resource);
|
|
634
|
+
return {
|
|
635
|
+
type: "Decision Requirements",
|
|
636
|
+
id: dr.decisionRequirementsId || "-",
|
|
637
|
+
version: dr.version ?? "-",
|
|
638
|
+
key: dr.decisionRequirementsKey?.toString() || "-",
|
|
639
|
+
resource,
|
|
640
|
+
};
|
|
641
|
+
}),
|
|
642
|
+
...result.forms.map((form) => {
|
|
643
|
+
const resource = formNameToResource.get(form.formId || "");
|
|
644
|
+
if (resource)
|
|
645
|
+
knownResources.add(resource);
|
|
646
|
+
return {
|
|
647
|
+
type: "Form",
|
|
648
|
+
id: form.formId || "-",
|
|
649
|
+
version: form.version ?? "-",
|
|
650
|
+
key: form.formKey?.toString() || "-",
|
|
651
|
+
resource,
|
|
652
|
+
};
|
|
653
|
+
}),
|
|
654
|
+
// Generic resources (not processes, decisions, or forms)
|
|
655
|
+
// are returned in the `resources` array by 8.10+.
|
|
656
|
+
...result.resources.map((res) => {
|
|
657
|
+
const resource = popResourceByName(res.resourceName || "");
|
|
658
|
+
if (resource)
|
|
659
|
+
knownResources.add(resource);
|
|
660
|
+
return {
|
|
661
|
+
type: "Resource",
|
|
662
|
+
id: res.resourceId || "-",
|
|
663
|
+
version: res.version ?? "-",
|
|
664
|
+
key: res.resourceKey?.toString() || "-",
|
|
665
|
+
resource,
|
|
666
|
+
};
|
|
667
|
+
}),
|
|
668
|
+
// Supplementary resources not returned in any response array.
|
|
669
|
+
// Show them in the table so the user knows they were deployed.
|
|
670
|
+
...resources
|
|
671
|
+
.filter((r) => !knownResources.has(r))
|
|
672
|
+
.map((r) => ({
|
|
673
|
+
type: "Resource",
|
|
674
|
+
id: "-",
|
|
675
|
+
version: "-",
|
|
676
|
+
key: "-",
|
|
677
|
+
resource: r,
|
|
441
678
|
})),
|
|
442
679
|
];
|
|
443
680
|
const tableData = allResources.map(({ type, id, version, key, resource }) => {
|
|
@@ -479,13 +716,13 @@ export async function deployResources(paths, options) {
|
|
|
479
716
|
/**
|
|
480
717
|
* Format and display deployment errors with actionable guidance
|
|
481
718
|
*/
|
|
482
|
-
function handleDeploymentError(error, resources, logger, continueOnError, continueOnUserError) {
|
|
719
|
+
function handleDeploymentError(error, resources, logger, continueOnError, continueOnUserError, verbose) {
|
|
483
720
|
// Extract problem title early to determine whether this is a user-fixable error
|
|
484
721
|
const raw = isRecord(error) ? error : {};
|
|
485
722
|
const problemTitle = typeof raw.title === "string" ? raw.title : undefined;
|
|
486
723
|
const isUserFixable = problemTitle === "INVALID_ARGUMENT";
|
|
487
724
|
const shouldContinue = continueOnError || (continueOnUserError && isUserFixable);
|
|
488
|
-
if (
|
|
725
|
+
if (verbose) {
|
|
489
726
|
if (shouldContinue) {
|
|
490
727
|
throw error;
|
|
491
728
|
}
|
|
@@ -645,89 +882,4 @@ function printDeploymentHints(title, detail, status, resources) {
|
|
|
645
882
|
logMessage(h);
|
|
646
883
|
});
|
|
647
884
|
}
|
|
648
|
-
|
|
649
|
-
/**
|
|
650
|
-
* Resolve the effective extension allow-list from the deploy flags.
|
|
651
|
-
*
|
|
652
|
-
* Priority: --force (no filtering) > --all-extensions > --extensions > default
|
|
653
|
-
*
|
|
654
|
-
* When `--extensions` is provided, the custom list is *merged* with the
|
|
655
|
-
* default (.bpmn, .dmn, .form) so users add to the baseline rather than
|
|
656
|
-
* replacing it.
|
|
657
|
-
*/
|
|
658
|
-
function resolveExtensionList(flags) {
|
|
659
|
-
// When --force is set the allow-list is irrelevant — downstream code
|
|
660
|
-
// skips filtering entirely. Return the default so callers always get a
|
|
661
|
-
// valid list, but the value is never consulted.
|
|
662
|
-
if (flags.force)
|
|
663
|
-
return DEPLOYABLE_EXTENSIONS;
|
|
664
|
-
// --all-extensions: use the full server-supported list
|
|
665
|
-
if (flags["all-extensions"])
|
|
666
|
-
return ALL_DEPLOYABLE_EXTENSIONS;
|
|
667
|
-
// --extensions: merge custom extensions with the default set
|
|
668
|
-
if (flags.extensions && String(flags.extensions).trim()) {
|
|
669
|
-
const custom = String(flags.extensions)
|
|
670
|
-
.split(",")
|
|
671
|
-
.map((e) => e.trim())
|
|
672
|
-
.filter(Boolean)
|
|
673
|
-
.map((e) => (e.startsWith(".") ? e : `.${e}`));
|
|
674
|
-
const merged = [...new Set([...DEPLOYABLE_EXTENSIONS, ...custom])];
|
|
675
|
-
return merged;
|
|
676
|
-
}
|
|
677
|
-
return DEPLOYABLE_EXTENSIONS;
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Side-effectful: collects files, validates, deploys, and renders its own
|
|
681
|
-
* table output.
|
|
682
|
-
*
|
|
683
|
-
* The body lives directly in the handler (per #288): argument-shape
|
|
684
|
-
* resolution, dry-run preview via the framework's `dryRun()` helper,
|
|
685
|
-
* and the call into the shared `deployResources` helper that watch also
|
|
686
|
-
* uses for change-triggered re-deploys.
|
|
687
|
-
*/
|
|
688
|
-
export const deployCommand = defineCommand("deploy", "", async (ctx, flags) => {
|
|
689
|
-
// Argument shape: `c8 deploy [path...]`. With no positional, default
|
|
690
|
-
// to cwd. Pinned by tests/unit/deploy-behaviour.test.ts.
|
|
691
|
-
const paths = ctx.resource
|
|
692
|
-
? [ctx.resource, ...ctx.positionals]
|
|
693
|
-
: ctx.positionals.length > 0
|
|
694
|
-
? ctx.positionals
|
|
695
|
-
: ["."];
|
|
696
|
-
// Resolve the active extension allow-list from flags.
|
|
697
|
-
// Priority: --force (no filtering) > --all-extensions > --extensions > default
|
|
698
|
-
const extensionList = resolveExtensionList(flags);
|
|
699
|
-
// Dry-run preview. Collect resources first so the preview body
|
|
700
|
-
// reflects what would actually be sent — and so the empty-paths /
|
|
701
|
-
// no-files guards still surface as thrown errors before we emit.
|
|
702
|
-
// Uses `ctx.dryRun` and `ctx.tenantId` from the framework rather
|
|
703
|
-
// than reaching into the global runtime/config layer.
|
|
704
|
-
if (ctx.dryRun) {
|
|
705
|
-
const { resources: previewResources, skippedExtensions } = collectResourcesForPaths(paths, flags.force, extensionList);
|
|
706
|
-
logSkippedExtensions(skippedExtensions);
|
|
707
|
-
const dr = dryRun({
|
|
708
|
-
command: "deploy",
|
|
709
|
-
method: "POST",
|
|
710
|
-
endpoint: "/deployments",
|
|
711
|
-
profile: ctx.profile,
|
|
712
|
-
body: {
|
|
713
|
-
tenantId: ctx.tenantId,
|
|
714
|
-
resources: previewResources.map((r) => ({ name: r.name })),
|
|
715
|
-
},
|
|
716
|
-
});
|
|
717
|
-
if (dr)
|
|
718
|
-
return dr;
|
|
719
|
-
}
|
|
720
|
-
// Execute path: only reached when not in dry-run mode (the branch
|
|
721
|
-
// above returns early). `deployResources` runs its own
|
|
722
|
-
// `collectResourcesForPaths` internally and renders the success
|
|
723
|
-
// table. Keeping the helper self-contained avoids threading
|
|
724
|
-
// pre-collected state between the handler and the shared helper
|
|
725
|
-
// used by `watch`.
|
|
726
|
-
await deployResources(paths, {
|
|
727
|
-
profile: ctx.profile,
|
|
728
|
-
force: flags.force,
|
|
729
|
-
extensionList,
|
|
730
|
-
});
|
|
731
|
-
return { kind: "none" };
|
|
732
|
-
});
|
|
733
|
-
//# sourceMappingURL=deployments.js.map
|
|
885
|
+
//# sourceMappingURL=deploy-helpers.js.map
|