@aifabrix/builder 2.39.3 → 2.40.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.
Files changed (114) hide show
  1. package/.cursor/rules/project-rules.mdc +6 -6
  2. package/README.md +2 -2
  3. package/babel.config.js +6 -0
  4. package/integration/hubspot/README.md +53 -141
  5. package/integration/hubspot/application.yaml +37 -0
  6. package/integration/hubspot/env.template +2 -11
  7. package/integration/hubspot/hubspot-deploy.json +1 -0
  8. package/integration/hubspot/test.js +5 -5
  9. package/lib/api/credentials.api.js +5 -5
  10. package/lib/api/deployments.api.js +2 -2
  11. package/lib/api/pipeline.api.js +17 -17
  12. package/lib/api/wizard.api.js +2 -2
  13. package/lib/app/config.js +11 -6
  14. package/lib/app/deploy-config.js +13 -16
  15. package/lib/app/deploy.js +29 -22
  16. package/lib/app/display.js +1 -1
  17. package/lib/app/dockerfile.js +11 -12
  18. package/lib/app/helpers.js +51 -13
  19. package/lib/app/index.js +14 -2
  20. package/lib/app/prompts.js +37 -45
  21. package/lib/app/push.js +8 -11
  22. package/lib/app/readme.js +16 -12
  23. package/lib/app/register.js +1 -1
  24. package/lib/app/run-helpers.js +31 -22
  25. package/lib/app/run.js +44 -5
  26. package/lib/app/show-display.js +104 -44
  27. package/lib/app/show.js +123 -43
  28. package/lib/build/index.js +11 -18
  29. package/lib/cli/setup-app.js +36 -29
  30. package/lib/cli/setup-auth.js +18 -15
  31. package/lib/cli/setup-credential-deployment.js +3 -1
  32. package/lib/cli/setup-external-system.js +35 -16
  33. package/lib/cli/setup-infra.js +45 -23
  34. package/lib/cli/setup-utility.js +79 -31
  35. package/lib/commands/app-logs.js +28 -20
  36. package/lib/commands/app.js +30 -26
  37. package/lib/commands/convert.js +202 -0
  38. package/lib/commands/credential-list.js +78 -17
  39. package/lib/commands/datasource.js +24 -24
  40. package/lib/commands/deployment-list.js +13 -6
  41. package/lib/commands/up-common.js +80 -42
  42. package/lib/commands/up-dataplane.js +15 -14
  43. package/lib/commands/up-miso.js +15 -14
  44. package/lib/commands/upload.js +163 -0
  45. package/lib/commands/wizard-core.js +5 -4
  46. package/lib/core/diff.js +84 -9
  47. package/lib/core/key-generator.js +9 -12
  48. package/lib/core/secrets-docker-env.js +2 -2
  49. package/lib/core/secrets.js +3 -2
  50. package/lib/core/templates.js +2 -2
  51. package/lib/datasource/deploy.js +2 -1
  52. package/lib/deployment/deployer.js +76 -48
  53. package/lib/external-system/delete.js +0 -1
  54. package/lib/external-system/deploy-helpers.js +5 -6
  55. package/lib/external-system/deploy.js +7 -2
  56. package/lib/external-system/download-helpers.js +4 -4
  57. package/lib/external-system/download.js +11 -10
  58. package/lib/external-system/generator.js +19 -17
  59. package/lib/external-system/test.js +10 -15
  60. package/lib/generator/builders.js +1 -1
  61. package/lib/generator/external-controller-manifest.js +26 -29
  62. package/lib/generator/external-schema-utils.js +6 -18
  63. package/lib/generator/external.js +32 -27
  64. package/lib/generator/github.js +1 -1
  65. package/lib/generator/helpers.js +12 -19
  66. package/lib/generator/index.js +15 -15
  67. package/lib/generator/parse-image.js +35 -0
  68. package/lib/generator/split-readme.js +105 -0
  69. package/lib/generator/split-variables.js +149 -0
  70. package/lib/generator/split.js +86 -246
  71. package/lib/generator/wizard.js +46 -69
  72. package/lib/schema/application-schema.json +4 -4
  73. package/lib/schema/external-datasource.schema.json +5 -0
  74. package/lib/schema/external-system.schema.json +10 -0
  75. package/lib/utils/app-config-resolver.js +52 -0
  76. package/lib/utils/app-register-api.js +1 -1
  77. package/lib/utils/app-register-auth.js +1 -1
  78. package/lib/utils/app-register-config.js +16 -23
  79. package/lib/utils/app-register-validator.js +2 -2
  80. package/lib/utils/cli-utils.js +47 -3
  81. package/lib/utils/config-format.js +154 -0
  82. package/lib/utils/config-paths.js +19 -52
  83. package/lib/utils/config-tokens.js +1 -0
  84. package/lib/utils/docker-build.js +71 -94
  85. package/lib/utils/dockerfile-utils.js +1 -1
  86. package/lib/utils/env-copy.js +4 -4
  87. package/lib/utils/env-ports.js +2 -2
  88. package/lib/utils/error-formatter.js +1 -1
  89. package/lib/utils/error-formatters/validation-errors.js +1 -1
  90. package/lib/utils/external-readme.js +12 -5
  91. package/lib/utils/external-system-test-helpers.js +2 -0
  92. package/lib/utils/health-check.js +55 -66
  93. package/lib/utils/image-version.js +12 -21
  94. package/lib/utils/paths.js +39 -66
  95. package/lib/utils/port-resolver.js +8 -8
  96. package/lib/utils/schema-loader.js +22 -0
  97. package/lib/utils/schema-resolver.js +23 -33
  98. package/lib/utils/secrets-helpers.js +7 -7
  99. package/lib/utils/secrets-utils.js +10 -12
  100. package/lib/utils/template-helpers.js +13 -13
  101. package/lib/utils/token-manager.js +20 -2
  102. package/lib/utils/variable-transformer.js +2 -2
  103. package/lib/validation/validate-display.js +3 -4
  104. package/lib/validation/validate.js +33 -27
  105. package/lib/validation/validator.js +50 -30
  106. package/package.json +2 -1
  107. package/templates/README.md +1 -1
  108. package/templates/applications/README.md.hbs +3 -3
  109. package/templates/applications/miso-controller/env.template +3 -1
  110. package/templates/external-system/README.md.hbs +4 -4
  111. package/integration/hubspot/variables.yaml +0 -17
  112. /package/templates/applications/dataplane/{variables.yaml → application.yaml} +0 -0
  113. /package/templates/applications/keycloak/{variables.yaml → application.yaml} +0 -0
  114. /package/templates/applications/miso-controller/{variables.yaml → application.yaml} +0 -0
@@ -77,14 +77,14 @@ Files under **integration/** and **builder/** are **auto-generated** by the CLI.
77
77
  - **integration/** – External system / wizard output:
78
78
  - Path: `integration/<appName>/` (see `lib/utils/paths.js` → `getIntegrationPath`).
79
79
  - Generated by: `lib/generator/wizard.js` (`generateWizardFiles`, `generateConfigFilesForWizard`), `lib/external-system/download.js`, wizard commands in `lib/commands/wizard-core.js` and `lib/commands/wizard.js`.
80
- - Typical outputs: `variables.yaml`, `env.template`, `README.md`, `*-system.json`, `*-datasource*.json`, `*-deploy.json`, deploy script (`deploy.js`), and optionally `wizard.yaml`, `error.log`.
80
+ - Typical outputs: `application.yaml`, `env.template`, `README.md`, `*-system.json`, `*-datasource*.json`, `*-deploy.json`, deploy script (`deploy.js`), and optionally `wizard.yaml`, `error.log`.
81
81
  - **builder/** – Application (non-external) output:
82
82
  - Path: `builder/<appName>/` or custom root via `AIFABRIX_BUILDER_DIR` (see `lib/utils/paths.js` → `getBuilderPath`).
83
83
  - Generated by: app create/register flow, `lib/generator/index.js`, `lib/commands/up-common.js`, `lib/core/secrets.js`, and related app/deploy logic.
84
- - Typical outputs: `variables.yaml`, `env.template`, deploy JSON, `.env` (from secrets), and app-specific config.
84
+ - Typical outputs: `application.yaml`, `env.template`, deploy JSON, `.env` (from secrets), and app-specific config.
85
85
 
86
86
  **Editable vs generated:**
87
- - Some generated files are **intended to be edited** (e.g. `variables.yaml`, `env.template`, `README.md`, `wizard.yaml`). Improvements to defaults or structure still belong in the generator/templates.
87
+ - Some generated files are **intended to be edited** (e.g. `application.yaml`, `env.template`, `README.md`, `wizard.yaml`). Improvements to defaults or structure still belong in the generator/templates.
88
88
  - **When debugging:** First identify the **source of generation** (which module and function write the file). Fix bugs in that generator or template; avoid treating a one-off edit in integration/ or builder/ as the permanent fix unless it’s a deliberate local override.
89
89
 
90
90
  ### CLI Command Pattern
@@ -340,7 +340,7 @@ async function getItems() {
340
340
  const fs = require('fs').promises;
341
341
  const path = require('path');
342
342
 
343
- const filePath = path.join(process.cwd(), 'builder', appName, 'variables.yaml');
343
+ const filePath = path.join(process.cwd(), 'builder', appName, 'application.yaml');
344
344
  try {
345
345
  const content = await fs.readFileSync(filePath, 'utf8');
346
346
  // Process content
@@ -728,13 +728,13 @@ function validateAppName(appName) {
728
728
  const path = require('path');
729
729
 
730
730
  const appPath = path.join(process.cwd(), 'builder', appName);
731
- const configPath = path.join(appPath, 'variables.yaml');
731
+ const configPath = path.join(appPath, 'application.yaml');
732
732
  ```
733
733
 
734
734
  ### Configuration Loading
735
735
  ```javascript
736
736
  async function loadConfig(appName) {
737
- const configPath = path.join(process.cwd(), 'builder', appName, 'variables.yaml');
737
+ const configPath = path.join(process.cwd(), 'builder', appName, 'application.yaml');
738
738
  const content = await fs.readFile(configPath, 'utf8');
739
739
  return yaml.load(content);
740
740
  }
package/README.md CHANGED
@@ -101,9 +101,9 @@ Create, configure, and run your own AI Fabrix application locally or deploy it (
101
101
 
102
102
  All guides and references are listed in **[docs/README.md](docs/README.md)** (table of contents).
103
103
 
104
- - [CLI Reference](docs/cli-reference.md) – All commands
104
+ - [CLI Commands Reference](docs/commands/README.md) – All commands
105
105
  - [Infrastructure](docs/infrastructure.md) – What runs and why
106
- - [Configuration reference](docs/configuration/README.md) – Config files (deployment key, variables.yaml, env.template, secrets)
106
+ - [Configuration reference](docs/configuration/README.md) – Config files (deployment key, application.yaml, env.template, secrets)
107
107
 
108
108
  ---
109
109
 
@@ -0,0 +1,6 @@
1
+ /** Babel config for Jest (babel-jest). Single file so all workers resolve the same config. */
2
+ // Syntax-only plugin ensures Babel never treats config as "no configuration data" in workers.
3
+ module.exports = {
4
+ presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
5
+ plugins: ['@babel/plugin-syntax-optional-chaining']
6
+ };
@@ -1,184 +1,96 @@
1
1
  # HubSpot CRM Integration
2
2
 
3
- HubSpot CRM external system integration with companies, contacts, and deals datasources.
3
+ HubSpot CRM external system integration with companies, contacts, and deals
4
4
 
5
- ## Overview
5
+ ## System Information
6
6
 
7
- This integration connects to HubSpot CRM API and exposes companies, contacts, and deals data via the AI Fabrix Dataplane. Data is automatically synced and made available for querying via MCP/OpenAPI.
7
+ - **System Key**: `hubspot`
8
+ - **System Type**: `openapi`
9
+ - **Datasources**: 0
8
10
 
9
11
  ## Files
10
12
 
11
- - `variables.yaml` - Application configuration with externalIntegration block
12
- - `hubspot-system.json` - External system definition with OAuth2 authentication
13
- - `hubspot-datasource-company.json` - Companies datasource with field mappings
14
- - `hubspot-datasource-contact.json` - Contacts datasource with field mappings
15
- - `hubspot-datasource-deal.json` - Deals datasource with field mappings
16
- - `hubspot-deploy.json` - Deployment manifest (generated)
17
- - `env.template` - Environment variables template with kv:// references
13
+ - `application.yaml` Application configuration with `app` and `externalIntegration` blocks
14
+ - `hubspot-system.json` External system definition (authentication, OpenAPI/MCP, RBAC)
15
+ - `env.template` Environment variables template (secrets, API keys)
16
+ - `hubspot-deploy.json` Deployment manifest (generated by `aifabrix json`)
18
17
 
19
- ## Setup
18
+ Optional: `rbac.yaml` – Roles and permissions merged into the system when present.
20
19
 
21
- ### 1. Configure OAuth2 Credentials
20
+ ## Quick Start
22
21
 
23
- 1. Register an OAuth2 app in HubSpot:
24
- - Go to HubSpot Settings → Integrations → Private Apps
25
- - Create a new private app
26
- - Grant scopes:
27
- - `crm.objects.companies.read`
28
- - `crm.objects.companies.write`
29
- - `crm.objects.contacts.read`
30
- - `crm.objects.contacts.write`
31
- - `crm.objects.deals.read`
32
- - `crm.objects.deals.write`
33
-
34
- 2. Set credentials via Miso Controller or Dataplane portal:
35
- - Navigate to the HubSpot external system configuration
36
- - Enter OAuth2 Client ID and Client Secret
37
- - Values are automatically stored in Key Vault by the platform
38
- - No manual Key Vault operations required
39
-
40
- **Note:** The platform manages Key Vault storage automatically. You only need to provide values via the interface.
41
-
42
- ### 2. Validate Configuration
22
+ ### 1. Create External System
43
23
 
44
24
  ```bash
45
- aifabrix validate hubspot
25
+ aifabrix create hubspot --type external
46
26
  ```
47
27
 
48
- ### 3. Deploy
28
+ Or use the interactive wizard:
49
29
 
50
30
  ```bash
51
- # Login to controller
52
- aifabrix login --controller http://localhost:3100 --method device --environment dev
53
-
54
- # Register application
55
- aifabrix app register hubspot
31
+ aifabrix wizard --app hubspot
32
+ ```
56
33
 
57
- # Deploy entire system
58
- aifabrix deploy hubspot
34
+ ### 2. Configure Authentication and Datasources
59
35
 
60
- # Or deploy individual datasources for testing
61
- aifabrix datasource deploy hubspot-company --file integration/hubspot/hubspot-datasource-company.json
62
- aifabrix datasource deploy hubspot-contact --file integration/hubspot/hubspot-datasource-contact.json
63
- aifabrix datasource deploy hubspot-deal --file integration/hubspot/hubspot-datasource-deal.json
64
- ```
36
+ Edit files in `integration/hubspot/`:
65
37
 
66
- ## Field Mappings
38
+ - **Authentication**: `hubspot-system.yaml` (auth type, credentials placeholders)
39
+ - **Field mappings**: `hubspot-datasource-*.yaml` (dimensions, attributes, operations)
67
40
 
68
- HubSpot uses a nested properties structure. Field mappings transform this to flat, normalized fields:
41
+ ### 3. Validate Configuration
69
42
 
70
- **HubSpot structure:**
71
- ```json
72
- {
73
- "properties": {
74
- "name": { "value": "Acme Corp" },
75
- "country": { "value": "us" }
76
- }
77
- }
43
+ ```bash
44
+ aifabrix validate hubspot --type external
78
45
  ```
79
46
 
80
- **Normalized structure:**
81
- ```json
82
- {
83
- "name": "Acme Corp",
84
- "country": "US"
85
- }
86
- ```
47
+ ### 4. Generate Deployment Manifest
87
48
 
88
- Transformations applied:
89
- - `trim` - Remove whitespace
90
- - `toLower` - Convert to lowercase (for domains, emails)
91
- - `toUpper` - Convert to uppercase (for country codes)
49
+ ```bash
50
+ aifabrix json hubspot --type external
51
+ ```
92
52
 
93
- ## Datasources
53
+ This creates `hubspot-deploy.json` in `integration/hubspot/`.
94
54
 
95
- ### Companies (`hubspot-company`)
96
- - **Resource Type:** `customer`
97
- - **Access Fields:** `country`, `domain` (for ABAC filtering)
98
- - **Fields:** `id`, `name`, `domain`, `country`, `city`, `industry`, `website`, `phone`, `createdAt`, `updatedAt`
55
+ ### 5. Deploy
99
56
 
100
- ### Contacts (`hubspot-contact`)
101
- - **Resource Type:** `contact`
102
- - **Access Fields:** `email`, `country` (for ABAC filtering)
103
- - **Fields:** `id`, `firstName`, `lastName`, `email`, `phone`, `company`, `jobTitle`, `address`, `city`, `country`, `createdAt`, `updatedAt`
57
+ Controller URL and environment are read from config. Configure and log in first:
104
58
 
105
- ### Deals (`hubspot-deal`)
106
- - **Resource Type:** `deal`
107
- - **Access Fields:** `stage`, `pipeline` (for ABAC filtering)
108
- - **Fields:** `id`, `dealName`, `amount`, `currency`, `stage`, `pipeline`, `closeDate`, `dealType`, `associatedCompany`, `associatedContacts`, `createdAt`, `updatedAt`
59
+ ```bash
60
+ aifabrix auth config --set-controller <url> --set-environment dev
61
+ aifabrix login
62
+ ```
109
63
 
110
- ## OpenAPI Operations
64
+ Then deploy:
111
65
 
112
- All datasources expose full CRUD operations:
113
- - `list` - GET `/crm/v3/objects/{entity}`
114
- - `get` - GET `/crm/v3/objects/{entity}/{id}`
115
- - `create` - POST `/crm/v3/objects/{entity}`
116
- - `update` - PATCH `/crm/v3/objects/{entity}/{id}`
117
- - `delete` - DELETE `/crm/v3/objects/{entity}/{id}`
66
+ ```bash
67
+ aifabrix deploy hubspot
68
+ ```
118
69
 
119
- RBAC permissions are auto-generated: `hubspot.company.list`, `hubspot.company.get`, etc.
70
+ ## Testing
120
71
 
121
- ## Verification
72
+ ### Unit Tests (Local Validation, No API)
122
73
 
123
74
  ```bash
124
- # List datasources
125
- aifabrix datasource list
126
-
127
- # Validate specific datasource
128
- aifabrix datasource validate hubspot-company
75
+ aifabrix test hubspot
129
76
  ```
130
77
 
131
- ## Wizard E2E tests and use case coverage
132
-
133
- The script `integration/hubspot/test.js` runs end-to-end wizard and validation tests. It covers all wizard use cases from [Wizard Guide](../../docs/wizard.md):
134
-
135
- | Use case | Test ID | Description |
136
- |----------|---------|-------------|
137
- | **Headless config (wizard.yaml)** | | |
138
- | Required `appName` | 2.1 | Rejects config missing `appName` |
139
- | Valid `appName` pattern (lowercase, hyphens/underscores) | 2.2 | Rejects uppercase in app name |
140
- | Required `mode` | 2.5 | Rejects invalid `mode` enum |
141
- | Required `source` block | 2.3 | Rejects config without `source` |
142
- | Valid `source.type` | 2.4 | Rejects invalid source type |
143
- | `openapi-file` requires `filePath` | 2.7 | Rejects missing/non-existent OpenAPI file |
144
- | `openapi-url` requires `url` | 2.8 | Rejects `openapi-url` without `url` |
145
- | `known-platform` requires `platform` | 2.6 | Rejects known-platform without `platform` |
146
- | **Mode: add-datasource** | | |
147
- | `systemIdOrKey` required when mode=add-datasource | 2.9 | Rejects add-datasource without systemIdOrKey |
148
- | **Credential** | | |
149
- | `credential.action=select` requires `credentialIdOrKey` | 2.10 | Rejects select without credentialIdOrKey |
150
- | `credential.action=create` requires `config` | 2.11 | Rejects create without config |
151
- | **Positive flows** | | |
152
- | Full wizard with OpenAPI file | 1.1 | Complete flow with local OpenAPI file |
153
- | Wizard with known platform | 1.2 | Flow using known-platform (e.g. HubSpot) |
154
- | Wizard with env var substitution in deployment | 1.6 | `${CONTROLLER_URL}`, `${DATAPLANE_URL}` in wizard.yaml |
155
- | Real credential creation (real-data) | 1.3 | Credential create with real OAuth2 (optional env) |
156
- | **Post-wizard validation (external system)** | | |
157
- | RBAC: permissions reference existing roles | 2.12 | Rejects permission referencing non-existent role |
158
- | RBAC: rbac.yaml valid YAML and structure | 2.13 | Rejects invalid YAML in rbac.yaml |
159
- | Datasource: dimensions required in fieldMappings | 2.14 | Rejects missing dimensions |
160
- | Datasource: dimension key pattern | 2.15 | Rejects invalid dimension key |
161
- | Datasource: attribute path pattern | 2.16 | Rejects invalid attribute path |
162
- | Datasource: dimensions must be object | 2.17 | Rejects dimensions as array |
163
-
164
- **Run tests:**
78
+ ### Integration Tests (Via Dataplane)
165
79
 
166
80
  ```bash
167
- # All tests (positive may skip if dataplane/controller unavailable)
168
- node integration/hubspot/test.js
169
-
170
- # Negative only (no dataplane required)
171
- node integration/hubspot/test.js --type negative
172
-
173
- # Specific test
174
- node integration/hubspot/test.js --test "2.1,2.2"
81
+ aifabrix test-integration hubspot
175
82
  ```
176
83
 
177
- ## Documentation
84
+ ## Deployment
85
+
86
+ Deploy via miso-controller pipeline (same as regular apps). Auth and controller come from `aifabrix login` and `aifabrix auth config`:
178
87
 
179
- - [External Systems Guide](../../docs/external-systems.md) - Complete guide with examples
180
- - [Wizard Guide](../../docs/wizard.md) - Wizard workflow and headless config
181
- - [CLI Reference](../../docs/cli-reference.md) - All commands
182
- - [Configuration Reference](../../docs/CONFIGURATION.md) - Config file details
88
+ ```bash
89
+ aifabrix deploy hubspot
90
+ ```
183
91
 
92
+ ## Troubleshooting
184
93
 
94
+ - **Validation errors**: Run `aifabrix validate hubspot --type external` to see schema and manifest errors.
95
+ - **Deployment / auth**: Run `aifabrix auth config --set-controller <url> --set-environment <env>` and `aifabrix login` before `aifabrix deploy`.
96
+ - **File not found**: Run commands from the project root (where `package.json` and `integration/` live).
@@ -0,0 +1,37 @@
1
+ app:
2
+ key: hubspot
3
+ displayName: HubSpot CRM Integration
4
+ description: HubSpot CRM external system integration with companies, contacts, and deals
5
+ type: external
6
+ configuration:
7
+ - name: HUBSPOT_API_VERSION
8
+ portalInput:
9
+ field: select
10
+ label: HubSpot API Version
11
+ placeholder: Select API version
12
+ options:
13
+ - v1
14
+ - v2
15
+ - v3
16
+ validation:
17
+ required: false
18
+ - name: MAX_PAGE_SIZE
19
+ portalInput:
20
+ field: text
21
+ label: Maximum Page Size
22
+ placeholder: '100'
23
+ validation:
24
+ required: false
25
+ pattern: ^[0-9]+$
26
+ minLength: 1
27
+ maxLength: 1000
28
+ externalIntegration:
29
+ schemaBasePath: ./
30
+ systems:
31
+ - hubspot-system.json
32
+ dataSources:
33
+ - hubspot-datasource-company.json
34
+ - hubspot-datasource-contact.json
35
+ - hubspot-datasource-deal.json
36
+ autopublish: true
37
+ version: 1.0.0
@@ -1,14 +1,5 @@
1
- # HubSpot OAuth2 Configuration
2
- # These values are set via the Miso Controller interface or Dataplane portal
3
- # Values are stored in Key Vault automatically by the platform
4
-
5
1
  CLIENTID=kv://hubspot-clientidKeyVault
6
2
  CLIENTSECRET=kv://hubspot-clientsecretKeyVault
7
3
  TOKENURL=https://api.hubapi.com/oauth/v1/token
8
-
9
- # Optional: test runner (integration/hubspot/test.js) reads all config from this .env
10
- # CONTROLLER_URL=http://localhost:3110
11
- # ENVIRONMENT=miso
12
- # DATAPLANE_URL=
13
- # HUBSPOT_OPENAPI_FILE=integration/hubspot/companies.json
14
-
4
+ HUBSPOT_API_VERSION=v3
5
+ MAX_PAGE_SIZE=100
@@ -3,6 +3,7 @@
3
3
  "displayName": "HubSpot CRM Integration",
4
4
  "description": "HubSpot CRM external system integration with companies, contacts, and deals",
5
5
  "type": "external",
6
+ "version": "1.0.0",
6
7
  "externalIntegration": {
7
8
  "schemaBasePath": "./",
8
9
  "systems": [
@@ -511,7 +511,7 @@ async function checkAppDirectory(appPath) {
511
511
  * @throws {Error} If required files are missing
512
512
  */
513
513
  async function validateRequiredFiles(appPath, entries) {
514
- const requiredFiles = ['variables.yaml', 'env.template', 'README.md', 'deploy.js'];
514
+ const requiredFiles = ['application.yaml', 'env.template', 'README.md', 'deploy.js'];
515
515
  const missingFiles = [];
516
516
  for (const fileName of requiredFiles) {
517
517
  const filePath = path.join(appPath, fileName);
@@ -558,10 +558,10 @@ function validateDeployFiles(appPath, entries) {
558
558
  */
559
559
  async function validateFileContents(appPath, deployFiles) {
560
560
  try {
561
- const variablesContent = await fs.readFile(path.join(appPath, 'variables.yaml'), 'utf8');
561
+ const variablesContent = await fs.readFile(path.join(appPath, 'application.yaml'), 'utf8');
562
562
  yaml.load(variablesContent);
563
563
  } catch (error) {
564
- throw new Error(`Invalid YAML syntax in variables.yaml: ${error.message}`);
564
+ throw new Error(`Invalid YAML syntax in application.yaml: ${error.message}`);
565
565
  }
566
566
  for (const fileName of deployFiles) {
567
567
  try {
@@ -597,7 +597,7 @@ async function validateGeneratedFiles(appName) {
597
597
  * @returns {Promise<Object>} Snapshot of file contents keyed by path
598
598
  */
599
599
  async function captureExternalSnapshot(appPath) {
600
- const variablesPath = path.join(appPath, 'variables.yaml');
600
+ const variablesPath = path.join(appPath, 'application.yaml');
601
601
  const variablesContent = await fs.readFile(variablesPath, 'utf8');
602
602
  const variables = yaml.load(variablesContent);
603
603
 
@@ -608,7 +608,7 @@ async function captureExternalSnapshot(appPath) {
608
608
  const systemFiles = variables.externalIntegration.systems || [];
609
609
  const datasourceFiles = variables.externalIntegration.dataSources || [];
610
610
  const fileNames = [
611
- 'variables.yaml',
611
+ 'application.yaml',
612
612
  'env.template',
613
613
  'README.md',
614
614
  ...systemFiles,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @fileoverview Credentials API functions (controller/dataplane credential list)
2
+ * @fileoverview Credentials API functions (Dataplane credential list)
3
3
  * @author AI Fabrix Team
4
4
  * @version 2.0.0
5
5
  */
@@ -7,13 +7,13 @@
7
7
  const { ApiClient } = require('./index');
8
8
 
9
9
  /**
10
- * List credentials from controller or dataplane
10
+ * List credentials from Dataplane
11
11
  * GET /api/v1/credential
12
- * Used by `aifabrix credential list`. Call with controller or dataplane base URL per deployment.
13
- * @requiresPermission {Dataplane} credential:read (when baseUrl is dataplane; controller may differ)
12
+ * Used by `aifabrix credential list`. The Controller does not expose this endpoint; call with Dataplane base URL.
13
+ * @requiresPermission {Dataplane} credential:read
14
14
  * @async
15
15
  * @function listCredentials
16
- * @param {string} baseUrl - Controller or dataplane base URL
16
+ * @param {string} baseUrl - Dataplane base URL (GET /api/v1/credential is a Dataplane endpoint)
17
17
  * @param {Object} authConfig - Authentication configuration
18
18
  * @param {Object} [options] - List options
19
19
  * @param {boolean} [options.activeOnly] - If true, return only active credentials
@@ -62,8 +62,8 @@ async function deployEnvironment(controllerUrl, envKey, authConfig, deployData)
62
62
  * @param {string} envKey - Environment key
63
63
  * @param {Object} authConfig - Authentication configuration
64
64
  * @param {Object} [options] - List options
65
- * @param {number} [options.page] - Page number
66
- * @property {number} [options.pageSize] - Items per page
65
+ * @param {number} [options.page] - Page number (1-based)
66
+ * @param {number} [options.pageSize] - Items per page
67
67
  * @param {string} [options.sort] - Sort parameter
68
68
  * @param {string} [options.filter] - Filter parameter
69
69
  * @param {string} [options.search] - Search term
@@ -87,15 +87,15 @@ async function getPipelineHealth(controllerUrl, envKey) {
87
87
 
88
88
  /**
89
89
  * Publish one external system via dataplane pipeline endpoint
90
- * POST /api/v1/pipeline/publish
90
+ * POST /api/v1/pipeline/publish (Dataplane OpenAPI operationId: publishExternalSystemViaPipeline)
91
91
  * Request body: external system JSON (external-system.schema.json). Optional field in body:
92
92
  * generateMcpContract (boolean, default true). Optional: generateOpenApiContract (boolean).
93
93
  * Do not use query parameters for MCP; use the field in the body only.
94
- * @requiresPermission {Dataplane} Authenticated (oauth2: [])
94
+ * @requiresPermission {Dataplane} external-system:publish. Auth: OAuth2 (Bearer) or API_KEY only; client id/secret are not accepted.
95
95
  * @async
96
96
  * @function publishSystemViaPipeline
97
97
  * @param {string} dataplaneUrl - Dataplane base URL
98
- * @param {Object} authConfig - Authentication configuration
98
+ * @param {Object} authConfig - Authentication configuration (must include token for Bearer; client id/secret rejected)
99
99
  * @param {Object} systemConfig - External system configuration (conforms to external-system.schema.json)
100
100
  * @returns {Promise<Object>} Published external system response
101
101
  * @throws {Error} If publish fails
@@ -109,9 +109,9 @@ async function publishSystemViaPipeline(dataplaneUrl, authConfig, systemConfig)
109
109
 
110
110
  /**
111
111
  * Publish datasource via dataplane pipeline endpoint
112
- * POST /api/v1/pipeline/{systemKey}/publish
112
+ * POST /api/v1/pipeline/{systemKey}/publish (Dataplane OpenAPI operationId: publishExternalDataSourceViaPipeline)
113
113
  * No generateMcpContract for this endpoint; dataplane always uses default (MCP generated).
114
- * @requiresPermission {Dataplane} Authenticated (oauth2: [])
114
+ * @requiresPermission {Dataplane} external-system:publish. Auth: OAuth2 (Bearer) or API_KEY only; client id/secret are not accepted.
115
115
  * @async
116
116
  * @function publishDatasourceViaPipeline
117
117
  * @param {string} dataplaneUrl - Dataplane base URL
@@ -130,8 +130,8 @@ async function publishDatasourceViaPipeline(dataplaneUrl, systemKey, authConfig,
130
130
 
131
131
  /**
132
132
  * Test datasource via dataplane pipeline endpoint
133
- * POST /api/v1/pipeline/{systemKey}/{datasourceKey}/test
134
- * @requiresPermission {Dataplane} Authenticated (oauth2: [])
133
+ * POST /api/v1/pipeline/{systemKey}/{datasourceKey}/test (Dataplane OpenAPI operationId: testExternalDataSourceViaPipeline)
134
+ * @requiresPermission {Dataplane} external-system:publish or external-data-source:read. Auth: OAuth2 (Bearer) or API_KEY only; client id/secret are not accepted.
135
135
  * @async
136
136
  * @function testDatasourceViaPipeline
137
137
  * @param {Object} params - Function parameters
@@ -161,7 +161,7 @@ async function testDatasourceViaPipeline({ dataplaneUrl, systemKey, datasourceKe
161
161
  /**
162
162
  * Deploy external system via dataplane pipeline endpoint
163
163
  * POST /api/v1/pipeline/deploy
164
- * @requiresPermission {Dataplane} Authenticated (oauth2: [])
164
+ * @requiresPermission {Dataplane} external-system:publish. Auth: OAuth2 (Bearer) or API_KEY only; client id/secret are not accepted.
165
165
  * @async
166
166
  * @function deployExternalSystemViaPipeline
167
167
  * @param {string} dataplaneUrl - Dataplane base URL
@@ -180,7 +180,7 @@ async function deployExternalSystemViaPipeline(dataplaneUrl, authConfig, systemC
180
180
  /**
181
181
  * Deploy datasource via dataplane pipeline endpoint
182
182
  * POST /api/v1/pipeline/{systemKey}/deploy
183
- * @requiresPermission {Dataplane} Authenticated (oauth2: [])
183
+ * @requiresPermission {Dataplane} external-system:publish. Auth: OAuth2 (Bearer) or API_KEY only; client id/secret are not accepted.
184
184
  * @async
185
185
  * @function deployDatasourceViaPipeline
186
186
  * @param {string} dataplaneUrl - Dataplane base URL
@@ -199,15 +199,15 @@ async function deployDatasourceViaPipeline(dataplaneUrl, systemKey, authConfig,
199
199
 
200
200
  /**
201
201
  * Upload application configuration via dataplane pipeline endpoint
202
- * POST /api/v1/pipeline/upload
202
+ * POST /api/v1/pipeline/upload (Dataplane OpenAPI operationId: uploadApplication)
203
203
  * Body: { version, application, dataSources }. Include application.generateMcpContract
204
204
  * and/or application.generateOpenApiContract to control contract generation when
205
205
  * publishing this upload (publish reads from stored config; no query param on publish).
206
- * @requiresPermission {Dataplane} Authenticated (oauth2: [])
206
+ * @requiresPermission {Dataplane} external-system:publish. Auth: OAuth2 (Bearer) or API_KEY only; client id/secret are not accepted.
207
207
  * @async
208
208
  * @function uploadApplicationViaPipeline
209
209
  * @param {string} dataplaneUrl - Dataplane base URL
210
- * @param {Object} authConfig - Authentication configuration
210
+ * @param {Object} authConfig - Authentication configuration (must include token for Bearer; client id/secret rejected)
211
211
  * @param {Object} applicationSchema - { version, application, dataSources }; application may include generateMcpContract, generateOpenApiContract
212
212
  * @returns {Promise<Object>} Upload response with uploadId
213
213
  * @throws {Error} If upload fails
@@ -221,8 +221,8 @@ async function uploadApplicationViaPipeline(dataplaneUrl, authConfig, applicatio
221
221
 
222
222
  /**
223
223
  * Validate upload via dataplane pipeline endpoint
224
- * POST /api/v1/pipeline/upload/{uploadId}/validate
225
- * @requiresPermission {Dataplane} Authenticated (oauth2: [])
224
+ * POST /api/v1/pipeline/upload/{uploadId}/validate (Dataplane OpenAPI operationId: validateApplication)
225
+ * @requiresPermission {Dataplane} external-system:publish. Auth: OAuth2 (Bearer) or API_KEY only; client id/secret are not accepted.
226
226
  * @async
227
227
  * @function validateUploadViaPipeline
228
228
  * @param {string} dataplaneUrl - Dataplane base URL
@@ -238,17 +238,17 @@ async function validateUploadViaPipeline(dataplaneUrl, uploadId, authConfig) {
238
238
 
239
239
  /**
240
240
  * Publish upload via dataplane pipeline endpoint
241
- * POST /api/v1/pipeline/upload/{uploadId}/publish
241
+ * POST /api/v1/pipeline/upload/{uploadId}/publish (Dataplane OpenAPI operationId: publishApplication)
242
242
  * No body or query parameters. MCP/OpenAPI generation is taken from the application config
243
243
  * that was uploaded (application.generateMcpContract, application.generateOpenApiContract).
244
244
  * To control MCP/OpenAPI, include those fields in the application object when calling
245
245
  * uploadApplicationViaPipeline.
246
- * @requiresPermission {Dataplane} Authenticated (oauth2: [])
246
+ * @requiresPermission {Dataplane} external-system:publish. Auth: OAuth2 (Bearer) or API_KEY only; client id/secret are not accepted.
247
247
  * @async
248
248
  * @function publishUploadViaPipeline
249
249
  * @param {string} dataplaneUrl - Dataplane base URL
250
250
  * @param {string} uploadId - Upload ID
251
- * @param {Object} authConfig - Authentication configuration
251
+ * @param {Object} authConfig - Authentication configuration (must include token for Bearer; client id/secret rejected)
252
252
  * @returns {Promise<Object>} Publish response
253
253
  * @throws {Error} If publish fails
254
254
  */
@@ -343,7 +343,7 @@ async function getDeploymentDocs(dataplaneUrl, authConfig, systemKey) {
343
343
  }
344
344
 
345
345
  /**
346
- * Generate deployment documentation with variables.yaml and deploy JSON for better quality
346
+ * Generate deployment documentation with application.yaml and deploy JSON for better quality
347
347
  * POST /api/v1/wizard/deployment-docs/{systemKey}
348
348
  * Sends deployJson and variablesYaml in the request body so the dataplane can align README with the integration folder.
349
349
  * @requiresPermission {Dataplane} external-system:update
@@ -354,7 +354,7 @@ async function getDeploymentDocs(dataplaneUrl, authConfig, systemKey) {
354
354
  * @param {string} systemKey - System key identifier
355
355
  * @param {Object} [body] - Optional request body (WizardDeploymentDocsRequest)
356
356
  * @param {Object} [body.deployJson] - Deploy JSON object (e.g. *-deploy.json content)
357
- * @param {string} [body.variablesYaml] - variables.yaml file content as string
357
+ * @param {string} [body.variablesYaml] - application config file content as string
358
358
  * @returns {Promise<Object>} Deployment documentation response (content, contentType, systemKey)
359
359
  * @throws {Error} If request fails
360
360
  */
package/lib/app/config.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Application Configuration File Generation
3
3
  *
4
- * Generates configuration files for applications (variables.yaml, env.template, rbac.yaml, etc.)
4
+ * Generates configuration files for applications (application.yaml, env.template, rbac.yaml, etc.)
5
5
  *
6
6
  * @fileoverview Configuration file generation for AI Fabrix Builder
7
7
  * @author AI Fabrix Team
@@ -32,18 +32,23 @@ async function fileExists(filePath) {
32
32
  }
33
33
 
34
34
  /**
35
- * Generates variables.yaml file if it doesn't exist
35
+ * Generates application.yaml file if no application config exists
36
36
  * @async
37
37
  * @param {string} appPath - Path to application directory
38
38
  * @param {string} appName - Application name
39
39
  * @param {Object} config - Application configuration
40
40
  */
41
41
  async function generateVariablesYamlFile(appPath, appName, config) {
42
- const variablesPath = path.join(appPath, 'variables.yaml');
43
- if (!(await fileExists(variablesPath))) {
44
- const variablesYaml = generateVariablesYaml(appName, config);
45
- await fs.writeFile(variablesPath, variablesYaml);
42
+ const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
43
+ try {
44
+ resolveApplicationConfigPath(appPath);
45
+ return;
46
+ } catch {
47
+ // No config file; create application.yaml
46
48
  }
49
+ const variablesPath = path.join(appPath, 'application.yaml');
50
+ const variablesYaml = generateVariablesYaml(appName, config);
51
+ await fs.writeFile(variablesPath, variablesYaml);
47
52
  }
48
53
 
49
54
  /**