@aifabrix/builder 2.31.0 → 2.32.1

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.
Files changed (119) hide show
  1. package/README.md +9 -9
  2. package/integration/hubspot/README.md +2 -2
  3. package/integration/hubspot/hubspot-deploy-company.json +17 -14
  4. package/integration/hubspot/hubspot-deploy-contact.json +19 -16
  5. package/integration/hubspot/hubspot-deploy-deal.json +21 -18
  6. package/lib/api/types/datasources.types.js +31 -5
  7. package/lib/api/types/wizard.types.js +142 -0
  8. package/lib/api/wizard.api.js +177 -0
  9. package/lib/{app-config.js → app/config.js} +4 -4
  10. package/lib/{app-deploy.js → app/deploy.js} +8 -8
  11. package/lib/app/display.js +90 -0
  12. package/lib/{app-dockerfile.js → app/dockerfile.js} +4 -4
  13. package/lib/{app-down.js → app/down.js} +4 -4
  14. package/lib/app/helpers.js +218 -0
  15. package/lib/app/index.js +298 -0
  16. package/lib/{app-list.js → app/list.js} +6 -6
  17. package/lib/{app-push.js → app/push.js} +4 -4
  18. package/lib/{app-readme.js → app/readme.js} +34 -13
  19. package/lib/{app-register.js → app/register.js} +9 -9
  20. package/lib/{app-rotate-secret.js → app/rotate-secret.js} +123 -37
  21. package/lib/{app-run-helpers.js → app/run-helpers.js} +10 -10
  22. package/lib/{app-run.js → app/run.js} +6 -6
  23. package/lib/{build.js → build/index.js} +59 -32
  24. package/lib/build/package.json +7 -0
  25. package/lib/cli.js +245 -179
  26. package/lib/commands/app.js +3 -3
  27. package/lib/commands/datasource.js +4 -4
  28. package/lib/commands/login-credentials.js +209 -0
  29. package/lib/commands/login-device.js +254 -0
  30. package/lib/commands/login.js +67 -378
  31. package/lib/commands/logout.js +1 -1
  32. package/lib/commands/secrets-set.js +1 -1
  33. package/lib/commands/secure.js +2 -2
  34. package/lib/commands/wizard.js +498 -0
  35. package/lib/{audit-logger.js → core/audit-logger.js} +1 -1
  36. package/lib/{config.js → core/config.js} +28 -26
  37. package/lib/{diff.js → core/diff.js} +157 -72
  38. package/lib/{secrets.js → core/secrets.js} +86 -49
  39. package/lib/{templates.js → core/templates-env.js} +14 -222
  40. package/lib/core/templates.js +279 -0
  41. package/lib/{datasource-deploy.js → datasource/deploy.js} +6 -6
  42. package/lib/{datasource-diff.js → datasource/diff.js} +2 -2
  43. package/lib/datasource/list.js +223 -0
  44. package/lib/{datasource-validate.js → datasource/validate.js} +2 -2
  45. package/lib/{deployer.js → deployment/deployer.js} +48 -18
  46. package/lib/{environment-deploy.js → deployment/environment.js} +163 -84
  47. package/lib/{push.js → deployment/push.js} +1 -1
  48. package/lib/external-system/deploy-helpers.js +145 -0
  49. package/lib/{external-system-deploy.js → external-system/deploy.js} +156 -111
  50. package/lib/external-system/download-helpers.js +114 -0
  51. package/lib/{external-system-download.js → external-system/download.js} +92 -135
  52. package/lib/{external-system-generator.js → external-system/generator.js} +15 -11
  53. package/lib/external-system/test-auth.js +40 -0
  54. package/lib/external-system/test-execution.js +84 -0
  55. package/lib/external-system/test-helpers.js +109 -0
  56. package/lib/{external-system-test.js → external-system/test.js} +174 -192
  57. package/lib/{generator-builders.js → generator/builders.js} +87 -10
  58. package/lib/{generator-external.js → generator/external.js} +115 -52
  59. package/lib/{github-generator.js → generator/github.js} +116 -15
  60. package/lib/{generator-helpers.js → generator/helpers.js} +92 -42
  61. package/lib/{generator.js → generator/index.js} +49 -22
  62. package/lib/{generator-split.js → generator/split.js} +108 -55
  63. package/lib/generator/wizard-prompts.js +357 -0
  64. package/lib/generator/wizard.js +490 -0
  65. package/lib/{infra.js → infrastructure/index.js} +49 -22
  66. package/lib/schema/external-datasource.schema.json +145 -133
  67. package/lib/schema/external-system.schema.json +42 -0
  68. package/lib/utils/api.js +9 -5
  69. package/lib/utils/app-register-api.js +60 -32
  70. package/lib/utils/app-register-auth.js +172 -47
  71. package/lib/utils/app-register-config.js +130 -59
  72. package/lib/utils/app-run-containers.js +29 -8
  73. package/lib/utils/build-helpers.js +1 -1
  74. package/lib/utils/cli-utils.js +78 -30
  75. package/lib/utils/compose-generator.js +145 -65
  76. package/lib/utils/config-paths.js +2 -0
  77. package/lib/utils/deployment-errors.js +1 -1
  78. package/lib/utils/device-code.js +99 -41
  79. package/lib/utils/env-config-loader.js +1 -1
  80. package/lib/utils/env-copy.js +21 -18
  81. package/lib/utils/env-endpoints.js +115 -67
  82. package/lib/utils/env-map.js +13 -14
  83. package/lib/utils/env-ports.js +45 -25
  84. package/lib/utils/env-template.js +84 -42
  85. package/lib/utils/error-formatter.js +26 -9
  86. package/lib/utils/error-formatters/error-parser.js +90 -4
  87. package/lib/utils/error-formatters/http-status-errors.js +54 -17
  88. package/lib/utils/error-formatters/network-errors.js +103 -26
  89. package/lib/utils/external-system-display.js +184 -90
  90. package/lib/utils/external-system-validators.js +164 -42
  91. package/lib/utils/file-upload.js +109 -0
  92. package/lib/utils/health-check.js +199 -83
  93. package/lib/utils/infra-containers.js +1 -1
  94. package/lib/utils/infra-status.js +66 -15
  95. package/lib/utils/local-secrets.js +45 -25
  96. package/lib/utils/paths.js +45 -33
  97. package/lib/utils/schema-loader.js +42 -25
  98. package/lib/utils/schema-resolver.js +123 -74
  99. package/lib/utils/secrets-encryption.js +62 -25
  100. package/lib/utils/secrets-helpers.js +126 -63
  101. package/lib/utils/secrets-path.js +1 -1
  102. package/lib/utils/secrets-url.js +1 -1
  103. package/lib/utils/token-manager-refresh.js +181 -0
  104. package/lib/utils/token-manager.js +76 -123
  105. package/lib/utils/variable-transformer.js +154 -77
  106. package/lib/utils/yaml-preserve.js +41 -47
  107. package/lib/{template-validator.js → validation/template.js} +54 -23
  108. package/lib/{validate.js → validation/validate.js} +205 -125
  109. package/lib/{validator.js → validation/validator.js} +58 -39
  110. package/package.json +34 -3
  111. package/scripts/install-local.js +210 -0
  112. package/templates/external-system/deploy.ps1.hbs +34 -0
  113. package/templates/external-system/deploy.sh.hbs +34 -0
  114. package/templates/external-system/external-datasource.json.hbs +31 -12
  115. package/lib/app.js +0 -467
  116. package/lib/datasource-list.js +0 -141
  117. /package/lib/{app-prompts.js → app/prompts.js} +0 -0
  118. /package/lib/{env-reader.js → core/env-reader.js} +0 -0
  119. /package/lib/{key-generator.js → core/key-generator.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aifabrix/builder",
3
- "version": "2.31.0",
3
+ "version": "2.32.1",
4
4
  "description": "AI Fabrix Local Fabric & Deployment SDK",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -9,6 +9,7 @@
9
9
  "scripts": {
10
10
  "test": "node tests/scripts/test-wrapper.js",
11
11
  "test:coverage": "jest --config jest.config.coverage.js --coverage --runInBand",
12
+ "test:coverage:nyc": "nyc --reporter=text --reporter=lcov --reporter=html jest --config jest.config.coverage.js --runInBand",
12
13
  "test:watch": "jest --watch",
13
14
  "test:integration": "jest --config jest.config.integration.js --runInBand",
14
15
  "test:integration:python": "cross-env TEST_LANGUAGE=python jest --config jest.config.integration.js --runInBand",
@@ -21,7 +22,9 @@
21
22
  "pack": "npm run build && npm pack",
22
23
  "validate": "npm run build",
23
24
  "prepublishOnly": "npm run validate",
24
- "precommit": "npm run lint:fix && npm run test"
25
+ "precommit": "npm run lint:fix && npm run test",
26
+ "install:local": "node scripts/install-local.js",
27
+ "uninstall:local": "node scripts/install-local.js uninstall"
25
28
  },
26
29
  "keywords": [
27
30
  "aifabrix",
@@ -36,6 +39,32 @@
36
39
  "engines": {
37
40
  "node": ">=18.0.0"
38
41
  },
42
+ "nyc": {
43
+ "all": true,
44
+ "check-coverage": false,
45
+ "reporter": [
46
+ "text",
47
+ "lcov",
48
+ "html"
49
+ ],
50
+ "include": [
51
+ "lib/**/*.js",
52
+ "bin/**/*.js"
53
+ ],
54
+ "exclude": [
55
+ "**/node_modules/**",
56
+ "**/tests/**",
57
+ "lib/infra.js",
58
+ "bin/aifabrix.js"
59
+ ],
60
+ "cache": true,
61
+ "temp-dir": ".nyc_output"
62
+ },
63
+ "pnpm": {
64
+ "overrides": {
65
+ "@bcoe/v8-coverage": "^1.0.2"
66
+ }
67
+ },
39
68
  "dependencies": {
40
69
  "ajv": "^8.12.0",
41
70
  "axios": "^1.6.0",
@@ -47,10 +76,12 @@
47
76
  "ora": "^5.4.1"
48
77
  },
49
78
  "devDependencies": {
79
+ "@bcoe/v8-coverage": "^1.0.2",
50
80
  "@types/node": "^20.10.0",
51
81
  "cross-env": "^10.1.0",
52
82
  "eslint": "^8.55.0",
53
- "jest": "^29.7.0"
83
+ "jest": "^30.2.0",
84
+ "nyc": "^17.1.0"
54
85
  },
55
86
  "repository": {
56
87
  "type": "git",
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable no-console */
3
+
4
+ /**
5
+ * Install local package globally using npm link or pnpm link
6
+ * Automatically detects which package manager is being used
7
+ *
8
+ * @fileoverview Local installation script for @aifabrix/builder
9
+ * @author AI Fabrix Team
10
+ * @version 2.0.0
11
+ */
12
+
13
+ const { execSync } = require('child_process');
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+
17
+ /**
18
+ * Detect which package manager is being used (pnpm or npm)
19
+ * @returns {string} 'pnpm' or 'npm'
20
+ */
21
+ function detectPackageManager() {
22
+ try {
23
+ // Check if pnpm is available
24
+ execSync('which pnpm', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
25
+ return 'pnpm';
26
+ } catch {
27
+ // Fall back to npm
28
+ return 'npm';
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Get currently installed version of aifabrix CLI
34
+ * @returns {string|null} Version string or null if not installed
35
+ */
36
+ function getCurrentVersion() {
37
+ try {
38
+ const version = execSync('aifabrix --version', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
39
+ return version;
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Get version from local package.json
47
+ * @returns {string|null} Version string or null if not found
48
+ */
49
+ function getPackageVersion() {
50
+ try {
51
+ const packageJsonPath = path.join(__dirname, '..', 'package.json');
52
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
53
+ return packageJson.version;
54
+ } catch {
55
+ return null;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Display version comparison information
61
+ * @param {string|null} currentVersion - Currently installed version
62
+ * @param {string|null} packageVersion - Version being linked
63
+ * @returns {void}
64
+ */
65
+ function displayVersionInfo(currentVersion, packageVersion) {
66
+ if (currentVersion) {
67
+ console.log(`📦 Current installed version: ${currentVersion}`);
68
+ } else {
69
+ console.log('📦 No previous version detected (first install)');
70
+ }
71
+
72
+ if (packageVersion) {
73
+ if (currentVersion && currentVersion !== packageVersion) {
74
+ console.log(`🔄 Linking new version: ${packageVersion}`);
75
+ console.log(` Version change: ${currentVersion} → ${packageVersion}\n`);
76
+ } else if (currentVersion && currentVersion === packageVersion) {
77
+ console.log(`🔄 Linking version: ${packageVersion} (same version)\n`);
78
+ } else {
79
+ console.log(`🔄 Linking version: ${packageVersion}\n`);
80
+ }
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Display success message with version information
86
+ * @param {string|null} currentVersion - Version before linking
87
+ * @param {string|null} newVersion - Version after linking
88
+ * @returns {void}
89
+ */
90
+ function displaySuccessMessage(currentVersion, newVersion) {
91
+ console.log('\n✅ Successfully linked!');
92
+ if (currentVersion && newVersion && currentVersion !== newVersion) {
93
+ console.log(`📊 Version updated: ${currentVersion} → ${newVersion}`);
94
+ } else if (newVersion) {
95
+ console.log(`📊 Installed version: ${newVersion}`);
96
+ }
97
+ console.log('Run "aifabrix --version" to verify.');
98
+ }
99
+
100
+ /**
101
+ * Install local package globally
102
+ * @returns {void}
103
+ */
104
+ function installLocal() {
105
+ const pm = detectPackageManager();
106
+ const packageVersion = getPackageVersion();
107
+ const currentVersion = getCurrentVersion();
108
+
109
+ console.log(`Detected package manager: ${pm}\n`);
110
+
111
+ // Show version comparison
112
+ displayVersionInfo(currentVersion, packageVersion);
113
+
114
+ console.log('Linking @aifabrix/builder globally...\n');
115
+
116
+ try {
117
+ if (pm === 'pnpm') {
118
+ execSync('pnpm link --global', { stdio: 'inherit' });
119
+ } else {
120
+ execSync('npm link', { stdio: 'inherit' });
121
+ }
122
+
123
+ // Get new version after linking
124
+ const newVersion = getCurrentVersion();
125
+
126
+ displaySuccessMessage(currentVersion, newVersion);
127
+ } catch (error) {
128
+ console.error('\n❌ Failed to link package:', error.message);
129
+ process.exit(1);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Display version information before unlinking
135
+ * @param {string|null} currentVersion - Currently installed version
136
+ * @param {string|null} packageVersion - Local package version
137
+ * @returns {void}
138
+ */
139
+ function displayUninstallVersionInfo(currentVersion, packageVersion) {
140
+ if (currentVersion) {
141
+ console.log(`📦 Current installed version: ${currentVersion}`);
142
+ } else {
143
+ console.log('📦 No installed version detected');
144
+ }
145
+
146
+ if (packageVersion) {
147
+ console.log(`📋 Local package version: ${packageVersion}`);
148
+ if (currentVersion && currentVersion === packageVersion) {
149
+ console.log(' (matches installed version)\n');
150
+ } else if (currentVersion && currentVersion !== packageVersion) {
151
+ console.log(` (installed: ${currentVersion}, local: ${packageVersion})\n`);
152
+ } else {
153
+ console.log('\n');
154
+ }
155
+ } else {
156
+ console.log('\n');
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Display success message after unlinking
162
+ * @param {string} pm - Package manager ('pnpm' or 'npm')
163
+ * @param {string|null} currentVersion - Version that was uninstalled
164
+ * @returns {void}
165
+ */
166
+ function displayUninstallSuccess(pm, currentVersion) {
167
+ console.log(`\n✅ Successfully unlinked with ${pm}!`);
168
+ if (currentVersion) {
169
+ console.log(`📊 Uninstalled version: ${currentVersion}`);
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Uninstall local package from global installation
175
+ * @returns {void}
176
+ */
177
+ function uninstallLocal() {
178
+ const pm = detectPackageManager();
179
+ const currentVersion = getCurrentVersion();
180
+ const packageVersion = getPackageVersion();
181
+
182
+ console.log(`Detected package manager: ${pm}\n`);
183
+
184
+ // Show version information before unlinking
185
+ displayUninstallVersionInfo(currentVersion, packageVersion);
186
+
187
+ console.log('Unlinking @aifabrix/builder globally...\n');
188
+
189
+ try {
190
+ if (pm === 'pnpm') {
191
+ execSync('pnpm unlink --global @aifabrix/builder', { stdio: 'inherit' });
192
+ displayUninstallSuccess(pm, currentVersion);
193
+ } else {
194
+ execSync('npm unlink -g @aifabrix/builder', { stdio: 'inherit' });
195
+ displayUninstallSuccess(pm, currentVersion);
196
+ }
197
+ } catch (error) {
198
+ console.error('\n❌ Failed to unlink package:', error.message);
199
+ process.exit(1);
200
+ }
201
+ }
202
+
203
+ // Main execution
204
+ const command = process.argv[2];
205
+
206
+ if (command === 'uninstall' || command === 'unlink') {
207
+ uninstallLocal();
208
+ } else {
209
+ installLocal();
210
+ }
@@ -0,0 +1,34 @@
1
+ # Deploy {{systemKey}} external system and datasources using aifabrix CLI
2
+
3
+ $ErrorActionPreference = "Stop"
4
+
5
+ $SCRIPT_DIR = $PSScriptRoot
6
+ $env:ENVIRONMENT = if ($env:ENVIRONMENT) { $env:ENVIRONMENT } else { "dev" }
7
+ $env:CONTROLLER = if ($env:CONTROLLER) { $env:CONTROLLER } else { "http://localhost:3000" }
8
+
9
+ Write-Host "🔍 Validating {{systemKey}} configuration files..."
10
+ {{#each allJsonFiles}}
11
+ aifabrix validate "${SCRIPT_DIR}\{{this}}"
12
+ if ($LASTEXITCODE -ne 0) { exit 1 }
13
+ {{/each}}
14
+
15
+ Write-Host "✅ Validation passed"
16
+
17
+ Write-Host "🚀 Deploying {{systemKey}} external system and datasources..."
18
+ Write-Host " Environment: $env:ENVIRONMENT"
19
+ Write-Host " Controller: $env:CONTROLLER"
20
+
21
+ # Deploy datasources
22
+ {{#each datasourceFileNames}}
23
+ aifabrix datasource deploy {{../systemKey}} "${SCRIPT_DIR}\{{this}}" --environment $env:ENVIRONMENT --controller $env:CONTROLLER
24
+ if ($LASTEXITCODE -ne 0) { exit 1 }
25
+ {{/each}}
26
+
27
+ Write-Host "✅ Deployment complete"
28
+
29
+ # Optional: Run tests
30
+ if ($env:RUN_TESTS -eq "true") {
31
+ Write-Host "🧪 Running integration tests..."
32
+ aifabrix test-integration {{systemKey}} --environment $env:ENVIRONMENT --controller $env:CONTROLLER
33
+ }
34
+
@@ -0,0 +1,34 @@
1
+ #!/bin/bash
2
+ # Deploy {{systemKey}} external system and datasources using aifabrix CLI
3
+
4
+ set -e
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ ENVIRONMENT="${ENVIRONMENT:-dev}"
8
+ CONTROLLER="${CONTROLLER:-http://localhost:3000}"
9
+
10
+ echo "🔍 Validating {{systemKey}} configuration files..."
11
+ {{#each allJsonFiles}}
12
+ aifabrix validate "${SCRIPT_DIR}/{{this}}" || exit 1
13
+ {{/each}}
14
+
15
+ echo "✅ Validation passed"
16
+
17
+ echo "🚀 Deploying {{systemKey}} external system and datasources..."
18
+ echo " Environment: ${ENVIRONMENT}"
19
+ echo " Controller: ${CONTROLLER}"
20
+
21
+ # Deploy datasources
22
+ {{#each datasourceFileNames}}
23
+ aifabrix datasource deploy {{../systemKey}} "${SCRIPT_DIR}/{{this}}" \
24
+ --environment "${ENVIRONMENT}" --controller "${CONTROLLER}" || exit 1
25
+ {{/each}}
26
+
27
+ echo "✅ Deployment complete"
28
+
29
+ # Optional: Run tests
30
+ if [ "${RUN_TESTS:-false}" = "true" ]; then
31
+ echo "🧪 Running integration tests..."
32
+ aifabrix test-integration {{systemKey}} --environment "${ENVIRONMENT}" --controller "${CONTROLLER}"
33
+ fi
34
+
@@ -3,7 +3,7 @@
3
3
  "displayName": "{{datasourceDisplayName}}",
4
4
  "description": "{{datasourceDescription}}",
5
5
  "systemKey": "{{systemKey}}",
6
- "entityKey": "{{entityKey}}",
6
+ "entityType": "{{entityType}}",
7
7
  "resourceType": "{{resourceType}}",
8
8
  "enabled": true,
9
9
  "version": "1.0.0",
@@ -12,41 +12,60 @@
12
12
  "properties": {}
13
13
  },
14
14
  "fieldMappings": {
15
- "accessFields": ["id", "name"],
16
- "fields": {
15
+ "dimensions": {
16
+ {{#if dimensions}}
17
+ {{#each dimensions}}
18
+ "{{@key}}": "{{this}}"{{#unless @last}},{{/unless}}
19
+ {{/each}}
20
+ {{else}}
21
+ "country": "metadata.country",
22
+ "department": "metadata.department"
23
+ {{/if}}
24
+ },
25
+ "attributes": {
26
+ {{#if attributes}}
27
+ {{#each attributes}}
28
+ "{{@key}}": {
29
+ {{#each this}}
30
+ "{{@key}}": {{#if (eq @key "indexed")}}{{this}}{{else}}"{{this}}"{{/if}}{{#unless @last}},{{/unless}}
31
+ {{/each}}
32
+ }{{#unless @last}},{{/unless}}
33
+ {{/each}}
34
+ {{else}}
17
35
  "id": {
18
36
  "expression": "{{raw.id}}",
19
37
  "type": "string",
20
38
  "description": "Unique identifier",
21
- "required": true
39
+ "indexed": true
22
40
  },
23
41
  "name": {
24
42
  "expression": "{{raw.name}}",
25
43
  "type": "string",
26
44
  "description": "Display name",
27
- "required": true
45
+ "indexed": false
28
46
  }
47
+ {{/if}}
29
48
  }
30
49
  },
31
50
  "exposed": {
32
- "fields": ["id", "name"],
33
- "description": "Exposed fields for {{datasourceDisplayName}}"
51
+ "attributes": ["id", "name"],
52
+ "description": "Exposed attributes for {{datasourceDisplayName}}"
34
53
  }{{#if (eq systemType "openapi")}},
35
54
  "openapi": {
36
55
  "enabled": true,
37
56
  "documentKey": "{{systemKey}}-api",
38
57
  "baseUrl": "https://api.example.com",
39
- "resourcePath": "/{{entityKey}}",
58
+ "resourcePath": "/{{entityType}}",
40
59
  "operations": {
41
60
  "list": {
42
- "operationId": "list{{entityKey}}",
61
+ "operationId": "list{{entityType}}",
43
62
  "method": "GET",
44
- "path": "/{{entityKey}}"
63
+ "path": "/{{entityType}}"
45
64
  },
46
65
  "get": {
47
- "operationId": "get{{entityKey}}",
66
+ "operationId": "get{{entityType}}",
48
67
  "method": "GET",
49
- "path": "/{{entityKey}}/{id}"
68
+ "path": "/{{entityType}}/{id}"
50
69
  }
51
70
  },
52
71
  "autoRbac": true