@friggframework/core 2.0.0--canary.522.cbd3d5a.0 → 2.0.0--canary.517.35ee143.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 (225) hide show
  1. package/CHANGELOG.md +67 -66
  2. package/CLAUDE.md +124 -148
  3. package/README.md +130 -165
  4. package/admin-scripts/index.js +16 -30
  5. package/admin-scripts/repositories/{admin-api-key-repository-documentdb.js → admin-process-repository-documentdb.js} +5 -5
  6. package/admin-scripts/repositories/{admin-api-key-repository-factory.js → admin-process-repository-factory.js} +15 -19
  7. package/admin-scripts/repositories/admin-process-repository-interface.js +150 -0
  8. package/admin-scripts/repositories/admin-process-repository-mongo.js +213 -0
  9. package/admin-scripts/repositories/admin-process-repository-postgres.js +251 -0
  10. package/admin-scripts/repositories/script-schedule-repository-factory.js +2 -6
  11. package/admin-scripts/repositories/script-schedule-repository-interface.js +14 -36
  12. package/admin-scripts/repositories/script-schedule-repository-mongo.js +13 -25
  13. package/admin-scripts/repositories/script-schedule-repository-postgres.js +13 -25
  14. package/application/commands/admin-script-commands.js +102 -266
  15. package/application/commands/integration-commands.js +6 -12
  16. package/application/index.js +3 -1
  17. package/assertions/get.js +4 -1
  18. package/associations/association.js +57 -59
  19. package/associations/model.js +41 -41
  20. package/core/CLAUDE.md +156 -222
  21. package/core/Worker.js +1 -5
  22. package/credential/repositories/credential-repository-documentdb.js +1 -71
  23. package/credential/repositories/credential-repository-interface.js +2 -8
  24. package/credential/repositories/credential-repository-mongo.js +4 -45
  25. package/credential/repositories/credential-repository-postgres.js +3 -44
  26. package/credential/repositories/credential-repository.js +4 -6
  27. package/credential/use-cases/get-credential-for-user.js +3 -21
  28. package/credential/use-cases/update-authentication-status.js +2 -5
  29. package/database/MONGODB_TRANSACTION_FIX.md +52 -72
  30. package/database/adapters/lambda-invoker.js +7 -8
  31. package/database/config.js +13 -15
  32. package/database/documentdb-encryption-service.js +13 -29
  33. package/database/documentdb-utils.js +12 -21
  34. package/database/encryption/README.md +36 -53
  35. package/database/encryption/encryption-schema-registry.js +9 -21
  36. package/database/encryption/field-encryption-service.js +4 -15
  37. package/database/encryption/logger.js +2 -3
  38. package/database/encryption/prisma-encryption-extension.js +8 -5
  39. package/database/index.js +2 -4
  40. package/database/models/IndividualUser.js +15 -15
  41. package/database/models/OrganizationUser.js +4 -6
  42. package/database/models/UserModel.js +2 -2
  43. package/database/models/WebsocketConnection.js +1 -4
  44. package/database/mongoose.js +2 -2
  45. package/database/prisma.js +14 -22
  46. package/database/repositories/health-check-repository-documentdb.js +7 -22
  47. package/database/repositories/health-check-repository-factory.js +3 -9
  48. package/database/repositories/health-check-repository-interface.js +5 -15
  49. package/database/repositories/health-check-repository-mongodb.js +6 -9
  50. package/database/repositories/health-check-repository-postgres.js +1 -1
  51. package/database/repositories/migration-status-repository-s3.js +5 -10
  52. package/database/use-cases/check-database-health-use-case.js +2 -3
  53. package/database/use-cases/check-database-state-use-case.js +7 -9
  54. package/database/use-cases/get-database-state-via-worker-use-case.js +12 -15
  55. package/database/use-cases/get-migration-status-use-case.js +2 -4
  56. package/database/use-cases/run-database-migration-use-case.js +9 -41
  57. package/database/use-cases/test-encryption-use-case.js +5 -4
  58. package/database/use-cases/trigger-database-migration-use-case.js +8 -9
  59. package/database/utils/mongodb-collection-utils.js +3 -11
  60. package/database/utils/mongodb-schema-init.js +4 -10
  61. package/database/utils/prisma-runner.js +74 -144
  62. package/database/utils/prisma-schema-parser.js +2 -2
  63. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +80 -135
  64. package/encrypt/Cryptor.js +2 -8
  65. package/errors/fetch-error.js +1 -1
  66. package/generated/prisma-mongodb/edge.js +16 -59
  67. package/generated/prisma-mongodb/index-browser.js +12 -62
  68. package/generated/prisma-mongodb/index.d.ts +4850 -8136
  69. package/generated/prisma-mongodb/index.js +16 -59
  70. package/generated/prisma-mongodb/package.json +1 -1
  71. package/generated/prisma-mongodb/schema.prisma +33 -75
  72. package/generated/prisma-mongodb/wasm.js +16 -59
  73. package/generated/prisma-postgresql/edge.js +15 -59
  74. package/generated/prisma-postgresql/index-browser.js +11 -62
  75. package/generated/prisma-postgresql/index.d.ts +5963 -8930
  76. package/generated/prisma-postgresql/index.js +15 -59
  77. package/generated/prisma-postgresql/package.json +1 -1
  78. package/generated/prisma-postgresql/schema.prisma +33 -73
  79. package/generated/prisma-postgresql/wasm.js +15 -59
  80. package/handlers/WEBHOOKS.md +81 -104
  81. package/handlers/app-definition-loader.js +1 -1
  82. package/handlers/app-handler-helpers.js +2 -14
  83. package/handlers/backend-utils.js +1 -0
  84. package/handlers/database-migration-handler.js +45 -64
  85. package/handlers/middleware/admin-auth.js +53 -0
  86. package/handlers/routers/HEALTHCHECK.md +135 -170
  87. package/handlers/routers/auth.js +2 -23
  88. package/handlers/routers/db-migration.handler.js +3 -2
  89. package/handlers/routers/db-migration.js +33 -69
  90. package/handlers/routers/health.js +8 -23
  91. package/handlers/routers/integration-defined-routers.js +4 -4
  92. package/handlers/routers/integration-webhook-routers.js +7 -17
  93. package/handlers/routers/websocket.js +3 -9
  94. package/handlers/use-cases/check-integrations-health-use-case.js +6 -13
  95. package/handlers/workers/db-migration.js +26 -54
  96. package/index.js +9 -5
  97. package/integrations/WEBHOOK-QUICKSTART.md +14 -21
  98. package/integrations/index.js +0 -4
  99. package/integrations/integration-base.js +6 -9
  100. package/integrations/integration-router.js +146 -1817
  101. package/integrations/options.js +20 -47
  102. package/integrations/repositories/integration-repository-documentdb.js +24 -53
  103. package/integrations/repositories/integration-repository-factory.js +2 -6
  104. package/integrations/repositories/integration-repository-interface.js +9 -27
  105. package/integrations/repositories/integration-repository-postgres.js +3 -3
  106. package/integrations/repositories/process-repository-factory.js +1 -0
  107. package/integrations/repositories/process-repository-interface.js +5 -9
  108. package/integrations/repositories/process-repository-mongo.js +3 -7
  109. package/integrations/repositories/process-repository-postgres.js +2 -2
  110. package/integrations/tests/doubles/config-capturing-integration.js +8 -9
  111. package/integrations/tests/doubles/dummy-integration-class.js +8 -81
  112. package/integrations/tests/doubles/test-integration-repository.js +11 -51
  113. package/integrations/use-cases/create-integration.js +32 -36
  114. package/integrations/use-cases/create-process.js +9 -20
  115. package/integrations/use-cases/delete-integration-for-user.js +4 -5
  116. package/integrations/use-cases/get-integration-for-user.js +10 -25
  117. package/integrations/use-cases/get-integration-instance-by-definition.js +7 -13
  118. package/integrations/use-cases/get-integrations-for-user.js +1 -4
  119. package/integrations/use-cases/get-possible-integrations.js +1 -1
  120. package/integrations/use-cases/get-process.js +6 -5
  121. package/integrations/use-cases/index.js +1 -3
  122. package/integrations/use-cases/load-integration-context.js +5 -1
  123. package/integrations/use-cases/update-process-state.js +8 -10
  124. package/integrations/utils/map-integration-dto.js +3 -9
  125. package/jest-setup.js +1 -1
  126. package/jest-teardown.js +1 -1
  127. package/lambda/TimeoutCatcher.js +30 -32
  128. package/lambda/index.js +1 -1
  129. package/logs/index.js +3 -3
  130. package/modules/module.js +1 -3
  131. package/modules/repositories/module-repository-documentdb.js +48 -114
  132. package/modules/repositories/module-repository-interface.js +0 -13
  133. package/modules/repositories/module-repository-mongo.js +6 -46
  134. package/modules/repositories/module-repository-postgres.js +6 -48
  135. package/modules/repositories/module-repository.js +1 -34
  136. package/modules/requester/api-key.js +2 -0
  137. package/modules/requester/basic.js +1 -0
  138. package/modules/requester/oauth-2.js +2 -3
  139. package/modules/test/mock-api/definition.js +10 -15
  140. package/modules/test/mock-api/mocks/hubspot.js +36 -36
  141. package/modules/tests/doubles/test-module-factory.js +4 -10
  142. package/modules/tests/doubles/test-module-repository.js +1 -1
  143. package/modules/use-cases/get-entities-for-user.js +1 -1
  144. package/modules/use-cases/get-entity-options-by-id.js +6 -8
  145. package/modules/use-cases/get-module.js +9 -12
  146. package/modules/use-cases/process-authorization-callback.js +6 -12
  147. package/modules/use-cases/refresh-entity-options.js +6 -8
  148. package/modules/use-cases/test-module-auth.js +6 -8
  149. package/modules/utils/map-module-dto.js +2 -2
  150. package/package.json +5 -7
  151. package/prisma-mongodb/schema.prisma +33 -75
  152. package/prisma-postgresql/schema.prisma +33 -73
  153. package/queues/queuer-util.js +1 -5
  154. package/syncs/model.js +51 -51
  155. package/syncs/repositories/sync-repository-documentdb.js +19 -39
  156. package/syncs/repositories/sync-repository-interface.js +2 -6
  157. package/syncs/repositories/sync-repository-postgres.js +13 -19
  158. package/syncs/sync.js +100 -104
  159. package/token/repositories/token-repository-factory.js +3 -1
  160. package/types/assertions/index.d.ts +72 -72
  161. package/types/associations/index.d.ts +57 -57
  162. package/types/core/index.d.ts +53 -59
  163. package/types/database/index.d.ts +2 -2
  164. package/types/encrypt/index.d.ts +3 -3
  165. package/types/errors/index.d.ts +54 -61
  166. package/types/eslint-config/index.d.ts +40 -40
  167. package/types/integrations/index.d.ts +183 -185
  168. package/types/lambda/index.d.ts +26 -26
  169. package/types/logs/index.d.ts +4 -4
  170. package/types/module-plugin/index.d.ts +237 -239
  171. package/types/prettier-config/index.d.ts +5 -5
  172. package/types/syncs/index.d.ts +108 -102
  173. package/types/test-environment/index.d.ts +14 -14
  174. package/types/tsconfig.json +93 -95
  175. package/user/tests/doubles/test-user-repository.js +2 -5
  176. package/user/use-cases/authenticate-user.js +4 -2
  177. package/user/use-cases/authenticate-with-shared-secret.js +1 -1
  178. package/user/use-cases/create-individual-user.js +7 -8
  179. package/user/use-cases/create-organization-user.js +1 -1
  180. package/user/use-cases/create-token-for-user-id.js +1 -1
  181. package/user/use-cases/get-user-from-adopter-jwt.js +2 -0
  182. package/user/use-cases/get-user-from-bearer-token.js +3 -7
  183. package/user/use-cases/get-user-from-x-frigg-headers.js +11 -14
  184. package/user/use-cases/login-user.js +8 -8
  185. package/user/user.js +4 -18
  186. package/utils/backend-path.js +2 -2
  187. package/utils/index.js +1 -4
  188. package/websocket/repositories/websocket-connection-repository-documentdb.js +8 -21
  189. package/websocket/repositories/websocket-connection-repository-mongo.js +4 -8
  190. package/websocket/repositories/websocket-connection-repository-postgres.js +4 -8
  191. package/websocket/repositories/websocket-connection-repository.js +4 -8
  192. package/admin-scripts/repositories/admin-api-key-repository-interface.js +0 -121
  193. package/admin-scripts/repositories/admin-api-key-repository-mongo.js +0 -155
  194. package/admin-scripts/repositories/admin-api-key-repository-postgres.js +0 -189
  195. package/admin-scripts/repositories/script-execution-repository-documentdb.js +0 -21
  196. package/admin-scripts/repositories/script-execution-repository-factory.js +0 -55
  197. package/admin-scripts/repositories/script-execution-repository-interface.js +0 -193
  198. package/admin-scripts/repositories/script-execution-repository-mongo.js +0 -278
  199. package/admin-scripts/repositories/script-execution-repository-postgres.js +0 -320
  200. package/credential/credential-router.js +0 -262
  201. package/credential/use-cases/delete-credential-for-user.js +0 -50
  202. package/credential/use-cases/list-credentials-for-user.js +0 -31
  203. package/credential/use-cases/reauthorize-credential.js +0 -103
  204. package/handlers/routers/admin.js +0 -450
  205. package/handlers/routers/docs.js +0 -180
  206. package/handlers/routers/middleware/loadUser.js +0 -39
  207. package/handlers/routers/middleware/requireAdmin.js +0 -41
  208. package/handlers/routers/middleware/requireLoggedInUser.js +0 -19
  209. package/integrations/use-cases/execute-proxy-request.js +0 -564
  210. package/modules/domain/entities/AuthorizationSession.js +0 -131
  211. package/modules/domain/entities/index.js +0 -10
  212. package/modules/repositories/authorization-session-repository-factory.js +0 -55
  213. package/modules/repositories/authorization-session-repository-interface.js +0 -75
  214. package/modules/repositories/authorization-session-repository-mongo.js +0 -169
  215. package/modules/repositories/authorization-session-repository-postgres.js +0 -170
  216. package/modules/use-cases/delete-module-entity.js +0 -23
  217. package/modules/use-cases/get-authorization-requirements.js +0 -110
  218. package/modules/use-cases/get-module-entity-by-id.js +0 -16
  219. package/modules/use-cases/process-authorization-step.js +0 -160
  220. package/modules/use-cases/start-authorization-session.js +0 -86
  221. package/modules/use-cases/update-module-entity.js +0 -27
  222. package/openapi/openapi-spec-generator.js +0 -370
  223. package/openapi/openapi-v1.yaml +0 -1360
  224. package/openapi/openapi-v2.yaml +0 -1535
  225. package/user/use-cases/delete-user.js +0 -47
@@ -1,370 +0,0 @@
1
- /**
2
- * Dynamic OpenAPI Spec Generator
3
- *
4
- * Generates OpenAPI specifications dynamically from appDefinition and installed modules.
5
- * Supports both v1 (legacy) and v2 (current) API versions.
6
- *
7
- * Usage:
8
- * const { generateOpenApiSpecV1, generateOpenApiSpecV2 } = require('./openapi-spec-generator');
9
- * const v1Spec = generateOpenApiSpecV1(appDefinition, { serverUrl });
10
- * const v2Spec = generateOpenApiSpecV2(appDefinition, { serverUrl });
11
- */
12
-
13
- const path = require('path');
14
- const fs = require('fs');
15
- const yaml = require('js-yaml');
16
-
17
- const V1_SPEC_PATH = path.join(__dirname, 'openapi-v1.yaml');
18
- const V2_SPEC_PATH = path.join(__dirname, 'openapi-v2.yaml');
19
-
20
- // Separate caches for each version
21
- const cache = {
22
- v1: { spec: null, modules: null },
23
- v2: { spec: null, modules: null },
24
- legacy: { spec: null, modules: null },
25
- };
26
-
27
- /**
28
- * Load a YAML spec file
29
- * @param {string} specPath - Path to the YAML file
30
- * @returns {Object} Parsed spec object
31
- */
32
- function loadSpecFile(specPath) {
33
- if (!fs.existsSync(specPath)) {
34
- throw new Error(`OpenAPI spec not found: ${specPath}`);
35
- }
36
- const specContent = fs.readFileSync(specPath, 'utf8');
37
- return yaml.load(specContent);
38
- }
39
-
40
- /**
41
- * Load the base OpenAPI spec (defaults to v2)
42
- * @deprecated Use loadV1Spec or loadV2Spec instead
43
- */
44
- function loadBaseSpec() {
45
- return loadSpecFile(V2_SPEC_PATH);
46
- }
47
-
48
- /**
49
- * Load the v1 OpenAPI spec
50
- */
51
- function loadV1Spec() {
52
- return loadSpecFile(V1_SPEC_PATH);
53
- }
54
-
55
- /**
56
- * Load the v2 OpenAPI spec
57
- */
58
- function loadV2Spec() {
59
- return loadSpecFile(V2_SPEC_PATH);
60
- }
61
-
62
- /**
63
- * Extract module metadata for OpenAPI documentation
64
- * @param {Object} moduleDefinition - Module definition object
65
- * @returns {Object} Module metadata
66
- */
67
- function extractModuleMetadata(moduleDefinition) {
68
- const Definition = moduleDefinition.Definition || moduleDefinition;
69
- const name = Definition?.getName?.() || Definition?.name || 'unknown';
70
- const displayName = Definition?.display?.name || name;
71
- const description =
72
- Definition?.display?.description || `${displayName} integration`;
73
- const moduleName = Definition?.moduleName || name;
74
-
75
- // Extract auth type from first module
76
- const moduleKeys = Object.keys(Definition?.modules || {});
77
- const firstModule =
78
- moduleKeys.length > 0 ? Definition.modules[moduleKeys[0]] : null;
79
- const authType =
80
- firstModule?.definition?.getAuthType?.() ||
81
- firstModule?.authType ||
82
- 'oauth2';
83
- const stepCount = firstModule?.definition?.getAuthStepCount?.() || 1;
84
-
85
- return {
86
- name,
87
- displayName,
88
- description,
89
- moduleName,
90
- authType,
91
- stepCount,
92
- isMultiStep: stepCount > 1,
93
- hasOptions: typeof Definition?.Options !== 'undefined',
94
- hasEvents: typeof Definition?.events !== 'undefined',
95
- capabilities: firstModule?.definition?.getCapabilities?.() || [],
96
- };
97
- }
98
-
99
- /**
100
- * Enrich spec with installed module information
101
- * @param {Object} spec - OpenAPI spec object
102
- * @param {Array} installedModules - Array of module metadata
103
- * @returns {Object} Enriched spec
104
- */
105
- function enrichSpecWithModules(spec, installedModules) {
106
- if (!installedModules.length) return spec;
107
-
108
- // Update ListEntityTypesResponse with actual modules
109
- if (spec.components?.schemas?.ListEntityTypesResponse) {
110
- spec.components.schemas.ListEntityTypesResponse.properties.types.example =
111
- installedModules.map((m) => ({
112
- type: m.name,
113
- name: m.displayName,
114
- description: m.description,
115
- authType: m.authType,
116
- isMultiStep: m.isMultiStep,
117
- stepCount: m.stepCount,
118
- }));
119
- }
120
-
121
- // Update IntegrationOption examples
122
- if (spec.components?.schemas?.IntegrationOption) {
123
- const examples = installedModules.slice(0, 3).map((m) => ({
124
- type: m.name,
125
- name: m.displayName,
126
- description: m.description,
127
- hasAuth: true,
128
- }));
129
- if (
130
- spec.components.schemas.ListIntegrationOptionsResponse?.properties
131
- ?.integrations
132
- ) {
133
- spec.components.schemas.ListIntegrationOptionsResponse.properties.integrations.example =
134
- examples;
135
- }
136
- }
137
-
138
- // Add module-specific enum values to parameters
139
- const moduleNames = installedModules.map((m) => m.name);
140
- if (moduleNames.length > 0) {
141
- Object.values(spec.paths || {}).forEach((pathItem) => {
142
- Object.values(pathItem).forEach((operation) => {
143
- if (operation.parameters) {
144
- operation.parameters.forEach((param) => {
145
- if (
146
- param.name === 'entityType' ||
147
- param.name === 'typeName' ||
148
- param.name === 'moduleType'
149
- ) {
150
- param.schema = param.schema || { type: 'string' };
151
- param.schema.enum = moduleNames;
152
- param.schema.example = moduleNames[0];
153
- }
154
- });
155
- }
156
- });
157
- });
158
- }
159
-
160
- // Add installed modules section to spec info
161
- const moduleList = installedModules
162
- .map((m) => `- **${m.displayName}** (\`${m.name}\`): ${m.description}`)
163
- .join('\n');
164
-
165
- spec.info.description = `${
166
- spec.info.description || ''
167
- }\n\n## Installed Modules\n${moduleList}`;
168
-
169
- return spec;
170
- }
171
-
172
- /**
173
- * Extract installed modules from appDefinition
174
- * @param {Object} appDefinition - App definition object
175
- * @returns {Array} Array of module metadata
176
- */
177
- function extractInstalledModules(appDefinition) {
178
- const installedModules = [];
179
-
180
- if (appDefinition?.integrations) {
181
- appDefinition.integrations.forEach((integration) => {
182
- try {
183
- const metadata = extractModuleMetadata(integration);
184
- if (metadata.name !== 'unknown') {
185
- installedModules.push(metadata);
186
- }
187
- } catch (e) {
188
- // Skip modules that can't be processed
189
- }
190
- });
191
- }
192
-
193
- return installedModules;
194
- }
195
-
196
- /**
197
- * Add server URL and generation metadata to spec
198
- * @param {Object} spec - OpenAPI spec
199
- * @param {Object} options - Options including serverUrl
200
- * @param {Array} installedModules - Installed modules for metadata
201
- * @returns {Object} Updated spec
202
- */
203
- function finalizeSpec(spec, options, installedModules) {
204
- const { serverUrl } = options;
205
-
206
- // Add custom server URL if provided
207
- if (serverUrl) {
208
- spec.servers = [
209
- { url: serverUrl, description: 'Current server' },
210
- ...(spec.servers || []),
211
- ];
212
- }
213
-
214
- // Add generation metadata
215
- spec.info['x-generated'] = {
216
- timestamp: new Date().toISOString(),
217
- moduleCount: installedModules.length,
218
- modules: installedModules.map((m) => m.name),
219
- };
220
-
221
- return spec;
222
- }
223
-
224
- /**
225
- * Generate v1 (legacy) OpenAPI spec from appDefinition
226
- * @param {Object} appDefinition - The app definition containing integrations
227
- * @param {Object} options - Generation options
228
- * @returns {Object} Complete v1 OpenAPI specification
229
- */
230
- function generateOpenApiSpecV1(appDefinition = null, options = {}) {
231
- const { useCache = true, serverUrl = null } = options;
232
- const modulesKey = JSON.stringify(appDefinition?.integrations);
233
-
234
- // Return cached spec if available
235
- if (useCache && cache.v1.spec && cache.v1.modules === modulesKey) {
236
- // Clone and update server URL if different
237
- const spec = JSON.parse(JSON.stringify(cache.v1.spec));
238
- if (serverUrl) {
239
- spec.servers = [
240
- { url: serverUrl, description: 'Current server' },
241
- ...(spec.servers?.filter(
242
- (s) => s.description !== 'Current server'
243
- ) || []),
244
- ];
245
- }
246
- return spec;
247
- }
248
-
249
- // Load v1 spec
250
- const spec = loadV1Spec();
251
-
252
- // Extract and enrich with installed modules
253
- const installedModules = extractInstalledModules(appDefinition);
254
- if (installedModules.length > 0) {
255
- enrichSpecWithModules(spec, installedModules);
256
- }
257
-
258
- // Finalize spec
259
- finalizeSpec(spec, { serverUrl }, installedModules);
260
-
261
- // Cache result
262
- if (useCache) {
263
- cache.v1.spec = JSON.parse(JSON.stringify(spec));
264
- cache.v1.modules = modulesKey;
265
- }
266
-
267
- return spec;
268
- }
269
-
270
- /**
271
- * Generate v2 (current) OpenAPI spec from appDefinition
272
- * @param {Object} appDefinition - The app definition containing integrations
273
- * @param {Object} options - Generation options
274
- * @returns {Object} Complete v2 OpenAPI specification
275
- */
276
- function generateOpenApiSpecV2(appDefinition = null, options = {}) {
277
- const { useCache = true, serverUrl = null } = options;
278
- const modulesKey = JSON.stringify(appDefinition?.integrations);
279
-
280
- // Return cached spec if available
281
- if (useCache && cache.v2.spec && cache.v2.modules === modulesKey) {
282
- // Clone and update server URL if different
283
- const spec = JSON.parse(JSON.stringify(cache.v2.spec));
284
- if (serverUrl) {
285
- spec.servers = [
286
- { url: serverUrl, description: 'Current server' },
287
- ...(spec.servers?.filter(
288
- (s) => s.description !== 'Current server'
289
- ) || []),
290
- ];
291
- }
292
- return spec;
293
- }
294
-
295
- // Load v2 spec
296
- const spec = loadV2Spec();
297
-
298
- // Extract and enrich with installed modules
299
- const installedModules = extractInstalledModules(appDefinition);
300
- if (installedModules.length > 0) {
301
- enrichSpecWithModules(spec, installedModules);
302
- }
303
-
304
- // Finalize spec
305
- finalizeSpec(spec, { serverUrl }, installedModules);
306
-
307
- // Cache result
308
- if (useCache) {
309
- cache.v2.spec = JSON.parse(JSON.stringify(spec));
310
- cache.v2.modules = modulesKey;
311
- }
312
-
313
- return spec;
314
- }
315
-
316
- /**
317
- * Generate OpenAPI spec (defaults to v2 for backwards compatibility)
318
- * @deprecated Use generateOpenApiSpecV1 or generateOpenApiSpecV2 instead
319
- * @param {Object} appDefinition - The app definition containing integrations
320
- * @param {Object} options - Generation options
321
- * @returns {Object} Complete OpenAPI specification
322
- */
323
- function generateOpenApiSpec(appDefinition = null, options = {}) {
324
- return generateOpenApiSpecV2(appDefinition, options);
325
- }
326
-
327
- /**
328
- * Clear all cached specs
329
- */
330
- function clearCache() {
331
- cache.v1.spec = null;
332
- cache.v1.modules = null;
333
- cache.v2.spec = null;
334
- cache.v2.modules = null;
335
- cache.legacy.spec = null;
336
- cache.legacy.modules = null;
337
- }
338
-
339
- /**
340
- * Get spec as YAML string
341
- * @param {Object} appDefinition - App definition
342
- * @param {Object} options - Options including version ('v1' or 'v2')
343
- * @returns {string} YAML string
344
- */
345
- function generateOpenApiYaml(appDefinition = null, options = {}) {
346
- const { version = 'v2', ...restOptions } = options;
347
- const spec =
348
- version === 'v1'
349
- ? generateOpenApiSpecV1(appDefinition, restOptions)
350
- : generateOpenApiSpecV2(appDefinition, restOptions);
351
- return yaml.dump(spec);
352
- }
353
-
354
- module.exports = {
355
- // Primary exports for v1/v2
356
- generateOpenApiSpecV1,
357
- generateOpenApiSpecV2,
358
-
359
- // Legacy/utility exports
360
- generateOpenApiSpec,
361
- generateOpenApiYaml,
362
- clearCache,
363
- extractModuleMetadata,
364
-
365
- // Internal utilities (exported for testing)
366
- loadBaseSpec,
367
- loadV1Spec,
368
- loadV2Spec,
369
- enrichSpecWithModules,
370
- };