@salesforce/afv-skills 1.59.0 → 1.60.0
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/package.json +1 -1
- package/skills/agentforce-architecture-analyze/SKILL.md +66 -17
- package/skills/agentforce-architecture-analyze/assets/cli/show_access_token.yaml +4 -7
- package/skills/agentforce-architecture-analyze/references/contract.json +1 -1
- package/skills/agentforce-architecture-analyze/scripts/emit_env.py +2 -2
- package/skills/agentforce-architecture-analyze/scripts/main.py +40 -44
- package/skills/agentforce-architecture-analyze/scripts/rest_client.py +11 -3
- package/skills/agentforce-architecture-analyze/scripts/sf_cli.py +77 -10
- package/skills/agentforce-architecture-analyze/scripts/tests/test_end_to_end_fixture.py +1 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_flow_children_inflation.py +1 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_main_pipeline.py +53 -2
- package/skills/agentforce-architecture-analyze/scripts/tests/test_resolve_creds.py +184 -36
- package/skills/agentforce-architecture-analyze/scripts/tests/test_rest_client.py +17 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_sf_cli.py +165 -11
- package/skills/agentforce-architecture-analyze/scripts/tests/test_skill_md_pipeline_block.py +319 -0
- package/skills/agentforce-d360-analyze/SKILL.md +28 -10
- package/skills/agentforce-d360-analyze/scripts/dc.py +200 -50
- package/skills/agentforce-d360-analyze/scripts/discover_sessions.py +10 -6
- package/skills/agentforce-d360-analyze/scripts/fetch_dc.py +22 -6
- package/skills/agentforce-d360-analyze/scripts/resolve_session.py +21 -13
- package/skills/agentforce-d360-analyze/scripts/tests/test_dc_and_resolve_session.py +298 -76
- package/skills/agentforce-d360-analyze/scripts/tests/test_default_target_org.py +432 -0
- package/skills/agentforce-d360-analyze/scripts/tests/test_discover_sessions.py +1 -1
- package/skills/agentforce-d360-analyze/scripts/tests/test_resolve_session_main.py +9 -3
- package/skills/agentforce-d360-analyze/scripts/tests/test_skill_md_prefix_block.py +176 -0
- package/skills/consumer-goods-accruals-datakit-deploy/SKILL.md +17 -27
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/setup.js +7 -17
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js +47 -63
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js +10 -13
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/02-replace-org-id.js +46 -46
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/03-deploy-metadata.js +4 -21
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/06-create-dataspace.js +58 -82
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/07-deploy-accruals-reports.js +16 -315
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/08-deploy-ui.js +9 -24
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/09-completion.js +44 -44
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/utils.js +11 -63
- package/skills/consumer-goods-rtr-datacloud-export-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-dashboard-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-datakit-deploy/SKILL.md +2 -1
- package/skills/data360-schema-get/SKILL.md +3 -3
- package/skills/design-systems-slds-validate/references/report-format.md +1 -1
- package/skills/dx-org-manage/SKILL.md +1 -0
- package/skills/dx-org-shape-manage/SKILL.md +1 -0
- package/skills/dx-org-snapshot-manage/SKILL.md +172 -0
- package/skills/dx-org-snapshot-manage/examples/create_error_output.json +16 -0
- package/skills/dx-org-snapshot-manage/examples/create_success_output.json +19 -0
- package/skills/dx-org-snapshot-manage/examples/delete_output.json +9 -0
- package/skills/dx-org-snapshot-manage/examples/get_output.json +19 -0
- package/skills/dx-org-snapshot-manage/examples/list_output.json +36 -0
- package/skills/dx-org-snapshot-manage/references/cli_flags.md +179 -0
- package/skills/dx-org-snapshot-manage/references/snapshot_usage.md +55 -0
- package/skills/dx-org-trial-expiration-check/SKILL.md +1 -1
- package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +2 -2
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +7 -5
- package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +11 -11
- package/skills/experience-content-media-image-generate/SKILL.md +83 -0
- package/skills/experience-content-media-image-generate/scripts/download-image.sh +84 -0
- package/skills/external-diagram-mermaid-generate/SKILL.md +12 -12
- package/skills/field-service-data-capture-migrate/references/component-mapping.md +1 -1
- package/skills/field-service-data-capture-migrate/references/fsm-dc-capability-catalog.md +1 -2
- package/skills/field-service-data-capture-migrate/references/known-deploy-errors.md +1 -0
- package/skills/field-service-data-capture-migrate/references/transformer-rules.md +1 -1
- package/skills/field-service-data-capture-migrate/scripts/transform_flow.py +12 -1
- package/skills/field-service-data-capture-migrate/scripts/vendor/build_flow.py +4 -1
- package/skills/field-service-setup-orchestrator-get/SKILL.md +0 -1
- package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +233 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/accounting-setup.md +117 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/billing-rules-config.md +237 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/billing-settings.md +271 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/demo-policy-config.md +138 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/org-defaults.md +64 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/permissions-config.md +226 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/prerequisites.md +142 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +3 -2
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +3 -3
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +68 -45
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +17 -18
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +16 -3
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +16 -13
- package/skills/marketing-message-test/SKILL.md +194 -0
- package/skills/marketing-message-test/references/api-contract.md +333 -0
- package/skills/omnistudio-callable-apex-generate/SKILL.md +3 -3
- package/skills/omnistudio-datamapper-generate/SKILL.md +6 -6
- package/skills/omnistudio-datapacks-deploy/SKILL.md +11 -11
- package/skills/omnistudio-dependencies-analyze/SKILL.md +5 -5
- package/skills/omnistudio-epc-catalog-generate/SKILL.md +6 -6
- package/skills/omnistudio-flexcard-generate/SKILL.md +6 -6
- package/skills/omnistudio-integration-procedure-generate/SKILL.md +6 -6
- package/skills/omnistudio-omniscript-generate/SKILL.md +6 -5
- package/skills/platform-apex-logs-debug/SKILL.md +1 -0
- package/skills/platform-metadata-deploy/SKILL.md +1 -0
- package/skills/platform-models-api-configure/SKILL.md +5 -5
- package/skills/platform-soql-query/SKILL.md +1 -0
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +17 -6
- package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +107 -192
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +6 -6
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +49 -20
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +4 -4
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +224 -290
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/workflow.md +295 -0
- package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -1
- package/skills/service-itsm-slack-itservice-configure/SKILL.md +2 -1
- package/skills/service-itsm-slack-itservice-configure/references/manage-slack-connection.md +2 -2
- package/skills/service-omni-channel-setup-coordinate/SKILL.md +20 -13
- package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +5 -55
- package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +0 -38
- package/skills/service-omni-command-center-analyze/SKILL.md +2 -3
- package/skills/service-omni-command-center-analyze/scripts/analyze.sh +3 -3
- package/skills/tableau-next-asset-create/README.md +65 -0
- package/skills/tableau-next-asset-create/SKILL.md +409 -0
- package/skills/tableau-next-asset-create/references/admin-users.md +149 -0
- package/skills/tableau-next-asset-create/references/ai-readiness.md +355 -0
- package/skills/tableau-next-asset-create/references/alerts.md +111 -0
- package/skills/tableau-next-asset-create/references/build-workflow.md +819 -0
- package/skills/tableau-next-asset-create/references/dashboard-authoring.md +302 -0
- package/skills/tableau-next-asset-create/references/dashboard-design-principles.md +352 -0
- package/skills/tableau-next-asset-create/references/data-transform-gotchas.md +210 -0
- package/skills/tableau-next-asset-create/references/data-understanding.md +387 -0
- package/skills/tableau-next-asset-create/references/deep-reference-index.md +74 -0
- package/skills/tableau-next-asset-create/references/destructive-operations.md +62 -0
- package/skills/tableau-next-asset-create/references/edit-dashboard.md +273 -0
- package/skills/tableau-next-asset-create/references/edit-visualization.md +529 -0
- package/skills/tableau-next-asset-create/references/empty-source-handling.md +104 -0
- package/skills/tableau-next-asset-create/references/ingest-and-metric-gotchas.md +638 -0
- package/skills/tableau-next-asset-create/references/insight-bundle.md +69 -0
- package/skills/tableau-next-asset-create/references/large-flat-file-handling.md +331 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_envelope.json +54 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_shared-widget-fields.json +122 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/add_page.json +29 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/delete_page.json +27 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/discard_dashboard.json +11 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget_to_page.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/place_widget_on_page.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_dashboard.json +16 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_page.json +26 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/rename_page.json +28 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/save_dashboard.json +18 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/undo.json +11 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_button_widget.json +69 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_container_widget.json +88 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_filter_widget.json +146 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_metric_widget.json +78 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_navigation_widget.json +80 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_parameter_widget.json +160 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_text_widget.json +103 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_visualization_widget.json +68 -0
- package/skills/tableau-next-asset-create/references/sdm-tool-reference.md +721 -0
- package/skills/tableau-next-asset-create/references/semantic-query-and-enrichment.md +355 -0
- package/skills/tableau-next-asset-create/references/shared-gates.md +322 -0
- package/skills/tableau-next-asset-create/references/sharing-and-promotion.md +306 -0
- package/skills/tableau-next-asset-create/references/tasks/ai-readiness-audit.md +51 -0
- package/skills/tableau-next-asset-create/references/tasks/analyze-data.md +48 -0
- package/skills/tableau-next-asset-create/references/tasks/build-dashboard.md +66 -0
- package/skills/tableau-next-asset-create/references/tasks/build-end-to-end.md +73 -0
- package/skills/tableau-next-asset-create/references/tasks/create-data-transform.md +51 -0
- package/skills/tableau-next-asset-create/references/tasks/create-viz.md +58 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-dashboard.md +80 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-sdm.md +106 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-viz.md +40 -0
- package/skills/tableau-next-asset-create/references/tasks/enrich-model.md +68 -0
- package/skills/tableau-next-asset-create/references/tasks/ingest-flat-file.md +68 -0
- package/skills/tableau-next-asset-create/references/tasks/manage-alert.md +35 -0
- package/skills/tableau-next-asset-create/references/tasks/profile-dataset.md +47 -0
- package/skills/tableau-next-asset-create/references/tasks/promote-or-reuse.md +46 -0
- package/skills/tableau-next-asset-create/references/tasks/provision-user.md +39 -0
- package/skills/tableau-next-asset-create/references/tasks/query-model.md +92 -0
- package/skills/tableau-next-asset-create/references/tasks/review-verified-questions.md +42 -0
- package/skills/tableau-next-asset-create/references/tasks/share-asset.md +37 -0
- package/skills/tableau-next-asset-create/references/verified-questions.md +125 -0
- package/skills/tableau-next-asset-create/references/viz-authoring.md +992 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +0 -102
|
@@ -15,6 +15,8 @@ metadata:
|
|
|
15
15
|
semver: ">=22.0.0"
|
|
16
16
|
- tool: ["sf"]
|
|
17
17
|
semver: ">=2.0.0"
|
|
18
|
+
- tool: ["sfdx"]
|
|
19
|
+
semver: ">=7.0.0"
|
|
18
20
|
---
|
|
19
21
|
|
|
20
22
|
## MANDATORY: Always write the Phase 6 report
|
|
@@ -134,37 +136,30 @@ is empty — `WHERE CreatedDate > null` is an `INVALID_QUERY_FILTER_OPERATOR` er
|
|
|
134
136
|
Salesforce SOQL and will abort the query.
|
|
135
137
|
|
|
136
138
|
### 1.7 Org-side manual prerequisites
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
as confirmed — do **not** re-ask. Only ask for items the user has not already addressed:
|
|
139
|
+
If the user's prompt already confirms these prerequisites, treat them as confirmed — do
|
|
140
|
+
**not** re-ask. Only ask for items the user has not already addressed:
|
|
140
141
|
- Data Cloud and Analytics Studio enabled (Setup → Data Cloud Setup)
|
|
141
142
|
- Connectors feature enabled (Data Cloud Setup → Feature Manager)
|
|
142
143
|
- A user assigned to the **Accrual Ingestion Process** in Processing Services Pairing
|
|
143
144
|
with the **Data Cloud Architect** permission set
|
|
144
|
-
- OAuth scope **`cdp_ingest_api`**
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
or Setup → External Client Apps. Do NOT assume any specific app name.
|
|
148
|
-
- Permission sets assigned to the System Admin (and to the Accrual Ingestion Process user):
|
|
149
|
-
- **Data Cloud Architect**
|
|
150
|
-
- CRM Analytics must be enabled first (Setup → Feature Settings → Analytics → Analytics → Getting Started → "Enable CRM Analytics"), then assign to the admin:
|
|
151
|
-
- **CRM Analytics Plus Admin**
|
|
145
|
+
- OAuth scope **`cdp_ingest_api`** on the TPM Offcore connected app
|
|
146
|
+
- Licenses: `AccrualsProcessingAddOn`, `AccrualsProcessingUserAddOn`,
|
|
147
|
+
`TpmAccrualsAddOn`, `TpmAccrualsUserAddOn` (advisory — record what the user confirmed)
|
|
152
148
|
|
|
153
149
|
---
|
|
154
150
|
|
|
155
151
|
## Phase 2 — Verify the Data Cloud connection (best-effort)
|
|
156
152
|
|
|
157
|
-
|
|
158
|
-
App**, and the app name varies by org configuration — it cannot be queried reliably by
|
|
159
|
-
name. Skip the programmatic check. Instead, if the user has not already confirmed
|
|
160
|
-
`cdp_ingest_api` as part of Phase 1.7, ask them to verify it manually:
|
|
153
|
+
Try to verify `cdp_ingest_api` by query — treat "cannot verify" as WARN, not STOP:
|
|
161
154
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
155
|
+
```bash
|
|
156
|
+
sf data query --target-org <alias> \
|
|
157
|
+
--query "SELECT Id, Name FROM ConnectedApplication WHERE Name LIKE '%TPM%'"
|
|
158
|
+
```
|
|
165
159
|
|
|
166
|
-
|
|
167
|
-
|
|
160
|
+
If the query errors on permissions, ask the user to confirm `cdp_ingest_api` is in
|
|
161
|
+
Setup → App Manager → (edit TPM Offcore connected app) → OAuth Policies →
|
|
162
|
+
Selected OAuth Scopes. Continue only after the user confirms.
|
|
168
163
|
|
|
169
164
|
---
|
|
170
165
|
|
|
@@ -228,13 +223,8 @@ Evaluate the rows:
|
|
|
228
223
|
failing component name and its `DeploymentError` value. Do not proceed to Phase 5.
|
|
229
224
|
Record Phase 5 as `not run — deployment failures unresolved` in the Phase 6 report.
|
|
230
225
|
- Any `InProgress` row → wait 60 s and re-query. **Do not advance to Phase 5 until all
|
|
231
|
-
rows are in a terminal state** (`Successful` or `Failure`).
|
|
232
|
-
|
|
233
|
-
has an internal 90-minute polling timeout — if the script exits with a timeout error,
|
|
234
|
-
**do not treat this as a failure**: query `DataKitDeploymentLog` directly in the agent
|
|
235
|
-
Phase 4 loop (as shown above) and continue polling until terminal state or a genuine
|
|
236
|
-
liveness signal is lost (org unreachable, explicit Failure rows). Surface live counts
|
|
237
|
-
periodically so the user can see progress.
|
|
226
|
+
rows are in a terminal state** (`Successful` or `Failure`). If any row is still
|
|
227
|
+
`InProgress` after 30 minutes, stop and surface the live counts.
|
|
238
228
|
- Zero rows → the deployment has not produced log entries yet; re-query every 60 s up to
|
|
239
229
|
30 minutes. Treat persistent zero rows as a deployment problem — stop and report.
|
|
240
230
|
- All rows `Successful` → proceed to Phase 5.
|
|
@@ -179,16 +179,7 @@ function getConfig() {
|
|
|
179
179
|
* @param {string} salesOrg - Must be exactly 4 alphanumeric characters.
|
|
180
180
|
* @param {string|null} namespaceOverride - When non-null, must be 1-15 alphanumeric characters.
|
|
181
181
|
*/
|
|
182
|
-
function validateInputs(salesOrg, namespaceOverride
|
|
183
|
-
// Org alias: Salesforce allows alphanumeric, hyphens, underscores, dots, and @ (usernames).
|
|
184
|
-
// Restrict to safe characters to prevent shell metacharacter injection on Windows cmd.exe.
|
|
185
|
-
// Allow alphanumeric, hyphens, underscores, dots, @, and + (valid in Salesforce usernames, e.g. user+ci@example.com).
|
|
186
|
-
// None of these characters are cmd.exe metacharacters, so shell injection via org alias is prevented.
|
|
187
|
-
if (!/^[A-Za-z0-9_\-@.+]+$/.test(orgAlias)) {
|
|
188
|
-
console.error(`Error: Invalid org alias "${orgAlias}". Must contain only alphanumeric characters, hyphens, underscores, dots, @, or +.`);
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
|
|
182
|
+
function validateInputs(salesOrg, namespaceOverride) {
|
|
192
183
|
if (!/^[A-Za-z0-9]{4}$/.test(salesOrg)) {
|
|
193
184
|
console.error('Error: Invalid sales org.');
|
|
194
185
|
process.exit(1);
|
|
@@ -232,7 +223,7 @@ async function main() {
|
|
|
232
223
|
const { orgAlias, skipDataSpace, salesOrg, dryRun, namespaceOverride } = config;
|
|
233
224
|
|
|
234
225
|
// Validate inputs before any org access or step execution
|
|
235
|
-
validateInputs(salesOrg, namespaceOverride
|
|
226
|
+
validateInputs(salesOrg, namespaceOverride);
|
|
236
227
|
|
|
237
228
|
const { dataSpaceName, dataSpacePrefix } = getDataSpaceConfig(salesOrg);
|
|
238
229
|
|
|
@@ -274,6 +265,8 @@ async function main() {
|
|
|
274
265
|
}
|
|
275
266
|
|
|
276
267
|
const setupDir = __dirname;
|
|
268
|
+
const dataKitPath = path.join(setupDir, 'CGCloudAddons', 'TPM', 'Accruals', 'TPM Accruals Data Kit');
|
|
269
|
+
const scriptsDir = path.join(setupDir, 'CGCloudAddons', 'TPM', 'Accruals', 'Accruals Data Kit Deployment Scripts');
|
|
277
270
|
|
|
278
271
|
console.log(`Sales Org: ${salesOrg}`);
|
|
279
272
|
if (!skipDataSpace) {
|
|
@@ -289,10 +282,7 @@ async function main() {
|
|
|
289
282
|
}
|
|
290
283
|
|
|
291
284
|
// Run all steps in order
|
|
292
|
-
|
|
293
|
-
const cgcloudAddonsDir = await downloadStaticResource(orgAlias, setupDir);
|
|
294
|
-
const dataKitPath = path.join(cgcloudAddonsDir, 'TPM', 'Accruals', 'TPM Accruals Data Kit');
|
|
295
|
-
const scriptsDir = path.join(cgcloudAddonsDir, 'TPM', 'Accruals', 'Accruals Data Kit Deployment Scripts');
|
|
285
|
+
await downloadStaticResource(orgAlias, setupDir);
|
|
296
286
|
await replaceOrgId(orgId, dataKitPath);
|
|
297
287
|
await deployMetadata(orgAlias, dataKitPath, dryRun);
|
|
298
288
|
await deployEngine(orgAlias, scriptsDir, orgId, namespace, dryRun);
|
|
@@ -306,10 +296,10 @@ async function main() {
|
|
|
306
296
|
}
|
|
307
297
|
|
|
308
298
|
// Step 7: Deploy Accruals Reports with Data Space replacements
|
|
309
|
-
await deployAccrualsReports(orgAlias,
|
|
299
|
+
await deployAccrualsReports(orgAlias, setupDir, skipDataSpace, dataSpaceName, dataSpacePrefix, namespace, dryRun);
|
|
310
300
|
|
|
311
301
|
// Step 8: Deploy UI components (TPMAccrualTacticSummary)
|
|
312
|
-
await deployUI(orgAlias,
|
|
302
|
+
await deployUI(orgAlias, setupDir, skipDataSpace, dataSpaceName, dataSpacePrefix, salesOrg, namespace, dryRun);
|
|
313
303
|
|
|
314
304
|
// Step 9: Completion and next steps
|
|
315
305
|
await completion(dryRun);
|
package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js
CHANGED
|
@@ -1,63 +1,47 @@
|
|
|
1
|
-
const readline = require('readline');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Step 0: Check Prerequisites
|
|
5
|
-
* Presents prerequisites to the user and waits for confirmation
|
|
6
|
-
*/
|
|
7
|
-
async function checkPrerequisites() {
|
|
8
|
-
console.log('\n=== Step 0: Prerequisites ===');
|
|
9
|
-
|
|
10
|
-
console.log('\nBefore proceeding,
|
|
11
|
-
|
|
12
|
-
console.log('
|
|
13
|
-
console.log('
|
|
14
|
-
console.log('
|
|
15
|
-
console.log(' - The user
|
|
16
|
-
console.log('
|
|
17
|
-
console.log('
|
|
18
|
-
console.log('
|
|
19
|
-
|
|
20
|
-
console.log('
|
|
21
|
-
|
|
22
|
-
console.log('\
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return Promise.resolve();
|
|
49
|
-
}
|
|
50
|
-
return new Promise((resolve) => {
|
|
51
|
-
const rl = readline.createInterface({
|
|
52
|
-
input: process.stdin,
|
|
53
|
-
output: process.stdout
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
rl.question('Press Enter when you have confirmed all prerequisites are met...', () => {
|
|
57
|
-
rl.close();
|
|
58
|
-
resolve();
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
module.exports = checkPrerequisites;
|
|
1
|
+
const readline = require('readline');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Step 0: Check Prerequisites
|
|
5
|
+
* Presents prerequisites to the user and waits for confirmation
|
|
6
|
+
*/
|
|
7
|
+
async function checkPrerequisites() {
|
|
8
|
+
console.log('\n=== Step 0: Prerequisites ===');
|
|
9
|
+
|
|
10
|
+
console.log('\nBefore proceeding with the setup, please ensure the following prerequisites are met:');
|
|
11
|
+
console.log('\n1. Enable Data Cloud and Analytics Studio');
|
|
12
|
+
console.log(' - Navigate to Setup > Data Cloud Setup');
|
|
13
|
+
console.log(' - Ensure Data Cloud and Analytics Studio are enabled');
|
|
14
|
+
console.log('\n2. Ensure there is a user assigned in the Processing Services Pairing app to the Accrual Ingestion Process');
|
|
15
|
+
console.log(' - The user must have the Data Cloud Architect permission set');
|
|
16
|
+
console.log(' - Alternatively, a System Admin or user with Data Cloud Architect can be assigned to all processes');
|
|
17
|
+
console.log('\n3. Ensure the connected app or external client app for TPM Offcore has the oauth scope "cdp_ingest_api"');
|
|
18
|
+
console.log(' - Navigate to Setup > App Manager');
|
|
19
|
+
console.log(' - Edit your connected app and verify the oauth scope includes "cdp_ingest_api"');
|
|
20
|
+
console.log(' - Note: Depending on your org setup, this permission may already be included');
|
|
21
|
+
|
|
22
|
+
console.log('\n');
|
|
23
|
+
|
|
24
|
+
// Wait for user confirmation
|
|
25
|
+
await waitForUserConfirmation();
|
|
26
|
+
|
|
27
|
+
console.log('[OK] Prerequisites confirmed. Proceeding to next step...\n');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Wait for user to press Enter
|
|
32
|
+
*/
|
|
33
|
+
function waitForUserConfirmation() {
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
const rl = readline.createInterface({
|
|
36
|
+
input: process.stdin,
|
|
37
|
+
output: process.stdout
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
rl.question('Press Enter when you have confirmed all prerequisites are met...', () => {
|
|
41
|
+
rl.close();
|
|
42
|
+
resolve();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = checkPrerequisites;
|
package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const https = require('https');
|
|
3
|
-
const os = require('os');
|
|
4
3
|
const path = require('path');
|
|
5
4
|
const { execFileSync } = require('child_process');
|
|
6
5
|
const { execSfJson, getOrgDetails } = require('./utils');
|
|
@@ -12,8 +11,6 @@ async function downloadStaticResource(orgAlias, setupDir) {
|
|
|
12
11
|
console.log('\n=== Step 1: Downloading CGCloudAddons static resource ===');
|
|
13
12
|
|
|
14
13
|
const staticResourceName = 'CGCloudAddons';
|
|
15
|
-
// Extract to os.tmpdir() to avoid EBUSY locks in the script tree on Windows
|
|
16
|
-
const extractBase = path.join(os.tmpdir(), `tpm_accruals_extract_${Date.now()}`);
|
|
17
14
|
|
|
18
15
|
// Get org details for REST API call
|
|
19
16
|
console.log('Getting org connection details...');
|
|
@@ -33,8 +30,7 @@ async function downloadStaticResource(orgAlias, setupDir) {
|
|
|
33
30
|
|
|
34
31
|
// Download the static resource body using REST API
|
|
35
32
|
console.log('Downloading static resource content...');
|
|
36
|
-
|
|
37
|
-
const targetFile = path.join(extractBase, `${staticResourceName}.zip`);
|
|
33
|
+
const targetFile = path.join(setupDir, `${staticResourceName}.zip`);
|
|
38
34
|
const bodyUrl = `${orgDetails.instanceUrl}/services/data/v${orgDetails.apiVersion}/sobjects/StaticResource/${staticResourceId}/Body`;
|
|
39
35
|
|
|
40
36
|
await new Promise((resolve, reject) => {
|
|
@@ -66,15 +62,17 @@ async function downloadStaticResource(orgAlias, setupDir) {
|
|
|
66
62
|
|
|
67
63
|
// Extract the zip file
|
|
68
64
|
console.log('Extracting static resource...');
|
|
69
|
-
const extractDir = path.join(
|
|
70
|
-
fs.mkdirSync(extractDir, { recursive: true });
|
|
65
|
+
const extractDir = path.join(setupDir, staticResourceName);
|
|
71
66
|
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
// Remove existing extraction directory if it exists
|
|
68
|
+
if (fs.existsSync(extractDir)) {
|
|
69
|
+
fs.rmSync(extractDir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Extract: tar on Windows (bsdtar handles ZIP), unzip on macOS/Linux.
|
|
73
|
+
// GNU tar on Linux cannot read ZIP archives.
|
|
76
74
|
const [unzipCmd, unzipArgs] = process.platform === 'win32'
|
|
77
|
-
? ['
|
|
75
|
+
? ['tar', ['-xf', targetFile, '-C', extractDir]]
|
|
78
76
|
: ['unzip', ['-o', '-q', targetFile, '-d', extractDir]];
|
|
79
77
|
try {
|
|
80
78
|
execFileSync(unzipCmd, unzipArgs, { stdio: 'pipe' });
|
|
@@ -94,7 +92,6 @@ async function downloadStaticResource(orgAlias, setupDir) {
|
|
|
94
92
|
}
|
|
95
93
|
|
|
96
94
|
console.log('[OK] CGCloudAddons static resource downloaded and extracted successfully\n');
|
|
97
|
-
return extractDir;
|
|
98
95
|
}
|
|
99
96
|
|
|
100
97
|
module.exports = downloadStaticResource;
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
function walkFiles(dir, extensions) {
|
|
5
|
-
const results = [];
|
|
6
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
7
|
-
const full = path.join(dir, entry.name);
|
|
8
|
-
if (entry.isDirectory()) results.push(...walkFiles(full, extensions));
|
|
9
|
-
else if (extensions.some(ext => entry.name.endsWith(ext))) results.push(full);
|
|
10
|
-
}
|
|
11
|
-
return results;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Step 2: Replace __SF_ORG_ID__ placeholder with actual org ID in all metadata files
|
|
16
|
-
*/
|
|
17
|
-
async function replaceOrgId(orgId, dataKitPath) {
|
|
18
|
-
console.log('\n=== Step 2: Replacing org ID placeholders ===');
|
|
19
|
-
console.log(`Target directory: ${dataKitPath}`);
|
|
20
|
-
console.log(`Org ID: ${orgId} (truncated to 15 chars: ${orgId.slice(0, 15)})`);
|
|
21
|
-
|
|
22
|
-
// Truncate org ID to 15 characters
|
|
23
|
-
const truncatedOrgId = orgId.slice(0, 15);
|
|
24
|
-
|
|
25
|
-
// Find all XML and JSON files
|
|
26
|
-
const files = walkFiles(dataKitPath, ['.xml', '.json']);
|
|
27
|
-
|
|
28
|
-
let replacementCount = 0;
|
|
29
|
-
|
|
30
|
-
files.forEach(file => {
|
|
31
|
-
try {
|
|
32
|
-
const content = fs.readFileSync(file, 'utf8');
|
|
33
|
-
if (content.includes('__SF_ORG_ID__')) {
|
|
34
|
-
const newContent = content.replace(/__SF_ORG_ID__/g, truncatedOrgId);
|
|
35
|
-
fs.writeFileSync(file, newContent, 'utf8');
|
|
36
|
-
replacementCount++;
|
|
37
|
-
}
|
|
38
|
-
} catch (error) {
|
|
39
|
-
console.error(`Warning: Failed to process file ${file}: ${error.message}`);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
console.log(`[OK] Replaced org ID placeholder in ${replacementCount} file(s)\n`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
module.exports = replaceOrgId;
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
function walkFiles(dir, extensions) {
|
|
5
|
+
const results = [];
|
|
6
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
7
|
+
const full = path.join(dir, entry.name);
|
|
8
|
+
if (entry.isDirectory()) results.push(...walkFiles(full, extensions));
|
|
9
|
+
else if (extensions.some(ext => entry.name.endsWith(ext))) results.push(full);
|
|
10
|
+
}
|
|
11
|
+
return results;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Step 2: Replace __SF_ORG_ID__ placeholder with actual org ID in all metadata files
|
|
16
|
+
*/
|
|
17
|
+
async function replaceOrgId(orgId, dataKitPath) {
|
|
18
|
+
console.log('\n=== Step 2: Replacing org ID placeholders ===');
|
|
19
|
+
console.log(`Target directory: ${dataKitPath}`);
|
|
20
|
+
console.log(`Org ID: ${orgId} (truncated to 15 chars: ${orgId.slice(0, 15)})`);
|
|
21
|
+
|
|
22
|
+
// Truncate org ID to 15 characters
|
|
23
|
+
const truncatedOrgId = orgId.slice(0, 15);
|
|
24
|
+
|
|
25
|
+
// Find all XML and JSON files
|
|
26
|
+
const files = walkFiles(dataKitPath, ['.xml', '.json']);
|
|
27
|
+
|
|
28
|
+
let replacementCount = 0;
|
|
29
|
+
|
|
30
|
+
files.forEach(file => {
|
|
31
|
+
try {
|
|
32
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
33
|
+
if (content.includes('__SF_ORG_ID__')) {
|
|
34
|
+
const newContent = content.replace(/__SF_ORG_ID__/g, truncatedOrgId);
|
|
35
|
+
fs.writeFileSync(file, newContent, 'utf8');
|
|
36
|
+
replacementCount++;
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error(`Warning: Failed to process file ${file}: ${error.message}`);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
console.log(`[OK] Replaced org ID placeholder in ${replacementCount} file(s)\n`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = replaceOrgId;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const { exec, execDeployJson, execSfJson } = require('./utils');
|
|
1
|
+
const { exec, execDeployJson, getSfBin } = require('./utils');
|
|
5
2
|
|
|
6
3
|
/**
|
|
7
4
|
* Step 3: Deploy TPM Accruals Data Kit metadata to the org
|
|
@@ -21,24 +18,10 @@ async function deployMetadata(orgAlias, dataKitPath, dryRun = false) {
|
|
|
21
18
|
return;
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
// orgs where tracking state diverges from org reality).
|
|
27
|
-
const mdapiOut = path.join(os.tmpdir(), `tpm_accruals_mdapi_${Date.now()}`);
|
|
28
|
-
console.log('Converting source to MDAPI format...');
|
|
29
|
-
const convertResult = execSfJson(['project', 'convert', 'source', '--output-dir', mdapiOut, '--json'], { cwd: dataKitPath });
|
|
30
|
-
if (convertResult.status !== 0) {
|
|
31
|
-
throw new Error(`Source conversion failed: ${convertResult.message || JSON.stringify(convertResult)}`);
|
|
32
|
-
}
|
|
33
|
-
console.log(`Converted to: ${convertResult.result && convertResult.result.location || mdapiOut}`);
|
|
34
|
-
|
|
21
|
+
// Deploy using sf project deploy start from the data kit root so the
|
|
22
|
+
// sfdx-project.json sourceApiVersion is respected.
|
|
35
23
|
console.log('Deploying metadata...');
|
|
36
|
-
execDeployJson(['project', 'deploy', 'start', '--
|
|
37
|
-
|
|
38
|
-
// Clean up temp dir
|
|
39
|
-
try { fs.rmSync(mdapiOut, { recursive: true }); } catch (cleanupErr) {
|
|
40
|
-
console.warn(`[WARN] Could not remove temp directory ${mdapiOut}: ${cleanupErr.message}`);
|
|
41
|
-
}
|
|
24
|
+
execDeployJson(['project', 'deploy', 'start', '--source-dir', 'force-app', '--target-org', orgAlias], { cwd: dataKitPath });
|
|
42
25
|
|
|
43
26
|
console.log('[OK] TPM Accruals Data Kit deployed successfully\n');
|
|
44
27
|
}
|
|
@@ -1,82 +1,58 @@
|
|
|
1
|
-
const readline = require('readline');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* @param {string}
|
|
7
|
-
* @param {string}
|
|
8
|
-
* @param {string}
|
|
9
|
-
* @param {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
console.log(
|
|
16
|
-
console.log(` -
|
|
17
|
-
console.log(` -
|
|
18
|
-
console.log(` -
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
console.log('
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
console.log('\
|
|
28
|
-
console.log('
|
|
29
|
-
console.log('
|
|
30
|
-
console.log('
|
|
31
|
-
console.log('
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Wait for user to press Enter.
|
|
62
|
-
* Auto-confirms immediately when stdin is not a TTY (piped / headless run).
|
|
63
|
-
*/
|
|
64
|
-
function waitForUserConfirmation() {
|
|
65
|
-
if (!process.stdin.isTTY) {
|
|
66
|
-
console.log('[Auto-confirmed: running non-interactively]');
|
|
67
|
-
return Promise.resolve();
|
|
68
|
-
}
|
|
69
|
-
return new Promise((resolve) => {
|
|
70
|
-
const rl = readline.createInterface({
|
|
71
|
-
input: process.stdin,
|
|
72
|
-
output: process.stdout
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
rl.question('Press Enter when you have completed these steps...', () => {
|
|
76
|
-
rl.close();
|
|
77
|
-
resolve();
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
module.exports = createDataSpace;
|
|
1
|
+
const readline = require('readline');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Step 6: Manual Data Space creation with DLO configuration
|
|
5
|
+
* @param {string} orgAlias - The Salesforce org alias
|
|
6
|
+
* @param {string} salesOrg - The sales org value (e.g., "0001")
|
|
7
|
+
* @param {string} dataSpaceName - The data space name (e.g., "DataSpace_0001")
|
|
8
|
+
* @param {string} dataSpacePrefix - The data space prefix (e.g., "DS1")
|
|
9
|
+
* @param {boolean} dryRun - If true, skip user prompt
|
|
10
|
+
*/
|
|
11
|
+
async function createDataSpace(orgAlias, salesOrg, dataSpaceName, dataSpacePrefix, dryRun = false) {
|
|
12
|
+
console.log('\n=== Step 6: Create Data Space (Manual Step) ===');
|
|
13
|
+
|
|
14
|
+
console.log('\nData Space configuration:');
|
|
15
|
+
console.log(` - Name: ${dataSpaceName}`);
|
|
16
|
+
console.log(` - Prefix: ${dataSpacePrefix}`);
|
|
17
|
+
console.log(` - DLO: accrualoutput_decorated__dll`);
|
|
18
|
+
console.log(` - Filter: SalesOrg equals "${salesOrg}"`);
|
|
19
|
+
|
|
20
|
+
if (dryRun) {
|
|
21
|
+
console.log('\n[DRY RUN] Skipping manual step prompt');
|
|
22
|
+
console.log('[OK] Step 6 completed (dry run)\n');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log('\nPlease complete the following manual steps in your Salesforce org:');
|
|
27
|
+
console.log('\n1. Navigate to the Data Spaces tab in your org');
|
|
28
|
+
console.log('2. Create a new Data Space with the details shown above');
|
|
29
|
+
console.log('3. Go into the newly created Data Space');
|
|
30
|
+
console.log('4. Add the DLO: accrualoutput_decorated__dll');
|
|
31
|
+
console.log('5. Apply the filter shown above');
|
|
32
|
+
|
|
33
|
+
console.log('\n');
|
|
34
|
+
|
|
35
|
+
// Wait for user confirmation
|
|
36
|
+
await waitForUserConfirmation();
|
|
37
|
+
|
|
38
|
+
console.log('[OK] Data Space creation confirmed. Proceeding to next step...\n');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Wait for user to press Enter
|
|
43
|
+
*/
|
|
44
|
+
function waitForUserConfirmation() {
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
const rl = readline.createInterface({
|
|
47
|
+
input: process.stdin,
|
|
48
|
+
output: process.stdout
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
rl.question('Press Enter when you have completed these steps...', () => {
|
|
52
|
+
rl.close();
|
|
53
|
+
resolve();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = createDataSpace;
|