@aifabrix/builder 2.40.2 → 2.42.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 (198) hide show
  1. package/.cursor/rules/docs-rules.mdc +30 -0
  2. package/README.md +7 -5
  3. package/integration/hubspot/README.md +8 -4
  4. package/integration/hubspot/application.json +54 -0
  5. package/integration/hubspot/create-hubspot.js +9 -136
  6. package/integration/hubspot/env.template +3 -4
  7. package/integration/hubspot/hubspot-datasource-company.json +343 -5
  8. package/integration/hubspot/hubspot-datasource-contact.json +413 -5
  9. package/integration/hubspot/hubspot-datasource-deal.json +341 -4
  10. package/integration/hubspot/hubspot-datasource-users.json +116 -0
  11. package/integration/hubspot/hubspot-deploy.json +1250 -108
  12. package/integration/hubspot/hubspot-system.json +15 -32
  13. package/integration/hubspot/test-dataplane-down-tests.js +17 -16
  14. package/integration/hubspot/test-dataplane-down.js +2 -2
  15. package/integration/hubspot/test.js +1 -1
  16. package/jest.config.manual.js +2 -1
  17. package/lib/api/credential.api.js +40 -0
  18. package/lib/api/dev.api.js +423 -0
  19. package/lib/api/external-test.api.js +111 -0
  20. package/lib/api/index.js +42 -19
  21. package/lib/api/pipeline.api.js +66 -120
  22. package/lib/api/types/credential.types.js +23 -0
  23. package/lib/api/types/dev.types.js +140 -0
  24. package/lib/api/types/pipeline.types.js +37 -0
  25. package/lib/api/wizard-platform.api.js +61 -0
  26. package/lib/api/wizard.api.js +34 -1
  27. package/lib/app/config.js +44 -11
  28. package/lib/app/down.js +2 -1
  29. package/lib/app/index.js +12 -1
  30. package/lib/app/prompts.js +44 -29
  31. package/lib/app/push.js +36 -12
  32. package/lib/app/readme.js +9 -6
  33. package/lib/app/run-env-compose.js +264 -0
  34. package/lib/app/run-helpers.js +121 -118
  35. package/lib/app/run.js +148 -28
  36. package/lib/app/show-display.js +1 -1
  37. package/lib/app/show.js +5 -2
  38. package/lib/build/index.js +11 -3
  39. package/lib/cli/setup-app.js +172 -15
  40. package/lib/cli/setup-credential-deployment.js +31 -6
  41. package/lib/cli/setup-dev.js +206 -16
  42. package/lib/cli/setup-environment.js +16 -6
  43. package/lib/cli/setup-external-system.js +89 -24
  44. package/lib/cli/setup-infra.js +82 -15
  45. package/lib/cli/setup-secrets.js +52 -5
  46. package/lib/cli/setup-utility.js +129 -24
  47. package/lib/commands/app-install.js +172 -0
  48. package/lib/commands/app-shell.js +75 -0
  49. package/lib/commands/app-test.js +282 -0
  50. package/lib/commands/app.js +1 -1
  51. package/lib/commands/credential-env.js +162 -0
  52. package/lib/commands/credential-list.js +17 -22
  53. package/lib/commands/credential-push.js +96 -0
  54. package/lib/commands/datasource.js +77 -6
  55. package/lib/commands/dev-cli-handlers.js +141 -0
  56. package/lib/commands/dev-down.js +114 -0
  57. package/lib/commands/dev-init.js +347 -0
  58. package/lib/commands/repair-auth-config.js +99 -0
  59. package/lib/commands/repair-datasource-keys.js +208 -0
  60. package/lib/commands/repair-datasource.js +235 -0
  61. package/lib/commands/repair-env-template.js +348 -0
  62. package/lib/commands/repair-internal.js +85 -0
  63. package/lib/commands/repair-rbac.js +158 -0
  64. package/lib/commands/repair.js +507 -0
  65. package/lib/commands/secrets-list.js +118 -0
  66. package/lib/commands/secrets-remove.js +97 -0
  67. package/lib/commands/secrets-set.js +30 -17
  68. package/lib/commands/secrets-validate.js +50 -0
  69. package/lib/commands/test-e2e-external.js +165 -0
  70. package/lib/commands/up-dataplane.js +2 -2
  71. package/lib/commands/up-miso.js +0 -25
  72. package/lib/commands/upload.js +96 -40
  73. package/lib/commands/wizard-core-helpers.js +226 -4
  74. package/lib/commands/wizard-core.js +67 -29
  75. package/lib/commands/wizard-dataplane.js +1 -1
  76. package/lib/commands/wizard-entity-selection.js +43 -0
  77. package/lib/commands/wizard-headless.js +44 -5
  78. package/lib/commands/wizard-helpers.js +7 -3
  79. package/lib/commands/wizard.js +86 -64
  80. package/lib/core/admin-secrets.js +96 -0
  81. package/lib/core/config.js +7 -1
  82. package/lib/core/secrets-ensure.js +378 -0
  83. package/lib/core/secrets-env-write.js +157 -0
  84. package/lib/core/secrets.js +176 -89
  85. package/lib/datasource/deploy.js +12 -3
  86. package/lib/datasource/field-reference-validator.js +91 -0
  87. package/lib/datasource/test-e2e.js +219 -0
  88. package/lib/datasource/test-integration.js +154 -0
  89. package/lib/datasource/validate.js +21 -3
  90. package/lib/deployment/deployer.js +7 -5
  91. package/lib/deployment/environment-config.js +137 -0
  92. package/lib/deployment/environment.js +21 -98
  93. package/lib/deployment/push.js +32 -2
  94. package/lib/external-system/download.js +188 -203
  95. package/lib/external-system/generator.js +204 -56
  96. package/lib/external-system/test-auth.js +7 -3
  97. package/lib/external-system/test-execution.js +2 -1
  98. package/lib/external-system/test-system-level.js +73 -0
  99. package/lib/external-system/test.js +56 -19
  100. package/lib/generator/external-controller-manifest.js +29 -2
  101. package/lib/generator/external-schema-utils.js +1 -1
  102. package/lib/generator/external.js +10 -3
  103. package/lib/generator/index.js +177 -25
  104. package/lib/generator/split-readme.js +1 -0
  105. package/lib/generator/split-variables.js +7 -1
  106. package/lib/generator/split.js +194 -54
  107. package/lib/generator/wizard-prompts-secondary.js +294 -0
  108. package/lib/generator/wizard-prompts.js +105 -106
  109. package/lib/generator/wizard-readme.js +88 -0
  110. package/lib/generator/wizard.js +155 -158
  111. package/lib/infrastructure/compose.js +11 -1
  112. package/lib/infrastructure/helpers.js +103 -20
  113. package/lib/infrastructure/index.js +98 -12
  114. package/lib/infrastructure/services.js +88 -22
  115. package/lib/schema/application-schema.json +32 -8
  116. package/lib/schema/external-datasource.schema.json +49 -26
  117. package/lib/schema/external-system.schema.json +509 -411
  118. package/lib/schema/wizard-config.schema.json +16 -0
  119. package/lib/utils/api.js +41 -13
  120. package/lib/utils/app-register-auth.js +25 -3
  121. package/lib/utils/auth-headers.js +8 -7
  122. package/lib/utils/cli-utils.js +20 -0
  123. package/lib/utils/compose-generator.js +77 -76
  124. package/lib/utils/compose-handlebars-helpers.js +54 -0
  125. package/lib/utils/compose-vector-helper.js +18 -0
  126. package/lib/utils/config-format-preference.js +51 -0
  127. package/lib/utils/config-format.js +36 -0
  128. package/lib/utils/config-paths.js +127 -2
  129. package/lib/utils/configuration-env-resolver.js +179 -0
  130. package/lib/utils/credential-display.js +83 -0
  131. package/lib/utils/credential-secrets-env.js +357 -0
  132. package/lib/utils/dataplane-pipeline-warning.js +28 -0
  133. package/lib/utils/deployment-validation-helpers.js +4 -4
  134. package/lib/utils/dev-ca-install.js +139 -0
  135. package/lib/utils/dev-cert-helper.js +122 -0
  136. package/lib/utils/device-code-helpers.js +224 -0
  137. package/lib/utils/device-code.js +37 -336
  138. package/lib/utils/docker-build.js +40 -8
  139. package/lib/utils/env-copy.js +103 -13
  140. package/lib/utils/env-map.js +35 -5
  141. package/lib/utils/env-template.js +6 -5
  142. package/lib/utils/error-formatters/http-status-errors.js +20 -2
  143. package/lib/utils/error-formatters/permission-errors.js +0 -1
  144. package/lib/utils/error-formatters/validation-errors.js +0 -1
  145. package/lib/utils/external-readme.js +56 -29
  146. package/lib/utils/external-system-display.js +59 -1
  147. package/lib/utils/external-system-test-helpers.js +21 -8
  148. package/lib/utils/external-system-validators.js +3 -0
  149. package/lib/utils/file-upload.js +20 -50
  150. package/lib/utils/help-builder.js +16 -2
  151. package/lib/utils/infra-status.js +80 -45
  152. package/lib/utils/local-secrets.js +7 -52
  153. package/lib/utils/mutagen-install.js +195 -0
  154. package/lib/utils/mutagen.js +146 -0
  155. package/lib/utils/paths.js +128 -37
  156. package/lib/utils/port-resolver.js +28 -16
  157. package/lib/utils/remote-dev-auth.js +38 -0
  158. package/lib/utils/remote-docker-env.js +43 -0
  159. package/lib/utils/remote-secrets-loader.js +60 -0
  160. package/lib/utils/secrets-canonical.js +93 -0
  161. package/lib/utils/secrets-generator.js +114 -6
  162. package/lib/utils/secrets-helpers.js +108 -114
  163. package/lib/utils/secrets-path.js +2 -2
  164. package/lib/utils/secrets-utils.js +52 -1
  165. package/lib/utils/secrets-validation.js +84 -0
  166. package/lib/utils/ssh-key-helper.js +116 -0
  167. package/lib/utils/test-log-writer.js +56 -0
  168. package/lib/utils/token-manager-messages.js +90 -0
  169. package/lib/utils/token-manager.js +29 -36
  170. package/lib/utils/variable-transformer.js +3 -3
  171. package/lib/validation/env-template-auth.js +157 -0
  172. package/lib/validation/env-template-kv.js +41 -0
  173. package/lib/validation/external-manifest-validator.js +25 -0
  174. package/lib/validation/external-system-auth-rules.js +86 -0
  175. package/lib/validation/validate-batch.js +149 -0
  176. package/lib/validation/validate-datasource-keys-api.js +33 -0
  177. package/lib/validation/validate-display.js +94 -16
  178. package/lib/validation/validate.js +25 -12
  179. package/lib/validation/validator.js +72 -9
  180. package/lib/validation/wizard-datasource-validation.js +50 -0
  181. package/package.json +8 -3
  182. package/scripts/install-local.js +34 -15
  183. package/templates/README.md +0 -1
  184. package/templates/applications/README.md.hbs +4 -4
  185. package/templates/applications/dataplane/application.yaml +6 -5
  186. package/templates/applications/dataplane/env.template +15 -10
  187. package/templates/applications/dataplane/rbac.yaml +2 -2
  188. package/templates/applications/keycloak/env.template +2 -0
  189. package/templates/applications/miso-controller/application.yaml +1 -0
  190. package/templates/applications/miso-controller/env.template +12 -10
  191. package/templates/external-system/README.md.hbs +65 -25
  192. package/templates/external-system/deploy.js.hbs +4 -2
  193. package/templates/external-system/external-datasource.yaml.hbs +217 -0
  194. package/templates/external-system/external-system.json.hbs +1 -18
  195. package/templates/infra/compose.yaml.hbs +6 -0
  196. package/templates/python/docker-compose.hbs +49 -23
  197. package/templates/typescript/docker-compose.hbs +48 -22
  198. package/integration/hubspot/application.yaml +0 -37
@@ -0,0 +1,217 @@
1
+ key: "{{fullDatasourceKey}}"
2
+ displayName: "{{datasourceDisplayName}}"
3
+ description: "{{datasourceDescription}}"
4
+ systemKey: "{{systemKey}}"
5
+ entityType: "{{schemaEntityType}}"
6
+ resourceType: "{{resourceType}}"
7
+ primaryKey:
8
+ {{#each primaryKey}} - "{{this}}"
9
+ {{/each}}
10
+ enabled: true
11
+ version: "1.0.0"
12
+ fieldMappings:
13
+ {{#if dimensions}}
14
+ dimensions:
15
+ {{#each dimensions}}
16
+ {{@key}}: "{{this}}"
17
+ {{/each}}
18
+ {{else}}
19
+ dimensions: {}
20
+ # Optional: add country, department, organization for ABAC
21
+ {{/if}}
22
+ attributes:
23
+ {{#if attributes}}
24
+ {{#each attributes}}
25
+ {{@key}}:
26
+ expression: "{{this.expression}}"
27
+ type: {{this.type}}
28
+ indexed: {{#if this.indexed}}true{{else}}false{{/if}}
29
+ {{/each}}
30
+ {{else}}
31
+ id:
32
+ expression: "{{raw.id}}"
33
+ type: string
34
+ indexed: true
35
+ name:
36
+ expression: "{{raw.name}}"
37
+ type: string
38
+ indexed: false
39
+ {{/if}}
40
+ {{#if (eq systemType "openapi")}}
41
+ openapi:
42
+ enabled: true
43
+ documentKey: "{{systemKey}}-api"
44
+ operations:
45
+ list:
46
+ operationId: "list{{entityKey}}"
47
+ method: GET
48
+ path: "/{{entityKey}}"
49
+ get:
50
+ operationId: "get{{entityKey}}"
51
+ method: GET
52
+ path: "/{{entityKey}}/{id}"
53
+ autoRbac: true
54
+ {{/if}}
55
+
56
+ # --- Optional sections: uncomment or delete as needed ---
57
+ # CIP (Custom Integration Pipeline) supports: fetch, paginate, map, filter, output, pythonInline steps.
58
+ # Operations: list, get, create, update, delete. Pagination: cursor | page | offset.
59
+ {{#if (eq schemaEntityType "recordStorage")}}
60
+ # sync:
61
+ # pull:
62
+ # enabled: true
63
+ # schedule: "0 * * * *"
64
+ # capabilities: [list, get]
65
+ {{/if}}
66
+ {{#if (eq schemaEntityType "documentStorage")}}
67
+ # documentStorage:
68
+ # enabled: true
69
+ # binaryOperationRef: get
70
+ # embeddingField: content
71
+ {{/if}}
72
+ {{#if (eq schemaEntityType "vectorStore")}}
73
+ # vectorStore:
74
+ # enabled: true
75
+ # embeddingModel: "text-embedding-ada-002"
76
+ {{/if}}
77
+ {{#if (eq schemaEntityType "messageService")}}
78
+ # messageService:
79
+ # enabled: true
80
+ # channels: []
81
+ {{/if}}
82
+
83
+ # --- execution: CIP pipeline ---
84
+ # Steps: fetch (openapi/http) → paginate (cursor|page|offset) → map (useFieldMappings, inputPath) → filter (enforceAbac, expression) → output (mode: records)
85
+ # Pagination: cursor=cursorField+cursorParam | page=pageParam+pageSizeParam | offset=offsetParam+pageSizeParam
86
+ # Adjust inputPath to your API ($.results[*], $.items[*], $.value[*], etc.)
87
+ {{#if (eq schemaEntityType "recordStorage")}}
88
+ # execution:
89
+ # engine: cip
90
+ # cip:
91
+ # operations:
92
+ # list:
93
+ # enabled: true
94
+ # description: "List all records"
95
+ # steps:
96
+ # - fetch: { source: openapi, openapiRef: list, query: {} }
97
+ # - paginate: { strategy: cursor, cursorField: "$.paging.next.after", cursorParam: after, pageSize: 100, maxPages: 100 }
98
+ # # Alternative: page → pageParam, pageSizeParam | offset → offsetParam, pageSizeParam
99
+ # - map: { useFieldMappings: true, inputPath: "$.results[*]" }
100
+ # - filter: { enforceAbac: true }
101
+ # # Optional: filter.expression for SQL or JSON filter, e.g. expression: "status = 'active'"
102
+ # - output: { mode: records }
103
+ # get:
104
+ # enabled: true
105
+ # description: "Get record by ID"
106
+ # steps:
107
+ # - fetch: { source: openapi, openapiRef: get, query: {} }
108
+ # - map: { useFieldMappings: true, inputPath: "$" }
109
+ # - filter: { enforceAbac: true }
110
+ # - output: { mode: records }
111
+ # create:
112
+ # steps:
113
+ # - fetch: { source: openapi, openapiRef: create, bodyTemplate: "{{body}}" }
114
+ # - map: { useFieldMappings: true, inputPath: "$" }
115
+ # - output: { mode: records }
116
+ # update:
117
+ # steps:
118
+ # - fetch: { source: openapi, openapiRef: update, bodyTemplate: "{{body}}" }
119
+ # - map: { useFieldMappings: true, inputPath: "$" }
120
+ # - output: { mode: records }
121
+ # delete:
122
+ # steps:
123
+ # - fetch: { source: openapi, openapiRef: delete }
124
+ # - output: { mode: records }
125
+ {{/if}}
126
+ {{#if (eq schemaEntityType "documentStorage")}}
127
+ # execution:
128
+ # engine: cip
129
+ # cip:
130
+ # operations:
131
+ # list:
132
+ # enabled: true
133
+ # description: "List documents"
134
+ # steps:
135
+ # - fetch: { source: openapi, openapiRef: list, query: {} }
136
+ # - paginate: { strategy: offset, offsetParam: skip, pageSizeParam: top, pageSize: 100, maxPages: 100 }
137
+ # - map: { useFieldMappings: true, inputPath: "$.value[*]" }
138
+ # - filter: { enforceAbac: true }
139
+ # - output: { mode: records }
140
+ # get:
141
+ # enabled: true
142
+ # description: "Get document by ID"
143
+ # steps:
144
+ # - fetch: { source: openapi, openapiRef: get, query: {} }
145
+ # - map: { useFieldMappings: true, inputPath: "$" }
146
+ # - filter: { enforceAbac: true }
147
+ # - output: { mode: records }
148
+ # create:
149
+ # enabled: true
150
+ # description: "Upload document"
151
+ # steps:
152
+ # - fetch: { source: openapi, openapiRef: create, bodyTemplate: "{{fileContent}}" }
153
+ # - map: { useFieldMappings: true, inputPath: "$" }
154
+ # - output: { mode: records }
155
+ {{/if}}
156
+ {{#if (eq schemaEntityType "vectorStore")}}
157
+ # execution:
158
+ # engine: cip
159
+ # cip:
160
+ # operations:
161
+ # list:
162
+ # steps:
163
+ # - fetch: { source: openapi, openapiRef: list, query: {} }
164
+ # - map: { useFieldMappings: true, inputPath: "$" }
165
+ # - output: { mode: records }
166
+ # get:
167
+ # steps:
168
+ # - fetch: { source: openapi, openapiRef: get, query: {} }
169
+ # - map: { useFieldMappings: true, inputPath: "$" }
170
+ # - output: { mode: records }
171
+ {{/if}}
172
+ {{#if (eq schemaEntityType "messageService")}}
173
+ # execution:
174
+ # engine: cip
175
+ # cip:
176
+ # operations:
177
+ # list:
178
+ # steps:
179
+ # - fetch: { source: openapi, openapiRef: list, query: {} }
180
+ # - map: { useFieldMappings: true, inputPath: "$" }
181
+ # - output: { mode: records }
182
+ {{/if}}
183
+ {{#if (eq schemaEntityType "none")}}
184
+ # execution:
185
+ # engine: cip
186
+ # cip:
187
+ # operations:
188
+ # list:
189
+ # steps:
190
+ # - fetch: { source: openapi, openapiRef: list, query: {} }
191
+ # - map: { useFieldMappings: true, inputPath: "$" }
192
+ # - output: { mode: records }
193
+ # get:
194
+ # steps:
195
+ # - fetch: { source: openapi, openapiRef: get, query: {} }
196
+ # - map: { useFieldMappings: true, inputPath: "$" }
197
+ # - output: { mode: records }
198
+ {{/if}}
199
+
200
+ # config: ABAC cross-system filters (SQL or JSON)
201
+ # config:
202
+ # abac:
203
+ # crossSystemSql: "country = '{{actor.country}}'"
204
+ # # crossSystemJson: { "dimensions.country": { "eq": "{{actor.country}}" } }
205
+
206
+ # capabilities: [list, get, create, update, delete]
207
+
208
+ # exposed: attributes to expose via MCP/OpenAPI
209
+ # exposed:
210
+ # attributes: [id, name]
211
+
212
+ # metadataSchema: JSON Schema for raw metadata validation
213
+ # metadataSchema:
214
+ # type: object
215
+ # properties:
216
+ # id: { type: string }
217
+ # name: { type: string }
@@ -4,23 +4,7 @@
4
4
  "description": "{{systemDescription}}",
5
5
  "type": "{{systemType}}",
6
6
  "enabled": true,
7
- "authentication": {
8
- "type": "{{authType}}"{{#if (eq authType "oauth2")}},
9
- "oauth2": {
10
- "tokenUrl": "https://api.example.com/oauth/token",
11
- "clientId": "kv://{{systemKey}}-oauth2-client-id",
12
- "clientSecret": "kv://{{systemKey}}-oauth2-client-secret",
13
- "scopes": []
14
- }{{/if}}{{#if (eq authType "apikey")}},
15
- "apikey": {
16
- "headerName": "X-API-Key",
17
- "key": "kv://{{systemKey}}-api-key"
18
- }{{/if}}{{#if (eq authType "basic")}},
19
- "basic": {
20
- "username": "kv://{{systemKey}}-username",
21
- "password": "kv://{{systemKey}}-password"
22
- }{{/if}}
23
- }{{#if (eq systemType "openapi")}},
7
+ "authentication": {{{json authentication}}}{{#if (eq systemType "openapi")}},
24
8
  "openapi": {
25
9
  "documentKey": "{{systemKey}}-api",
26
10
  "autoDiscoverEntities": false
@@ -51,4 +35,3 @@
51
35
  {{/each}}
52
36
  ]{{/if}}
53
37
  }
54
-
@@ -45,6 +45,7 @@ services:
45
45
  retries: 5
46
46
  restart: unless-stopped
47
47
 
48
+ {{#if pgadmin.enabled}}
48
49
  # Optional: pgAdmin for database management
49
50
  pgadmin:
50
51
  image: dpage/pgadmin4:latest
@@ -78,7 +79,9 @@ services:
78
79
  condition: service_healthy
79
80
  networks:
80
81
  - {{networkName}}
82
+ {{/if}}
81
83
 
84
+ {{#if redisCommander.enabled}}
82
85
  # Optional: Redis Commander for Redis management
83
86
  redis-commander:
84
87
  image: rediscommander/redis-commander:latest
@@ -96,6 +99,7 @@ services:
96
99
  condition: service_healthy
97
100
  networks:
98
101
  - {{networkName}}
102
+ {{/if}}
99
103
 
100
104
  {{#if traefik.enabled}}
101
105
  # Traefik Reverse Proxy
@@ -139,9 +143,11 @@ volumes:
139
143
  {{#if (eq devId 0)}}redis_data{{else}}dev{{devId}}_redis_data{{/if}}:
140
144
  name: {{#if (eq devId 0)}}infra_redis_data{{else}}infra_dev{{devId}}_redis_data{{/if}}
141
145
  driver: local
146
+ {{#if pgadmin.enabled}}
142
147
  {{#if (eq devId 0)}}pgadmin_data{{else}}dev{{devId}}_pgadmin_data{{/if}}:
143
148
  name: {{#if (eq devId 0)}}infra_pgadmin_data{{else}}infra_dev{{devId}}_pgadmin_data{{/if}}
144
149
  driver: local
150
+ {{/if}}
145
151
 
146
152
  networks:
147
153
  {{networkName}}:
@@ -25,23 +25,39 @@ services:
25
25
  - "traefik.http.routers.{{app.key}}.middlewares={{app.key}}-stripprefix"
26
26
  {{/unless}}
27
27
  {{/if}}
28
+ environment:
29
+ - MISO_ENVIRONMENT={{misoEnvironment}}
30
+ {{#if reloadStartCommand}}
31
+ - PORT={{containerPort}}
32
+ {{/if}}
28
33
  {{#if traefik.enabled}}
29
34
  {{#unless (eq traefik.path "/")}}
30
- environment:
31
35
  - BASE_PATH={{traefik.path}}
32
36
  - X_FORWARDED_PREFIX={{traefik.path}}
33
37
  {{/unless}}
34
38
  {{/if}}
35
39
  env_file:
36
40
  - {{envFile}}
41
+ {{#if reloadStartCommand}}
42
+ command: ["sh", "-c", "cd /app && {{reloadStartCommand}}"]
43
+ {{/if}}
37
44
  ports:
38
45
  - "{{hostPort}}:{{containerPort}}"
39
46
  networks:
40
47
  - {{networkName}}
48
+ {{#if devMountPath}}
49
+ volumes:
50
+ - {{devMountPath}}:/app
51
+ {{#if requiresStorage}}
52
+ - {{#if (eq devId 0)}}aifabrix_{{app.key}}_data{{else}}aifabrix_dev{{devId}}_{{app.key}}_data{{/if}}:/mnt/data
53
+ {{/if}}
54
+ user: "${AIFABRIX_UID:-1000}:${AIFABRIX_GID:-1000}"
55
+ {{else}}
41
56
  {{#if requiresStorage}}
42
57
  volumes:
43
58
  - {{#if (eq devId 0)}}aifabrix_{{app.key}}_data{{else}}aifabrix_dev{{devId}}_{{app.key}}_data{{/if}}:/mnt/data
44
59
  {{/if}}
60
+ {{/if}}
45
61
  healthcheck:
46
62
  test: ["CMD", "curl", "-f", "http://localhost:{{port}}{{healthCheck.path}}"]
47
63
  interval: {{healthCheck.interval}}s
@@ -56,78 +72,88 @@ services:
56
72
  {{/if}}
57
73
 
58
74
  {{#if requiresDatabase}}
59
- # Database Initialization
75
+ # Database Initialization (uses infra pgpass when available: ~/.aifabrix/infra/pgpass)
76
+ # env_file: .env.run.admin only (POSTGRES_PASSWORD + DB_*); admin secrets never in app container
60
77
  db-init:
61
78
  image: pgvector/pgvector:pg15
62
79
  container_name: {{containerName}}-db-init
63
80
  entrypoint: []
64
81
  env_file:
65
- - ${ADMIN_SECRETS_PATH}
66
- - {{envFile}}
82
+ - {{#if dbInitEnvFile}}{{dbInitEnvFile}}{{else}}{{envFile}}{{/if}}
67
83
  environment:
68
84
  POSTGRES_DB: postgres
69
85
  PGHOST: postgres
70
86
  PGPORT: "5432"
71
87
  PGUSER: pgadmin
72
- {{#if databases}}
73
- {{#each databases}}
74
- DB_{{@index}}_PASSWORD: {{lookup ../databasePasswords.array @index}}
75
- {{/each}}
76
- {{else}}
77
- DB_PASSWORD: {{lookup databasePasswords.array 0}}
88
+ {{#if useInfraPgpass}}
89
+ PGPASSFILE: /run/pgpass
78
90
  {{/if}}
79
91
  networks:
80
92
  - {{networkName}}
81
- volumes: []
93
+ volumes:
94
+ {{#if useInfraPgpass}}
95
+ - {{infraPgpassPath}}:/run/pgpass:ro
96
+ {{else}}
97
+ []
98
+ {{/if}}
82
99
  tmpfs:
83
100
  - /var/lib/postgresql/data
84
101
  command:
85
102
  - sh
86
103
  - -c
87
104
  - |
88
- export PGHOST=postgres PGPORT=5432 PGUSER=pgadmin &&
89
- export PGPASSWORD="${POSTGRES_PASSWORD}" &&
105
+ {{#unless useInfraPgpass}}
106
+ export PGPASSWORD="$${POSTGRES_PASSWORD}" &&
107
+ {{/unless}}
90
108
  echo 'Waiting for PostgreSQL to be ready...' &&
91
109
  counter=0 &&
92
- while [ ${counter:-0} -lt 30 ]; do
93
- if pg_isready -h postgres -p 5432 -U pgadmin >/dev/null 2>&1; then
110
+ while [ $${counter:-0} -lt 30 ]; do
111
+ if pg_isready >/dev/null 2>&1; then
94
112
  echo 'PostgreSQL is ready!'
95
113
  break
96
114
  fi
97
115
  echo 'Waiting for PostgreSQL...'
98
116
  sleep 1
99
- counter=$((${counter:-0} + 1))
117
+ counter=$$(($${counter:-0} + 1))
100
118
  done &&
101
119
  {{#if databases}}
102
120
  {{#each databases}}
103
121
  echo 'Creating {{name}} database and user...' &&
104
- if psql -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{name}}'" 2>/dev/null | grep -q '^1$'; then
105
- echo 'Database "{{name}}" already exists, all ok.'
122
+ if psql -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{name}}'" 2>/dev/null | grep -q '^1$$'; then
123
+ echo 'Database "{{name}}" already exists, syncing user password...' &&
124
+ psql -d postgres -c "ALTER USER \"{{pgUserName name}}\" WITH PASSWORD '"$${DB_{{@index}}_PASSWORD}"';" &&
125
+ echo 'Database "{{name}}" ok.'
106
126
  else
107
127
  echo 'Creating database "{{name}}"...' &&
108
128
  psql -d postgres -c "CREATE DATABASE \"{{name}}\";" &&
109
129
  echo 'Dropping old user if exists...' &&
110
130
  psql -d postgres -c "DROP USER IF EXISTS \"{{pgUserOld name}}\";" || true &&
111
131
  echo 'Creating user "{{pgUserName name}}"...' &&
112
- psql -d postgres -c 'CREATE USER "{{pgUserName name}}" WITH PASSWORD '\''${DB_{{@index}}_PASSWORD}'\'';' &&
132
+ psql -d postgres -c "CREATE USER \"{{pgUserName name}}\" WITH PASSWORD '"$${DB_{{@index}}_PASSWORD}"';" &&
113
133
  echo 'Granting privileges...' &&
114
134
  psql -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE \"{{name}}\" TO \"{{pgUserName name}}\";" &&
115
135
  psql -d {{name}} -c "ALTER SCHEMA public OWNER TO \"{{pgUserName name}}\";" &&
116
136
  psql -d {{name}} -c "GRANT ALL ON SCHEMA public TO \"{{pgUserName name}}\";" &&
117
137
  echo 'Database "{{name}}" created successfully!'
118
138
  fi &&
139
+ {{#each (extensionsForDb this)}}
140
+ (psql -d {{../name}} -c 'CREATE EXTENSION IF NOT EXISTS {{pgQuote this}};' || echo 'Warning: could not create extension {{this}}') &&
141
+ echo 'Extension "{{this}}" enabled on "{{../name}}".' &&
142
+ {{/each}}
119
143
  {{/each}}
120
144
  {{else}}
121
145
  echo 'Creating {{app.key}} database and user...' &&
122
- if psql -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{app.key}}'" 2>/dev/null | grep -q '^1$'; then
123
- echo 'Database "{{app.key}}" already exists, all ok.'
146
+ if psql -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{app.key}}'" 2>/dev/null | grep -q '^1$$'; then
147
+ echo 'Database "{{app.key}}" already exists, syncing user password...' &&
148
+ psql -d postgres -c "ALTER USER \"{{pgUserName app.key}}\" WITH PASSWORD '"$${DB_0_PASSWORD:-$$DB_PASSWORD}"';" &&
149
+ echo 'Database "{{app.key}}" ok.'
124
150
  else
125
151
  echo 'Creating database "{{app.key}}"...' &&
126
152
  psql -d postgres -c "CREATE DATABASE \"{{app.key}}\";" &&
127
153
  echo 'Dropping old user if exists...' &&
128
154
  psql -d postgres -c "DROP USER IF EXISTS \"{{pgUserOld app.key}}\";" || true &&
129
155
  echo 'Creating user "{{pgUserName app.key}}"...' &&
130
- psql -d postgres -c 'CREATE USER "{{pgUserName app.key}}" WITH PASSWORD '\''${DB_0_PASSWORD:-${DB_PASSWORD}}'\'';' &&
156
+ psql -d postgres -c "CREATE USER \"{{pgUserName app.key}}\" WITH PASSWORD '"$${DB_0_PASSWORD:-$$DB_PASSWORD}"';" &&
131
157
  echo 'Granting privileges...' &&
132
158
  psql -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE \"{{app.key}}\" TO \"{{pgUserName app.key}}\";" &&
133
159
  psql -d {{app.key}} -c "ALTER SCHEMA public OWNER TO \"{{pgUserName app.key}}\";" &&
@@ -154,4 +180,4 @@ volumes:
154
180
 
155
181
  networks:
156
182
  {{networkName}}:
157
- external: true
183
+ external: true
@@ -25,23 +25,39 @@ services:
25
25
  - "traefik.http.routers.{{app.key}}.middlewares={{app.key}}-stripprefix"
26
26
  {{/unless}}
27
27
  {{/if}}
28
+ environment:
29
+ - MISO_ENVIRONMENT={{misoEnvironment}}
30
+ {{#if reloadStartCommand}}
31
+ - PORT={{containerPort}}
32
+ {{/if}}
28
33
  {{#if traefik.enabled}}
29
34
  {{#unless (eq traefik.path "/")}}
30
- environment:
31
35
  - BASE_PATH={{traefik.path}}
32
36
  - X_FORWARDED_PREFIX={{traefik.path}}
33
37
  {{/unless}}
34
38
  {{/if}}
35
39
  env_file:
36
40
  - {{envFile}}
41
+ {{#if reloadStartCommand}}
42
+ command: ["sh", "-c", "cd /app && {{reloadStartCommand}}"]
43
+ {{/if}}
37
44
  ports:
38
45
  - "{{hostPort}}:{{containerPort}}"
39
46
  networks:
40
47
  - {{networkName}}
48
+ {{#if devMountPath}}
49
+ volumes:
50
+ - {{devMountPath}}:/app
51
+ {{#if requiresStorage}}
52
+ - {{#if (eq devId 0)}}aifabrix_{{app.key}}_data{{else}}aifabrix_dev{{devId}}_{{app.key}}_data{{/if}}:/mnt/data
53
+ {{/if}}
54
+ user: "${AIFABRIX_UID:-1000}:${AIFABRIX_GID:-1000}"
55
+ {{else}}
41
56
  {{#if requiresStorage}}
42
57
  volumes:
43
58
  - {{#if (eq devId 0)}}aifabrix_{{app.key}}_data{{else}}aifabrix_dev{{devId}}_{{app.key}}_data{{/if}}:/mnt/data
44
59
  {{/if}}
60
+ {{/if}}
45
61
  healthcheck:
46
62
  test: ["CMD", "curl", "-f", "http://localhost:{{port}}{{healthCheck.path}}"]
47
63
  interval: {{healthCheck.interval}}s
@@ -56,78 +72,88 @@ services:
56
72
  {{/if}}
57
73
 
58
74
  {{#if requiresDatabase}}
59
- # Database Initialization
75
+ # Database Initialization (uses infra pgpass when available: ~/.aifabrix/infra/pgpass)
76
+ # env_file: .env.run.admin only (POSTGRES_PASSWORD + DB_*); admin secrets never in app container
60
77
  db-init:
61
78
  image: pgvector/pgvector:pg15
62
79
  container_name: {{containerName}}-db-init
63
80
  entrypoint: []
64
81
  env_file:
65
- - ${ADMIN_SECRETS_PATH}
66
- - {{envFile}}
82
+ - {{#if dbInitEnvFile}}{{dbInitEnvFile}}{{else}}{{envFile}}{{/if}}
67
83
  environment:
68
84
  POSTGRES_DB: postgres
69
85
  PGHOST: postgres
70
86
  PGPORT: "5432"
71
87
  PGUSER: pgadmin
72
- {{#if databases}}
73
- {{#each databases}}
74
- DB_{{@index}}_PASSWORD: {{lookup ../databasePasswords.array @index}}
75
- {{/each}}
76
- {{else}}
77
- DB_PASSWORD: {{lookup databasePasswords.array 0}}
88
+ {{#if useInfraPgpass}}
89
+ PGPASSFILE: /run/pgpass
78
90
  {{/if}}
79
91
  networks:
80
92
  - {{networkName}}
81
- volumes: []
93
+ volumes:
94
+ {{#if useInfraPgpass}}
95
+ - {{infraPgpassPath}}:/run/pgpass:ro
96
+ {{else}}
97
+ []
98
+ {{/if}}
82
99
  tmpfs:
83
100
  - /var/lib/postgresql/data
84
101
  command:
85
102
  - sh
86
103
  - -c
87
104
  - |
88
- export PGHOST=postgres PGPORT=5432 PGUSER=pgadmin &&
89
- export PGPASSWORD="${POSTGRES_PASSWORD}" &&
105
+ {{#unless useInfraPgpass}}
106
+ export PGPASSWORD="$${POSTGRES_PASSWORD}" &&
107
+ {{/unless}}
90
108
  echo 'Waiting for PostgreSQL to be ready...' &&
91
109
  counter=0 &&
92
- while [ ${counter:-0} -lt 30 ]; do
93
- if pg_isready -h postgres -p 5432 -U pgadmin >/dev/null 2>&1; then
110
+ while [ $${counter:-0} -lt 30 ]; do
111
+ if pg_isready >/dev/null 2>&1; then
94
112
  echo 'PostgreSQL is ready!'
95
113
  break
96
114
  fi
97
115
  echo 'Waiting for PostgreSQL...'
98
116
  sleep 1
99
- counter=$((${counter:-0} + 1))
117
+ counter=$$(($${counter:-0} + 1))
100
118
  done &&
101
119
  {{#if databases}}
102
120
  {{#each databases}}
103
121
  echo 'Creating {{name}} database and user...' &&
104
- if psql -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{name}}'" 2>/dev/null | grep -q '^1$'; then
105
- echo 'Database "{{name}}" already exists, all ok.'
122
+ if psql -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{name}}'" 2>/dev/null | grep -q '^1$$'; then
123
+ echo 'Database "{{name}}" already exists, syncing user password...' &&
124
+ psql -d postgres -c "ALTER USER \"{{pgUserName name}}\" WITH PASSWORD '"$${DB_{{@index}}_PASSWORD}"';" &&
125
+ echo 'Database "{{name}}" ok.'
106
126
  else
107
127
  echo 'Creating database "{{name}}"...' &&
108
128
  psql -d postgres -c "CREATE DATABASE \"{{name}}\";" &&
109
129
  echo 'Dropping old user if exists...' &&
110
130
  psql -d postgres -c "DROP USER IF EXISTS \"{{pgUserOld name}}\";" || true &&
111
131
  echo 'Creating user "{{pgUserName name}}"...' &&
112
- psql -d postgres -c 'CREATE USER "{{pgUserName name}}" WITH PASSWORD '\''${DB_{{@index}}_PASSWORD}'\'';' &&
132
+ psql -d postgres -c "CREATE USER \"{{pgUserName name}}\" WITH PASSWORD '"$${DB_{{@index}}_PASSWORD}"';" &&
113
133
  echo 'Granting privileges...' &&
114
134
  psql -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE \"{{name}}\" TO \"{{pgUserName name}}\";" &&
115
135
  psql -d {{name}} -c "ALTER SCHEMA public OWNER TO \"{{pgUserName name}}\";" &&
116
136
  psql -d {{name}} -c "GRANT ALL ON SCHEMA public TO \"{{pgUserName name}}\";" &&
117
137
  echo 'Database "{{name}}" created successfully!'
118
138
  fi &&
139
+ {{#each (extensionsForDb this)}}
140
+ (psql -d {{../name}} -c 'CREATE EXTENSION IF NOT EXISTS {{pgQuote this}};' || echo 'Warning: could not create extension {{this}}') &&
141
+ echo 'Extension "{{this}}" enabled on "{{../name}}".' &&
142
+ {{/each}}
119
143
  {{/each}}
120
144
  {{else}}
121
145
  echo 'Creating {{app.key}} database and user...' &&
122
- if psql -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{app.key}}'" 2>/dev/null | grep -q '^1$'; then
123
- echo 'Database "{{app.key}}" already exists, all ok.'
146
+ if psql -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = '{{app.key}}'" 2>/dev/null | grep -q '^1$$'; then
147
+ echo 'Database "{{app.key}}" already exists, syncing user password...' &&
148
+ psql -d postgres -c "ALTER USER \"{{pgUserName app.key}}\" WITH PASSWORD '"$${DB_0_PASSWORD:-$$DB_PASSWORD}"';" &&
149
+ echo 'Database "{{app.key}}" ok.'
124
150
  else
125
151
  echo 'Creating database "{{app.key}}"...' &&
126
152
  psql -d postgres -c "CREATE DATABASE \"{{app.key}}\";" &&
127
153
  echo 'Dropping old user if exists...' &&
128
154
  psql -d postgres -c "DROP USER IF EXISTS \"{{pgUserOld app.key}}\";" || true &&
129
155
  echo 'Creating user "{{pgUserName app.key}}"...' &&
130
- psql -d postgres -c 'CREATE USER "{{pgUserName app.key}}" WITH PASSWORD '\''${DB_0_PASSWORD:-${DB_PASSWORD}}'\'';' &&
156
+ psql -d postgres -c "CREATE USER \"{{pgUserName app.key}}\" WITH PASSWORD '"$${DB_0_PASSWORD:-$$DB_PASSWORD}"';" &&
131
157
  echo 'Granting privileges...' &&
132
158
  psql -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE \"{{app.key}}\" TO \"{{pgUserName app.key}}\";" &&
133
159
  psql -d {{app.key}} -c "ALTER SCHEMA public OWNER TO \"{{pgUserName app.key}}\";" &&
@@ -1,37 +0,0 @@
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