@edgible-team/cli 1.2.13 → 1.2.15

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 (48) hide show
  1. package/dist/commands/stack/deploy.d.ts +6 -0
  2. package/dist/commands/stack/deploy.d.ts.map +1 -0
  3. package/dist/commands/stack/deploy.js +58 -0
  4. package/dist/commands/stack/diff.d.ts +7 -0
  5. package/dist/commands/stack/diff.d.ts.map +1 -0
  6. package/dist/commands/stack/diff.js +64 -0
  7. package/dist/commands/stack/status.d.ts +9 -0
  8. package/dist/commands/stack/status.d.ts.map +1 -0
  9. package/dist/commands/stack/status.js +53 -0
  10. package/dist/commands/stack/teardown.d.ts +6 -0
  11. package/dist/commands/stack/teardown.d.ts.map +1 -0
  12. package/dist/commands/stack/teardown.js +104 -0
  13. package/dist/commands/stack/validate.d.ts +7 -0
  14. package/dist/commands/stack/validate.d.ts.map +1 -0
  15. package/dist/commands/stack/validate.js +42 -0
  16. package/dist/commands/stack.d.ts +10 -0
  17. package/dist/commands/stack.d.ts.map +1 -0
  18. package/dist/commands/stack.js +112 -0
  19. package/dist/index.js +2 -0
  20. package/dist/services/instances.d.ts +23 -0
  21. package/dist/services/instances.d.ts.map +1 -1
  22. package/dist/services/instances.js +46 -1
  23. package/dist/services/stack/DependencyGraphManager.d.ts +69 -0
  24. package/dist/services/stack/DependencyGraphManager.d.ts.map +1 -0
  25. package/dist/services/stack/DependencyGraphManager.js +204 -0
  26. package/dist/services/stack/DeviceResolver.d.ts +63 -0
  27. package/dist/services/stack/DeviceResolver.d.ts.map +1 -0
  28. package/dist/services/stack/DeviceResolver.js +147 -0
  29. package/dist/services/stack/GatewayResolver.d.ts +84 -0
  30. package/dist/services/stack/GatewayResolver.d.ts.map +1 -0
  31. package/dist/services/stack/GatewayResolver.js +179 -0
  32. package/dist/services/stack/StackParser.d.ts +38 -0
  33. package/dist/services/stack/StackParser.d.ts.map +1 -0
  34. package/dist/services/stack/StackParser.js +234 -0
  35. package/dist/services/stack/StackService.d.ts +76 -0
  36. package/dist/services/stack/StackService.d.ts.map +1 -0
  37. package/dist/services/stack/StackService.js +476 -0
  38. package/dist/types/stack.d.ts +191 -0
  39. package/dist/types/stack.d.ts.map +1 -0
  40. package/dist/types/stack.js +5 -0
  41. package/dist/types/validation/schemas.d.ts +17 -17
  42. package/dist/utils/stack-errors.d.ts +103 -0
  43. package/dist/utils/stack-errors.d.ts.map +1 -0
  44. package/dist/utils/stack-errors.js +158 -0
  45. package/dist/validation/stack-schemas.d.ts +535 -0
  46. package/dist/validation/stack-schemas.d.ts.map +1 -0
  47. package/dist/validation/stack-schemas.js +178 -0
  48. package/package.json +4 -2
@@ -0,0 +1,476 @@
1
+ "use strict";
2
+ /**
3
+ * Stack Service
4
+ * Main orchestration service for application stack operations
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.StackService = void 0;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const StackParser_1 = require("./StackParser");
44
+ const DeviceResolver_1 = require("./DeviceResolver");
45
+ const GatewayResolver_1 = require("./GatewayResolver");
46
+ const DependencyGraphManager_1 = require("./DependencyGraphManager");
47
+ const stack_errors_1 = require("../../utils/stack-errors");
48
+ class StackService {
49
+ constructor(apiClient, applicationService, organizationId, logger) {
50
+ this.apiClient = apiClient;
51
+ this.applicationService = applicationService;
52
+ this.organizationId = organizationId;
53
+ this.logger = logger;
54
+ this.parser = new StackParser_1.StackParser(logger);
55
+ this.deviceResolver = new DeviceResolver_1.DeviceResolver(apiClient, organizationId, logger);
56
+ this.gatewayResolver = new GatewayResolver_1.GatewayResolver(apiClient, organizationId, logger);
57
+ this.dependencyManager = new DependencyGraphManager_1.DependencyGraphManager(logger);
58
+ }
59
+ /**
60
+ * Validate a stack file
61
+ * @param filePath Path to stack file
62
+ * @returns Validation result
63
+ */
64
+ async validateStack(filePath) {
65
+ this.logger.info('Validating stack file...');
66
+ try {
67
+ const result = await this.parser.validate(filePath);
68
+ if (result.valid) {
69
+ // Additional validation: check dependency graph
70
+ const stack = await this.parser.parseFile(filePath);
71
+ this.dependencyManager.validate(stack.applications);
72
+ // Check device names exist (optional, might be slow)
73
+ // Commented out for now to keep validation fast
74
+ // for (const app of stack.applications) {
75
+ // await this.deviceResolver.resolveDevice(app.deviceName);
76
+ // }
77
+ }
78
+ return result;
79
+ }
80
+ catch (error) {
81
+ // Convert any thrown errors to validation errors
82
+ return {
83
+ valid: false,
84
+ errors: [{
85
+ path: 'stack',
86
+ message: error instanceof Error ? error.message : 'Unknown validation error',
87
+ }],
88
+ warnings: [],
89
+ };
90
+ }
91
+ }
92
+ /**
93
+ * Deploy a stack
94
+ * @param options Deploy options
95
+ * @returns Deploy result
96
+ */
97
+ async deployStack(options) {
98
+ this.logger.info(`Deploying stack from: ${options.file}`);
99
+ const deployed = [];
100
+ const failed = [];
101
+ const skipped = [];
102
+ try {
103
+ // Parse and validate stack
104
+ const stack = await this.parser.parseFile(options.file);
105
+ this.logger.info(`Stack: ${stack.metadata.name} - ${stack.applications.length} applications`);
106
+ // Filter to single app if specified
107
+ let applicationsToDeploy = options.app
108
+ ? stack.applications.filter(app => app.name === options.app)
109
+ : stack.applications;
110
+ if (options.app && applicationsToDeploy.length === 0) {
111
+ throw new Error(`Application '${options.app}' not found in stack`);
112
+ }
113
+ // Validate dependency graph
114
+ this.dependencyManager.validate(applicationsToDeploy);
115
+ // Get deployment order
116
+ const deploymentOrder = this.dependencyManager.getDeploymentOrder(applicationsToDeploy);
117
+ this.logger.info(`Deployment order: ${deploymentOrder.join(' -> ')}`);
118
+ if (options.dryRun) {
119
+ this.logger.info('[DRY RUN] Would deploy applications in this order:');
120
+ for (const appName of deploymentOrder) {
121
+ const app = applicationsToDeploy.find(a => a.name === appName);
122
+ this.logger.info(` - ${appName} (${app.subtype}) on ${app.deviceName}`);
123
+ }
124
+ return {
125
+ success: true,
126
+ deployed: [],
127
+ failed: [],
128
+ skipped: deploymentOrder,
129
+ };
130
+ }
131
+ // Resolve devices and gateways
132
+ const resolved = await this.resolveStack(stack, applicationsToDeploy);
133
+ // Deploy applications in order
134
+ const deployedSet = new Set();
135
+ for (const appName of deploymentOrder) {
136
+ const app = applicationsToDeploy.find(a => a.name === appName);
137
+ // Check if dependencies deployed
138
+ if (!options.skipDependencies && app.dependsOn) {
139
+ const missingDeps = app.dependsOn.filter(dep => !deployedSet.has(dep));
140
+ if (missingDeps.length > 0) {
141
+ failed.push({
142
+ name: appName,
143
+ error: `Missing dependencies: ${missingDeps.join(', ')}`,
144
+ });
145
+ continue;
146
+ }
147
+ }
148
+ try {
149
+ this.logger.info(`Deploying application: ${appName}`);
150
+ const result = await this.deployApplication(app, resolved);
151
+ deployed.push(result);
152
+ deployedSet.add(appName);
153
+ }
154
+ catch (error) {
155
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
156
+ this.logger.error(`Failed to deploy ${appName}: ${errorMsg}`);
157
+ failed.push({
158
+ name: appName,
159
+ error: errorMsg,
160
+ });
161
+ // Stop deployment on first failure (fail-fast)
162
+ if (!options.force) {
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ const success = failed.length === 0;
168
+ this.logger.info(`Deployment ${success ? 'completed successfully' : 'completed with errors'}`);
169
+ this.logger.info(` Deployed: ${deployed.length}`);
170
+ this.logger.info(` Failed: ${failed.length}`);
171
+ return {
172
+ success,
173
+ deployed,
174
+ failed,
175
+ skipped,
176
+ };
177
+ }
178
+ catch (error) {
179
+ this.logger.error(`Stack deployment failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
180
+ throw error;
181
+ }
182
+ }
183
+ /**
184
+ * Teardown a stack
185
+ * @param options Teardown options
186
+ * @returns Teardown result
187
+ */
188
+ async teardownStack(options) {
189
+ this.logger.info(`Tearing down stack from: ${options.file}`);
190
+ const removed = [];
191
+ const failed = [];
192
+ const skipped = [];
193
+ try {
194
+ // Parse stack
195
+ const stack = await this.parser.parseFile(options.file);
196
+ // Filter to single app if specified
197
+ let applicationsToRemove = options.app
198
+ ? stack.applications.filter(app => app.name === options.app)
199
+ : stack.applications;
200
+ if (options.app && applicationsToRemove.length === 0) {
201
+ throw new Error(`Application '${options.app}' not found in stack`);
202
+ }
203
+ // Get teardown order (reverse of deployment)
204
+ const teardownOrder = this.dependencyManager.getTeardownOrder(applicationsToRemove);
205
+ this.logger.info(`Teardown order: ${teardownOrder.join(' -> ')}`);
206
+ // Get deployed applications
207
+ const deployedApps = await this.getDeployedApplications(applicationsToRemove);
208
+ // Remove applications in order
209
+ for (const appName of teardownOrder) {
210
+ const deployedApp = deployedApps.find(app => app.name === appName);
211
+ if (!deployedApp || !deployedApp.applicationId) {
212
+ this.logger.debug(`Application ${appName} not deployed, skipping`);
213
+ skipped.push(appName);
214
+ continue;
215
+ }
216
+ try {
217
+ this.logger.info(`Removing application: ${appName}`);
218
+ await this.applicationService.deleteApplication(deployedApp.applicationId);
219
+ removed.push(appName);
220
+ }
221
+ catch (error) {
222
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
223
+ this.logger.error(`Failed to remove ${appName}: ${errorMsg}`);
224
+ failed.push({
225
+ name: appName,
226
+ error: errorMsg,
227
+ });
228
+ // Continue even on failure (best effort teardown)
229
+ }
230
+ }
231
+ const success = failed.length === 0;
232
+ this.logger.info(`Teardown ${success ? 'completed successfully' : 'completed with errors'}`);
233
+ this.logger.info(` Removed: ${removed.length}`);
234
+ this.logger.info(` Failed: ${failed.length}`);
235
+ this.logger.info(` Skipped: ${skipped.length}`);
236
+ return {
237
+ success,
238
+ removed,
239
+ failed,
240
+ skipped,
241
+ };
242
+ }
243
+ catch (error) {
244
+ this.logger.error(`Stack teardown failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
245
+ throw error;
246
+ }
247
+ }
248
+ /**
249
+ * Get status of applications in a stack
250
+ * @param filePath Path to stack file
251
+ * @returns Stack status
252
+ */
253
+ async getStackStatus(filePath) {
254
+ this.logger.info('Getting stack status...');
255
+ const stack = await this.parser.parseFile(filePath);
256
+ const applicationStatuses = await this.getDeployedApplications(stack.applications);
257
+ return {
258
+ stackName: stack.metadata.name,
259
+ applications: applicationStatuses,
260
+ };
261
+ }
262
+ /**
263
+ * Get diff between stack definition and deployed state
264
+ * @param filePath Path to stack file
265
+ * @returns Stack diff
266
+ */
267
+ async diffStack(filePath) {
268
+ this.logger.info('Computing stack diff...');
269
+ const stack = await this.parser.parseFile(filePath);
270
+ const deployed = await this.getDeployedApplications(stack.applications);
271
+ const toCreate = [];
272
+ const toUpdate = [];
273
+ const toDelete = [];
274
+ const unchanged = [];
275
+ // Check each application in the stack
276
+ for (const app of stack.applications) {
277
+ const deployedApp = deployed.find(d => d.name === app.name);
278
+ if (!deployedApp || deployedApp.status === 'not-deployed') {
279
+ toCreate.push(app);
280
+ }
281
+ else {
282
+ // For MVP, consider as unchanged if deployed
283
+ // Future: implement proper field-by-field comparison
284
+ unchanged.push(app.name);
285
+ }
286
+ }
287
+ // Check for deployed apps not in stack (to delete)
288
+ for (const deployedApp of deployed) {
289
+ if (deployedApp.status === 'deployed') {
290
+ const inStack = stack.applications.find(a => a.name === deployedApp.name);
291
+ if (!inStack) {
292
+ toDelete.push(deployedApp);
293
+ }
294
+ }
295
+ }
296
+ return {
297
+ toCreate,
298
+ toUpdate,
299
+ toDelete,
300
+ unchanged,
301
+ };
302
+ }
303
+ /**
304
+ * Resolve stack: resolve device names and gateways
305
+ * @param stack Application stack
306
+ * @param applications Applications to resolve (filtered subset)
307
+ * @returns Resolved stack
308
+ */
309
+ async resolveStack(stack, applications) {
310
+ this.logger.info('Resolving devices and gateways...');
311
+ // Get unique device names
312
+ const deviceNames = [...new Set(applications.map(app => app.deviceName))];
313
+ // Resolve devices
314
+ const devices = await this.deviceResolver.resolveDevices(deviceNames);
315
+ this.logger.info(`Resolved ${devices.size} devices`);
316
+ // Resolve gateways
317
+ const gateways = await this.gatewayResolver.resolveGateways(applications);
318
+ this.logger.info(`Resolved gateways for ${gateways.size} published applications`);
319
+ return {
320
+ ...stack,
321
+ applications: stack.applications,
322
+ resolved: {
323
+ devices,
324
+ gateways,
325
+ applications: new Map(),
326
+ },
327
+ };
328
+ }
329
+ /**
330
+ * Deploy a single application
331
+ * @param app Application to deploy
332
+ * @param resolved Resolved stack information
333
+ * @returns Deployed application info
334
+ */
335
+ async deployApplication(app, resolved) {
336
+ const deviceId = resolved.resolved.devices.get(app.deviceName);
337
+ if (!deviceId) {
338
+ throw new stack_errors_1.ApplicationDeploymentError(app.name, `Device '${app.deviceName}' not found`);
339
+ }
340
+ const gatewayIds = resolved.resolved.gateways.get(app.name) || [];
341
+ // Map subtype to ApplicationService format
342
+ let serviceSubtype;
343
+ switch (app.subtype) {
344
+ case 'existing':
345
+ serviceSubtype = 'local-preexisting';
346
+ break;
347
+ case 'docker-compose':
348
+ serviceSubtype = 'docker-compose';
349
+ break;
350
+ case 'managed-process':
351
+ serviceSubtype = 'managed-process';
352
+ break;
353
+ default:
354
+ throw new stack_errors_1.ApplicationDeploymentError(app.name, `Unsupported subtype: ${app.subtype}`);
355
+ }
356
+ // Build configuration based on subtype
357
+ const configuration = {};
358
+ if (app.subtype === 'docker-compose' && app.composeFile) {
359
+ // Read and encode docker-compose file to base64
360
+ const dockerComposePath = await this.encodeDockerComposeFile(app.composeFile);
361
+ configuration.dockerComposePath = dockerComposePath;
362
+ // Also set environment variables if provided
363
+ if (app.environment) {
364
+ configuration.env = app.environment;
365
+ }
366
+ }
367
+ else if (app.subtype === 'managed-process') {
368
+ if (app.command)
369
+ configuration.command = app.command;
370
+ if (app.workingDir)
371
+ configuration.workingDir = app.workingDir;
372
+ if (app.environment)
373
+ configuration.environment = app.environment;
374
+ if (app.logFile)
375
+ configuration.logFile = app.logFile;
376
+ }
377
+ try {
378
+ const result = await this.applicationService.createApplicationProgrammatically({
379
+ name: app.name,
380
+ description: app.description || '',
381
+ port: app.port,
382
+ protocol: app.protocol,
383
+ hostnames: app.hostnames,
384
+ deviceIds: [deviceId],
385
+ gatewayIds: gatewayIds.length > 0 ? gatewayIds : undefined,
386
+ useManagedGateway: app.published,
387
+ subtype: serviceSubtype,
388
+ configuration,
389
+ authModes: app.authModes,
390
+ allowedOrganizations: app.allowedOrganizations,
391
+ });
392
+ return {
393
+ name: app.name,
394
+ applicationId: result.applicationId || result.id || 'unknown',
395
+ urls: result.urls || [],
396
+ };
397
+ }
398
+ catch (error) {
399
+ throw new stack_errors_1.ApplicationDeploymentError(app.name, error instanceof Error ? error.message : 'Unknown error', error instanceof Error ? error : undefined);
400
+ }
401
+ }
402
+ /**
403
+ * Get deployed applications matching stack apps
404
+ * @param applications Stack applications to check
405
+ * @returns Array of application statuses
406
+ */
407
+ async getDeployedApplications(applications) {
408
+ try {
409
+ // Get all applications in the organization
410
+ const allApps = await this.applicationService.getApplications();
411
+ // Match by name
412
+ return applications.map(stackApp => {
413
+ const deployedApp = allApps.find((app) => app.name === stackApp.name);
414
+ if (deployedApp) {
415
+ return {
416
+ name: stackApp.name,
417
+ status: 'deployed',
418
+ applicationId: deployedApp.id,
419
+ deviceName: stackApp.deviceName,
420
+ published: stackApp.published || false,
421
+ urls: deployedApp.urls || [],
422
+ };
423
+ }
424
+ else {
425
+ return {
426
+ name: stackApp.name,
427
+ status: 'not-deployed',
428
+ deviceName: stackApp.deviceName,
429
+ published: stackApp.published || false,
430
+ };
431
+ }
432
+ });
433
+ }
434
+ catch (error) {
435
+ this.logger.error(`Failed to get deployed applications: ${error instanceof Error ? error.message : 'Unknown error'}`);
436
+ // Return all as not-deployed on error
437
+ return applications.map(app => ({
438
+ name: app.name,
439
+ status: 'not-deployed',
440
+ deviceName: app.deviceName,
441
+ published: app.published || false,
442
+ }));
443
+ }
444
+ }
445
+ /**
446
+ * Encode docker-compose file to base64
447
+ * @param composeFilePath Path to docker-compose file (relative to stack file or absolute)
448
+ * @returns Base64-prefixed compose content ready for API submission
449
+ */
450
+ async encodeDockerComposeFile(composeFilePath) {
451
+ try {
452
+ // Resolve path (could be absolute or relative)
453
+ const resolvedPath = path.isAbsolute(composeFilePath)
454
+ ? composeFilePath
455
+ : path.resolve(process.cwd(), composeFilePath);
456
+ this.logger.debug(`Reading docker-compose file: ${resolvedPath}`);
457
+ // Check if file exists
458
+ if (!fs.existsSync(resolvedPath)) {
459
+ throw new Error(`Docker compose file not found: ${resolvedPath}`);
460
+ }
461
+ // Read file contents
462
+ const fileContents = fs.readFileSync(resolvedPath, 'utf-8');
463
+ // Encode to base64
464
+ const base64Content = Buffer.from(fileContents, 'utf-8').toString('base64');
465
+ // Return with base64: prefix (matching existing pattern)
466
+ this.logger.debug(`Encoded docker-compose file to base64 (${base64Content.length} bytes)`);
467
+ return `base64:${base64Content}`;
468
+ }
469
+ catch (error) {
470
+ this.logger.error(`Failed to encode docker-compose file: ${error instanceof Error ? error.message : 'Unknown error'}`);
471
+ throw new Error(`Failed to encode docker-compose file '${composeFilePath}': ${error instanceof Error ? error.message : 'Unknown error'}`);
472
+ }
473
+ }
474
+ }
475
+ exports.StackService = StackService;
476
+ //# sourceMappingURL=StackService.js.map
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Application Stack type definitions
3
+ * Defines the structure for declarative application deployments
4
+ */
5
+ /**
6
+ * Main application stack structure
7
+ */
8
+ export interface ApplicationStack {
9
+ apiVersion: string;
10
+ kind: 'ApplicationStack';
11
+ metadata: StackMetadata;
12
+ applications: StackApplication[];
13
+ }
14
+ /**
15
+ * Stack metadata
16
+ */
17
+ export interface StackMetadata {
18
+ name: string;
19
+ description?: string;
20
+ }
21
+ /**
22
+ * Application definition within a stack
23
+ */
24
+ export interface StackApplication {
25
+ name: string;
26
+ description?: string;
27
+ port: number;
28
+ protocol: 'http' | 'https' | 'tcp' | 'udp';
29
+ subtype: ApplicationSubtype;
30
+ deviceName: string;
31
+ published?: boolean;
32
+ hostnames?: string[];
33
+ dependsOn?: string[];
34
+ authModes?: AuthMode[];
35
+ allowedOrganizations?: string[];
36
+ composeFile?: string;
37
+ command?: string;
38
+ workingDir?: string;
39
+ environment?: Record<string, string>;
40
+ logFile?: string;
41
+ }
42
+ /**
43
+ * Supported application subtypes
44
+ */
45
+ export type ApplicationSubtype = 'existing' | 'docker-compose' | 'managed-process' | 'docker' | 'podman' | 'qemu';
46
+ /**
47
+ * Authentication modes
48
+ */
49
+ export type AuthMode = 'none' | 'org' | 'api-key';
50
+ /**
51
+ * Stack with resolved device and gateway IDs
52
+ */
53
+ export interface ResolvedStack extends ApplicationStack {
54
+ resolved: {
55
+ devices: Map<string, string>;
56
+ gateways: Map<string, string[]>;
57
+ applications: Map<string, string>;
58
+ };
59
+ }
60
+ /**
61
+ * Resolved application ready for deployment
62
+ */
63
+ export interface ResolvedApplication extends StackApplication {
64
+ deviceId: string;
65
+ gatewayIds?: string[];
66
+ existingApplicationId?: string;
67
+ }
68
+ /**
69
+ * Stack validation result
70
+ */
71
+ export interface StackValidationResult {
72
+ valid: boolean;
73
+ errors: StackValidationError[];
74
+ warnings: StackValidationWarning[];
75
+ }
76
+ /**
77
+ * Validation error
78
+ */
79
+ export interface StackValidationError {
80
+ path: string;
81
+ message: string;
82
+ line?: number;
83
+ }
84
+ /**
85
+ * Validation warning
86
+ */
87
+ export interface StackValidationWarning {
88
+ path: string;
89
+ message: string;
90
+ }
91
+ /**
92
+ * Options for deploy command
93
+ */
94
+ export interface DeployOptions {
95
+ file: string;
96
+ app?: string;
97
+ dryRun?: boolean;
98
+ skipDependencies?: boolean;
99
+ force?: boolean;
100
+ }
101
+ /**
102
+ * Options for teardown command
103
+ */
104
+ export interface TeardownOptions {
105
+ file: string;
106
+ app?: string;
107
+ force?: boolean;
108
+ keepDependencies?: boolean;
109
+ }
110
+ /**
111
+ * Deploy operation result
112
+ */
113
+ export interface DeployResult {
114
+ success: boolean;
115
+ deployed: DeployedApplication[];
116
+ failed: FailedApplication[];
117
+ skipped: string[];
118
+ }
119
+ /**
120
+ * Successfully deployed application
121
+ */
122
+ export interface DeployedApplication {
123
+ name: string;
124
+ applicationId: string;
125
+ urls?: string[];
126
+ }
127
+ /**
128
+ * Failed application deployment
129
+ */
130
+ export interface FailedApplication {
131
+ name: string;
132
+ error: string;
133
+ }
134
+ /**
135
+ * Teardown operation result
136
+ */
137
+ export interface TeardownResult {
138
+ success: boolean;
139
+ removed: string[];
140
+ failed: FailedApplication[];
141
+ skipped: string[];
142
+ }
143
+ /**
144
+ * Stack status information
145
+ */
146
+ export interface StackStatus {
147
+ stackName: string;
148
+ applications: ApplicationStatus[];
149
+ }
150
+ /**
151
+ * Individual application status
152
+ */
153
+ export interface ApplicationStatus {
154
+ name: string;
155
+ status: 'deployed' | 'not-deployed' | 'error';
156
+ applicationId?: string;
157
+ deviceName: string;
158
+ deviceId?: string;
159
+ published: boolean;
160
+ urls?: string[];
161
+ lastUpdated?: Date;
162
+ error?: string;
163
+ }
164
+ /**
165
+ * Stack diff result
166
+ */
167
+ export interface StackDiff {
168
+ toCreate: StackApplication[];
169
+ toUpdate: ApplicationDiff[];
170
+ toDelete: ApplicationStatus[];
171
+ unchanged: string[];
172
+ }
173
+ /**
174
+ * Application diff details
175
+ */
176
+ export interface ApplicationDiff {
177
+ name: string;
178
+ changes: {
179
+ field: string;
180
+ oldValue: any;
181
+ newValue: any;
182
+ }[];
183
+ }
184
+ /**
185
+ * Dependency graph node
186
+ */
187
+ export interface DependencyNode {
188
+ name: string;
189
+ dependencies: string[];
190
+ }
191
+ //# sourceMappingURL=stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../src/types/stack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // AUTO-GENERATED FILE - DO NOT EDIT
3
+ // This file is copied from backend during build. Changes will be overwritten.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ //# sourceMappingURL=stack.js.map