@aifabrix/builder 2.52.0 → 2.53.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/lib/api/datasources-extended.api.js +8 -8
- package/lib/api/keycloak.api.js +92 -0
- package/lib/api/token-providers.api.js +77 -0
- package/lib/api/types/keycloak.types.js +23 -0
- package/lib/api/types/token-providers.types.js +65 -0
- package/lib/app/deploy-config.js +3 -2
- package/lib/app/down.js +16 -1
- package/lib/channels/add-channel.js +134 -57
- package/lib/channels/approval-guides/chatgpt.js +1 -1
- package/lib/channels/approval-guides/index.js +3 -0
- package/lib/channels/approval-guides/microsoft-copilot.js +27 -14
- package/lib/channels/channel-add-ensure.js +128 -0
- package/lib/channels/channel-add-existing.js +72 -0
- package/lib/channels/channel-artifact-generator.js +11 -1
- package/lib/channels/channel-branding.js +94 -0
- package/lib/channels/channel-credential.js +8 -0
- package/lib/channels/channel-discovery.js +330 -0
- package/lib/channels/channel-external-system.js +1 -1
- package/lib/channels/channel-runtime-resolver.js +107 -14
- package/lib/channels/channel-status-display.js +36 -3
- package/lib/channels/microsoft-copilot-channel-add.js +138 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +251 -0
- package/lib/channels/microsoft-copilot-entra-sso.js +285 -0
- package/lib/channels/microsoft-copilot-icons.js +74 -0
- package/lib/channels/microsoft-copilot-limits.js +103 -0
- package/lib/channels/microsoft-copilot-package.js +178 -52
- package/lib/channels/microsoft-copilot-validate.js +227 -0
- package/lib/cli/attach-default-help-examples.js +102 -0
- package/lib/cli/index.js +4 -0
- package/lib/cli/infra-guided.js +13 -6
- package/lib/cli/setup-credential-deployment.js +7 -5
- package/lib/cli/setup-infra.js +31 -4
- package/lib/cli/setup-utility-validate.js +1 -0
- package/lib/commands/channel-add-setup.js +28 -9
- package/lib/commands/channel.js +14 -10
- package/lib/commands/credential-push.js +37 -5
- package/lib/commands/integration-definition.js +158 -0
- package/lib/commands/package-score.js +72 -0
- package/lib/commands/repair-auth-apply.js +19 -5
- package/lib/commands/repair-datasource-sync-operations.js +4 -1
- package/lib/commands/role-assistant-test-output.js +200 -0
- package/lib/commands/role-assistant.js +163 -166
- package/lib/datasource/capability/capability-resolve.js +15 -5
- package/lib/datasource/capability/copy-operations.js +14 -4
- package/lib/deployment/deployer-poll-run.js +2 -2
- package/lib/deployment/deployer.js +1 -1
- package/lib/deployment/environment.js +2 -2
- package/lib/external-system/deploy.js +11 -21
- package/lib/infrastructure/index.js +19 -4
- package/lib/integration-definition/apply.js +476 -0
- package/lib/integration-definition/canonical-json.js +51 -0
- package/lib/integration-definition/emit-suite-bid.js +94 -0
- package/lib/integration-definition/enrich-crm-field-mappings.js +240 -0
- package/lib/integration-definition/enrich-openapi-operations.js +433 -0
- package/lib/integration-definition/from-discovery.js +339 -0
- package/lib/integration-definition/hash.js +37 -0
- package/lib/integration-definition/index.js +37 -0
- package/lib/integration-definition/resource-type-catalog.js +59 -0
- package/lib/integration-definition/system-kind-enum.js +40 -0
- package/lib/integration-definition/validate.js +148 -0
- package/lib/lab/package-parity-score.js +417 -0
- package/lib/programmatic/builder-api-request.js +5 -1
- package/lib/programmatic/builder-help-governance.js +3 -2
- package/lib/programmatic/capability-registry.js +20 -0
- package/lib/programmatic/help-content/channel-onboarding.md +35 -0
- package/lib/programmatic/help-content/cip-overview.md +27 -0
- package/lib/programmatic/help-content/connected-system-ui.md +70 -0
- package/lib/programmatic/help-content/dimensions-guide.md +23 -0
- package/lib/programmatic/help-content/enterprise-sync-fabrix.md +123 -0
- package/lib/programmatic/help-content/overview.md +25 -0
- package/lib/programmatic/help-content/subscription-guide.md +27 -0
- package/lib/programmatic/help-content/workflow.md +50 -0
- package/lib/programmatic/openapi-component-schemas.js +7 -1
- package/lib/programmatic/openapi-descriptions.js +46 -0
- package/lib/programmatic/openapi-envelope-examples.js +280 -0
- package/lib/programmatic/openapi-operation-bindings.js +50 -0
- package/lib/programmatic/openapi-request-schemas.js +40 -0
- package/lib/programmatic/openapi-result-schemas-overflow.js +101 -0
- package/lib/programmatic/openapi-result-schemas.js +76 -99
- package/lib/programmatic/openapi-schema-descriptions-core.js +25 -4
- package/lib/programmatic/openapi-schema-descriptions-help.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-operations.js +43 -0
- package/lib/programmatic/openapi-schema-helpers.js +9 -9
- package/lib/programmatic/openapi-spec.js +11 -1
- package/lib/programmatic/orchestration-openapi-meta.js +10 -0
- package/lib/programmatic/persist-supplied-openapi.js +180 -0
- package/lib/programmatic/route-handler-map.js +35 -1
- package/lib/programmatic/run-channel-package.js +236 -0
- package/lib/programmatic/run-integration-definition.js +77 -0
- package/lib/role-assistant/evidence-sync.js +55 -7
- package/lib/role-assistant/knowledge-sync-logging.js +58 -0
- package/lib/role-assistant/knowledge-sync.js +88 -93
- package/lib/role-assistant/test-cases-bid.js +155 -0
- package/lib/role-assistant/test-cases-evaluate.js +9 -1
- package/lib/role-assistant/test-cases-honesty.js +24 -10
- package/lib/role-assistant/test-cases.js +28 -0
- package/lib/role-assistant/test-runner-attachments.js +118 -0
- package/lib/role-assistant/test-runner-bid-apply.js +201 -0
- package/lib/role-assistant/test-runner-bid-document.js +278 -0
- package/lib/role-assistant/test-runner-start-payload.js +96 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +249 -20
- package/lib/role-assistant/test-runner-workhub-helpers.js +100 -0
- package/lib/role-assistant/test-runner-workhub-soft.js +86 -0
- package/lib/role-assistant/test-runner-workhub.js +152 -107
- package/lib/role-assistant/test-runner.js +5 -63
- package/lib/role-assistant/test-suite.js +112 -0
- package/lib/schema/application-schema.json +56 -6
- package/lib/schema/external-datasource.schema.json +103 -17
- package/lib/schema/external-system.schema.json +54 -3
- package/lib/schema/integration-definition.schema.json +195 -0
- package/lib/utils/authentication-shape.js +6 -0
- package/lib/utils/compose-generator.js +10 -1
- package/lib/utils/compose-traefik-extra-routes.js +107 -0
- package/lib/utils/docker-build.js +2 -2
- package/lib/utils/help-builder.js +3 -1
- package/lib/utils/promote-dev-docker-image.js +102 -18
- package/lib/utils/transient-developer-id.js +28 -0
- package/package.json +14 -16
- package/templates/README.md +12 -1
- package/templates/applications/dataplane/application.yaml +10 -2
- package/templates/applications/dataplane/env.template +7 -6
- package/templates/applications/miso-controller/application.yaml +23 -8
- package/templates/applications/miso-controller/env.template +8 -2
- package/templates/applications/miso-controller/rbac.yaml +1 -0
- package/templates/channels/README.md +11 -1
- package/templates/channels/brand/color-192.png +0 -0
- package/templates/channels/brand/dark/128.png +0 -0
- package/templates/channels/brand/dark/192.png +0 -0
- package/templates/channels/brand/dark/256.png +0 -0
- package/templates/channels/brand/dark/32.png +0 -0
- package/templates/channels/brand/dark/512.png +0 -0
- package/templates/channels/brand/dark/64.png +0 -0
- package/templates/channels/brand/light/128.png +0 -0
- package/templates/channels/brand/light/192.png +0 -0
- package/templates/channels/brand/light/256.png +0 -0
- package/templates/channels/brand/light/32.png +0 -0
- package/templates/channels/brand/light/512.png +0 -0
- package/templates/channels/brand/light/64.png +0 -0
- package/templates/channels/brand/mono-white/128.png +0 -0
- package/templates/channels/brand/mono-white/192.png +0 -0
- package/templates/channels/brand/mono-white/256.png +0 -0
- package/templates/channels/brand/mono-white/32.png +0 -0
- package/templates/channels/brand/mono-white/512.png +0 -0
- package/templates/channels/brand/mono-white/64.png +0 -0
- package/templates/channels/brand/outline-32.png +0 -0
- package/templates/channels/chatgpt/install.template.md.hbs +6 -4
- package/templates/channels/chatgpt/integration/README.md +4 -5
- package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +14 -16
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +5 -3
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +30 -0
- package/templates/channels/microsoft-copilot/fi-fi.template.json.hbs +7 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +93 -22
- package/templates/channels/microsoft-copilot/integration/README.md +2 -3
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +1 -22
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -19
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +15 -0
- package/templates/channels/slack/integration/README.md +2 -4
- package/templates/channels/teams-bot/install.template.md.hbs +4 -0
- package/templates/channels/teams-bot/integration/README.md +3 -5
- package/templates/channels/web-embed/integration/web-embed-system.json +1 -16
- package/templates/python/docker-compose.hbs +36 -0
- package/templates/typescript/docker-compose.hbs +36 -0
- package/.cursor/plans/Done/157.1-security-quality-violations-by-type.csv +0 -374
- package/.cursor/process/README.md +0 -9
- package/.cursor/rules/anchor-docs.mdc +0 -15
- package/.cursor/rules/assistant-driven-integration-build.mdc +0 -40
- package/.cursor/rules/cli-layout.mdc +0 -81
- package/.cursor/rules/cli-product-neutral.mdc +0 -43
- package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +0 -49
- package/.cursor/rules/docs-rules.mdc +0 -32
- package/.cursor/rules/plan-rules/application-lifecycle.mdc +0 -30
- package/.cursor/rules/plan-rules/plan-frontmatter.mdc +0 -35
- package/.cursor/rules/plan-rules/plan-lifecycle.mdc +0 -31
- package/.cursor/rules/plan-rules/plan-validation-gate.mdc +0 -34
- package/.cursor/rules/project-rules.mdc +0 -913
- package/.cursor/skills/README.md +0 -15
- package/.dockerignore +0 -52
- package/.eslintignore +0 -22
- package/.markdownlint.json +0 -14
- package/anchor-docs/README.md +0 -10
- package/anchor-docs/_TEMPLATE +0 -24
- package/babel.config.js +0 -6
- package/bin/builder-api-cleanup.js +0 -26
- package/bin/builder-api-nest.js +0 -10
- package/bin/builder-api-spike.js +0 -19
- package/enterprise-knowledge/README.md +0 -50
- package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +0 -22
- package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +0 -15
- package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +0 -69
- package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +0 -52
- package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +0 -29
- package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +0 -2
- package/integration/README.md +0 -81
- package/integration/github/README.md +0 -53
- package/integration/github/application.json +0 -21
- package/integration/github/deploy.js +0 -72
- package/integration/github/env.template +0 -11
- package/integration/github/github-datasource-issue-comments.json +0 -239
- package/integration/github/github-datasource-issues.json +0 -399
- package/integration/github/github-datasource-repository.json +0 -354
- package/integration/github/github-deploy.json +0 -1202
- package/integration/github/github-system.json +0 -82
- package/integration/hubspot-test/README.md +0 -159
- package/integration/hubspot-test/application.json +0 -54
- package/integration/hubspot-test/companies.json +0 -2048
- package/integration/hubspot-test/create-hubspot.js +0 -523
- package/integration/hubspot-test/env.template +0 -4
- package/integration/hubspot-test/hubspot-test-datasource-company.json +0 -138
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +0 -146
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +0 -146
- package/integration/hubspot-test/hubspot-test-datasource-users.json +0 -76
- package/integration/hubspot-test/hubspot-test-deploy.json +0 -2160
- package/integration/hubspot-test/hubspot-test-system.json +0 -74
- package/integration/hubspot-test/rbac.json +0 -166
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +0 -20
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +0 -9
- package/integration/hubspot-test/test-artifacts/wizard-invalid-add-datasource.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-invalid-app-name.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-create.yaml +0 -7
- package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-select.yaml +0 -7
- package/integration/hubspot-test/test-artifacts/wizard-invalid-known-platform.yaml +0 -4
- package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-app.yaml +0 -4
- package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
- package/integration/hubspot-test/test-artifacts/wizard-invalid-mode.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-file.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-url.yaml +0 -4
- package/integration/hubspot-test/test-artifacts/wizard-invalid-source.yaml +0 -4
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-array-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +0 -5
- package/integration/hubspot-test/test-dataplane-down-helpers.js +0 -249
- package/integration/hubspot-test/test-dataplane-down-tests.js +0 -386
- package/integration/hubspot-test/test-dataplane-down.js +0 -209
- package/integration/hubspot-test/test.js +0 -1588
- package/integration/hubspot-test/wizard-hubspot-e2e.yaml +0 -16
- package/integration/hubspot-test/wizard-hubspot-platform.yaml +0 -8
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +0 -23
- package/integration/roundtrip-test-local/README.md +0 -143
- package/integration/roundtrip-test-local/application.yaml +0 -13
- package/integration/roundtrip-test-local/env.template +0 -15
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +0 -14
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +0 -61
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +0 -25
- package/integration/roundtrip-test-local2/README.md +0 -143
- package/integration/roundtrip-test-local2/application.yaml +0 -13
- package/integration/roundtrip-test-local2/env.template +0 -15
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +0 -31
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +0 -86
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +0 -25
- package/integration/test/wizard.yaml +0 -8
- package/jest.config.coverage.js +0 -37
- package/jest.config.default.js +0 -11
- package/jest.config.integration.fixtures.js +0 -22
- package/jest.config.integration.js +0 -33
- package/jest.config.isolated.js +0 -11
- package/jest.config.manual.js +0 -30
- package/jest.global-live-fabrix-hooks.js +0 -36
- package/jest.isolated-projects.js +0 -260
- package/jest.projects.js +0 -76
- package/packages/builder-api/README.md +0 -120
- package/packages/builder-api/package.json +0 -30
- package/packages/builder-api/src/app.module.ts +0 -7
- package/packages/builder-api/src/auth/auth.module.ts +0 -5
- package/packages/builder-api/src/external-system/external-system.module.ts +0 -5
- package/packages/builder-api/src/main.ts +0 -16
- package/packages/builder-api/tsconfig.json +0 -15
- package/scripts/check-builder-api-architecture-grep.js +0 -79
- package/scripts/check-datasource-test-run-schema-sync.js +0 -34
- package/scripts/ci-fix.sh +0 -19
- package/scripts/ci-simulate.sh +0 -19
- package/scripts/diagnose-cli.js +0 -150
- package/scripts/docker_image_content_gate.js +0 -47
- package/scripts/docker_image_content_gate.sh +0 -5
- package/scripts/export-builder-api-evidence.js +0 -262
- package/scripts/install-local.js +0 -490
- package/scripts/lib/builder-api-docker-staging-copy.js +0 -60
- package/scripts/lib/builder-api-docker-staging-core.js +0 -183
- package/scripts/lib/docker-image-content-gate-core.js +0 -166
- package/scripts/lib/plan-actor.js +0 -109
- package/scripts/lib/plan-config.js +0 -20
- package/scripts/lib/plan-gates.js +0 -154
- package/scripts/lib/plan-meta.js +0 -104
- package/scripts/lib/plan-parse.js +0 -162
- package/scripts/lib/plan-prevalidate-gates.js +0 -337
- package/scripts/lib/plan-run-core.js +0 -125
- package/scripts/lib/plan-run-report.js +0 -119
- package/scripts/plan-approve.js +0 -24
- package/scripts/plan-archive.js +0 -49
- package/scripts/plan-run.js +0 -13
- package/scripts/plan-set-actor.js +0 -21
- package/scripts/plan-validate.js +0 -80
- package/scripts/pnpm/af.mjs +0 -110
- package/scripts/pnpm/check-quiet.mjs +0 -32
- package/scripts/pnpm/dev-install.mjs +0 -29
- package/scripts/pnpm/dev-reload.mjs +0 -18
- package/scripts/pnpm/help.mjs +0 -55
- package/scripts/pnpm/lib/dev-reload-core.mjs +0 -189
- package/scripts/pnpm/lib/dev-reload-log-capture.mjs +0 -67
- package/scripts/pnpm/lib/dev-reload-log-utils.mjs +0 -32
- package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +0 -124
- package/scripts/pnpm/lib/resolve-app-url.mjs +0 -183
- package/scripts/pnpm/lib/spinner.mjs +0 -42
- package/scripts/pnpm-global-remove.js +0 -48
- package/scripts/stage_builder_api_for_docker.js +0 -65
- package/scripts/sync-builder-api-template.js +0 -44
- package/scripts/test-dataplane-bootstrap.js +0 -331
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical JSON helpers for Builder Integration Definition hashing.
|
|
3
|
+
* @fileoverview Stable stringify for BID definitionHash
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Recursively sort object keys for canonical JSON.
|
|
10
|
+
* @param {unknown} value
|
|
11
|
+
* @returns {unknown}
|
|
12
|
+
*/
|
|
13
|
+
function sortValue(value) {
|
|
14
|
+
if (Array.isArray(value)) {
|
|
15
|
+
return value.map(sortValue);
|
|
16
|
+
}
|
|
17
|
+
if (value && typeof value === 'object' && !(value instanceof Date)) {
|
|
18
|
+
const out = {};
|
|
19
|
+
for (const key of Object.keys(value).sort()) {
|
|
20
|
+
out[key] = sortValue(value[key]);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Canonical JSON string (sorted keys, no whitespace variance).
|
|
29
|
+
* @param {unknown} value
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
function canonicalJsonString(value) {
|
|
33
|
+
return JSON.stringify(sortValue(value));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Clone BID without definitionHash for hashing.
|
|
38
|
+
* @param {Record<string, unknown>} bid
|
|
39
|
+
* @returns {Record<string, unknown>}
|
|
40
|
+
*/
|
|
41
|
+
function bidBodyWithoutHash(bid) {
|
|
42
|
+
const clone = { ...bid };
|
|
43
|
+
delete clone.definitionHash;
|
|
44
|
+
return clone;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
sortValue,
|
|
49
|
+
canonicalJsonString,
|
|
50
|
+
bidBodyWithoutHash
|
|
51
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stamp suite provenance onto a BID template for hard GP acceptance.
|
|
3
|
+
* @fileoverview Suite-emitted BID: suiteRunId + answerFingerprint + definitionHash
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
const { withDefinitionHash } = require('./hash');
|
|
10
|
+
const { canonicalJsonString } = require('./canonical-json');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Fingerprint discovery / case answers for BID meta.answerFingerprint.
|
|
14
|
+
* @param {unknown} answers
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
function fingerprintAnswers(answers) {
|
|
18
|
+
const digest = crypto
|
|
19
|
+
.createHash('sha256')
|
|
20
|
+
.update(canonicalJsonString(answers === null || answers === undefined ? null : answers), 'utf8')
|
|
21
|
+
.digest('hex');
|
|
22
|
+
return `sha256:${digest}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function resolvePriorMeta(baseBid) {
|
|
26
|
+
return baseBid.meta && typeof baseBid.meta === 'object' && !Array.isArray(baseBid.meta)
|
|
27
|
+
? baseBid.meta
|
|
28
|
+
: {};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolveAnswerFingerprint(options) {
|
|
32
|
+
if (typeof options.answerFingerprint === 'string' && options.answerFingerprint.trim()) {
|
|
33
|
+
return options.answerFingerprint.trim();
|
|
34
|
+
}
|
|
35
|
+
return fingerprintAnswers(options.answers);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function resolveProducedAt(options) {
|
|
39
|
+
if (typeof options.producedAt === 'string' && options.producedAt.trim()) {
|
|
40
|
+
return options.producedAt.trim();
|
|
41
|
+
}
|
|
42
|
+
return new Date().toISOString();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resolveBtAssistantKey(options, priorMeta) {
|
|
46
|
+
if (typeof options.btAssistantKey === 'string' && options.btAssistantKey.trim()) {
|
|
47
|
+
return options.btAssistantKey.trim();
|
|
48
|
+
}
|
|
49
|
+
if (typeof priorMeta.btAssistantKey === 'string' && priorMeta.btAssistantKey.trim()) {
|
|
50
|
+
return priorMeta.btAssistantKey.trim();
|
|
51
|
+
}
|
|
52
|
+
return 'ra-business-transformation';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Clone a BID template and stamp suite provenance (hard GP).
|
|
57
|
+
* Does not invent datasources/capabilities — only meta + hash refresh.
|
|
58
|
+
*
|
|
59
|
+
* @param {Record<string, unknown>} baseBid - Valid BID template (e.g. example-bid.json)
|
|
60
|
+
* @param {Object} options
|
|
61
|
+
* @param {string} options.suiteRunId - Suite / processExecution id (required for hard GP)
|
|
62
|
+
* @param {string} [options.producedAt] - ISO timestamp
|
|
63
|
+
* @param {string} [options.btAssistantKey]
|
|
64
|
+
* @param {unknown} [options.answers] - Case answers for answerFingerprint
|
|
65
|
+
* @param {string} [options.answerFingerprint] - Explicit fingerprint override
|
|
66
|
+
* @returns {Record<string, unknown>}
|
|
67
|
+
*/
|
|
68
|
+
function emitSuiteBid(baseBid, options = {}) {
|
|
69
|
+
if (!baseBid || typeof baseBid !== 'object' || Array.isArray(baseBid)) {
|
|
70
|
+
throw new Error('emitSuiteBid requires a BID object');
|
|
71
|
+
}
|
|
72
|
+
const suiteRunId = String(options.suiteRunId || '').trim();
|
|
73
|
+
if (!suiteRunId) {
|
|
74
|
+
throw new Error('emitSuiteBid requires options.suiteRunId');
|
|
75
|
+
}
|
|
76
|
+
const priorMeta = resolvePriorMeta(baseBid);
|
|
77
|
+
const next = {
|
|
78
|
+
...baseBid,
|
|
79
|
+
meta: {
|
|
80
|
+
...priorMeta,
|
|
81
|
+
suiteRunId,
|
|
82
|
+
producedAt: resolveProducedAt(options),
|
|
83
|
+
btAssistantKey: resolveBtAssistantKey(options, priorMeta),
|
|
84
|
+
answerFingerprint: resolveAnswerFingerprint(options)
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
delete next.definitionHash;
|
|
88
|
+
return withDefinitionHash(next);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
emitSuiteBid,
|
|
93
|
+
fingerprintAnswers
|
|
94
|
+
};
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRM-style fieldMappings + properties query for OpenAPI object APIs.
|
|
3
|
+
* @fileoverview Keep BID propertyKeys durable across force-apply
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const RESERVED_ATTR = new Set(['id', 'externalId', 'associations']);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Seed metadataSchema + fieldMappings.attributes from BID propertyKeys.
|
|
12
|
+
* Does not write dimensions[] (repair / enrich owns dimensions alignment).
|
|
13
|
+
* @param {Record<string, unknown>} body
|
|
14
|
+
* @param {unknown} propertyKeys
|
|
15
|
+
* @returns {void}
|
|
16
|
+
*/
|
|
17
|
+
function seedPropertyKeysOnDatasource(body, propertyKeys) {
|
|
18
|
+
const keys = Array.isArray(propertyKeys)
|
|
19
|
+
? propertyKeys.map((row) => String(row || '').trim()).filter(Boolean)
|
|
20
|
+
: [];
|
|
21
|
+
if (keys.length === 0) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!body.metadataSchema || typeof body.metadataSchema !== 'object') {
|
|
25
|
+
body.metadataSchema = { type: 'object', properties: {} };
|
|
26
|
+
}
|
|
27
|
+
const schema = /** @type {any} */ (body.metadataSchema);
|
|
28
|
+
if (!schema.properties || typeof schema.properties !== 'object') {
|
|
29
|
+
schema.properties = {};
|
|
30
|
+
}
|
|
31
|
+
if (!body.fieldMappings || typeof body.fieldMappings !== 'object') {
|
|
32
|
+
body.fieldMappings = { attributes: {} };
|
|
33
|
+
}
|
|
34
|
+
const mappings = /** @type {any} */ (body.fieldMappings);
|
|
35
|
+
if (!mappings.attributes || typeof mappings.attributes !== 'object') {
|
|
36
|
+
mappings.attributes = {};
|
|
37
|
+
}
|
|
38
|
+
for (const key of keys) {
|
|
39
|
+
if (!schema.properties[key]) {
|
|
40
|
+
schema.properties[key] = {
|
|
41
|
+
type: 'string',
|
|
42
|
+
index: true,
|
|
43
|
+
filter: true,
|
|
44
|
+
description: `Synced property ${key}`
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (!mappings.attributes[key]) {
|
|
48
|
+
mappings.attributes[key] = {
|
|
49
|
+
expression: `{{raw.${key}}}`,
|
|
50
|
+
description: `Synced property ${key}`
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function mappingAttributes(body) {
|
|
57
|
+
const mappings = /** @type {any} */ (body.fieldMappings);
|
|
58
|
+
if (mappings && mappings.attributes && typeof mappings.attributes === 'object') {
|
|
59
|
+
return mappings.attributes;
|
|
60
|
+
}
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function propertyNameFromAttr(key, row) {
|
|
65
|
+
const expr =
|
|
66
|
+
row && typeof row === 'object' ? String(/** @type {any} */ (row).expression || '') : '';
|
|
67
|
+
const match = expr.match(/\{\{\s*raw\.properties\.([a-zA-Z0-9_]+)\s*\}\}/);
|
|
68
|
+
if (match) {
|
|
69
|
+
return match[1];
|
|
70
|
+
}
|
|
71
|
+
if (expr === `{{raw.${key}}}` || expr.includes(`raw.properties.${key}`)) {
|
|
72
|
+
return key;
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Collect vendor property names from CRM-style attribute expressions + labelKey.
|
|
79
|
+
* @param {Record<string, unknown>} body
|
|
80
|
+
* @returns {string[]}
|
|
81
|
+
*/
|
|
82
|
+
function collectCrmPropertyNames(body) {
|
|
83
|
+
const names = new Set();
|
|
84
|
+
const labelKeys = Array.isArray(body.labelKey) ? body.labelKey : [];
|
|
85
|
+
for (const label of labelKeys) {
|
|
86
|
+
const key = String(label || '').trim();
|
|
87
|
+
if (key) {
|
|
88
|
+
names.add(key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (const [key, row] of Object.entries(mappingAttributes(body))) {
|
|
92
|
+
if (RESERVED_ATTR.has(key)) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const name = propertyNameFromAttr(key, row);
|
|
96
|
+
if (name) {
|
|
97
|
+
names.add(name);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return [...names].sort();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function ensureCrmPropertiesBag(schema) {
|
|
104
|
+
if (!schema || !schema.properties || typeof schema.properties !== 'object') {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
schema.properties.properties = {
|
|
108
|
+
type: 'object',
|
|
109
|
+
additionalProperties: true,
|
|
110
|
+
description: 'Vendor nested properties bag (CRM object APIs)'
|
|
111
|
+
};
|
|
112
|
+
schema.properties.associations = {
|
|
113
|
+
type: 'object',
|
|
114
|
+
additionalProperties: true,
|
|
115
|
+
description: 'Associated records bag from vendor list/get'
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function rewriteCrmLabelExpressions(mappings, labelKeys) {
|
|
120
|
+
for (const label of labelKeys) {
|
|
121
|
+
if (mappings.attributes[label]) {
|
|
122
|
+
mappings.attributes[label].expression = `{{raw.properties.${label}}}`;
|
|
123
|
+
mappings.attributes[label].description =
|
|
124
|
+
'Display label from vendor properties object';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function rewriteCrmAttributeExpressions(mappings, labelKeys) {
|
|
130
|
+
for (const [key, row] of Object.entries(mappings.attributes)) {
|
|
131
|
+
if (RESERVED_ATTR.has(key) || labelKeys.includes(key) || !row || typeof row !== 'object') {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const expr = String(/** @type {any} */ (row).expression || '');
|
|
135
|
+
if (expr === `{{raw.${key}}}` || !expr.includes('raw.properties.')) {
|
|
136
|
+
/** @type {any} */ (row).expression = `{{raw.properties.${key}}}`;
|
|
137
|
+
if (!/** @type {any} */ (row).description) {
|
|
138
|
+
/** @type {any} */ (row).description = `Synced property ${key}`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function ensureCrmIdentityMappings(mappings) {
|
|
145
|
+
if (mappings.attributes.id) {
|
|
146
|
+
mappings.attributes.id.expression = '{{raw.id}}';
|
|
147
|
+
}
|
|
148
|
+
if (mappings.attributes.externalId) {
|
|
149
|
+
mappings.attributes.externalId.expression = '{{raw.id}}';
|
|
150
|
+
}
|
|
151
|
+
if (!mappings.attributes.associations) {
|
|
152
|
+
mappings.attributes.associations = {
|
|
153
|
+
expression: '{{raw.associations}}',
|
|
154
|
+
description: 'Associated records returned when OpenAPI associations query is set'
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* When collection paths look like CRM object APIs, prefer nested properties for labels
|
|
161
|
+
* and request those properties on list/get CIP queries.
|
|
162
|
+
* @param {Record<string, unknown>} body
|
|
163
|
+
* @param {string} samplePath
|
|
164
|
+
* @returns {void}
|
|
165
|
+
*/
|
|
166
|
+
function maybeEnrichCrmStyleFieldMappings(body, samplePath) {
|
|
167
|
+
if (!/\/objects\//i.test(samplePath)) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const mappings = /** @type {any} */ (body.fieldMappings);
|
|
171
|
+
if (!mappings || !mappings.attributes || typeof mappings.attributes !== 'object') {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const labelKeys = Array.isArray(body.labelKey) ? body.labelKey : ['name'];
|
|
175
|
+
ensureCrmPropertiesBag(/** @type {any} */ (body.metadataSchema));
|
|
176
|
+
rewriteCrmLabelExpressions(mappings, labelKeys);
|
|
177
|
+
rewriteCrmAttributeExpressions(mappings, labelKeys);
|
|
178
|
+
ensureCrmIdentityMappings(mappings);
|
|
179
|
+
applyCrmPropertiesQuery(body);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function resolveCipOperations(body) {
|
|
183
|
+
if (
|
|
184
|
+
body.execution &&
|
|
185
|
+
typeof body.execution === 'object' &&
|
|
186
|
+
/** @type {any} */ (body.execution).cip &&
|
|
187
|
+
typeof /** @type {any} */ (body.execution).cip === 'object'
|
|
188
|
+
) {
|
|
189
|
+
return /** @type {any} */ (body.execution).cip.operations;
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function applyPropertiesToFetchSteps(op, joined) {
|
|
195
|
+
if (!op || typeof op !== 'object' || !Array.isArray(/** @type {any} */ (op).steps)) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
for (const step of /** @type {any} */ (op).steps) {
|
|
199
|
+
if (!step || !step.fetch || typeof step.fetch !== 'object') {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (!step.fetch.query || typeof step.fetch.query !== 'object') {
|
|
203
|
+
step.fetch.query = {};
|
|
204
|
+
}
|
|
205
|
+
step.fetch.query.properties = joined;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Set CIP list/get query.properties from mapped CRM property names.
|
|
211
|
+
* @param {Record<string, unknown>} body
|
|
212
|
+
* @returns {void}
|
|
213
|
+
*/
|
|
214
|
+
function applyCrmPropertiesQuery(body) {
|
|
215
|
+
const propertyNames = collectCrmPropertyNames(body);
|
|
216
|
+
if (propertyNames.length === 0) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const cipOps = resolveCipOperations(body);
|
|
220
|
+
if (!cipOps || typeof cipOps !== 'object') {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const joined = propertyNames.join(',');
|
|
224
|
+
for (const [capKey, op] of Object.entries(cipOps)) {
|
|
225
|
+
const leaf = String(capKey || '')
|
|
226
|
+
.split('.')
|
|
227
|
+
.pop()
|
|
228
|
+
.toLowerCase();
|
|
229
|
+
if (leaf === 'list' || leaf === 'get') {
|
|
230
|
+
applyPropertiesToFetchSteps(op, joined);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
module.exports = {
|
|
236
|
+
seedPropertyKeysOnDatasource,
|
|
237
|
+
collectCrmPropertyNames,
|
|
238
|
+
maybeEnrichCrmStyleFieldMappings,
|
|
239
|
+
applyCrmPropertiesQuery
|
|
240
|
+
};
|