polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
162 lines • 6.31 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SceneExecutor = void 0;
const variable_resolver_1 = require("./variable-resolver");
const resource_handlers_1 = require("./resource-handlers");
class SceneExecutor {
constructor(_client) {
this.lastExecution = { rolledBack: [] };
this.handlers = (0, resource_handlers_1.createResourceHandlers)(_client);
this.resolver = new variable_resolver_1.VariableResolver();
}
setProgressCallback(callback) {
this.progressCallback = callback;
}
getLastExecution() {
return this.lastExecution;
}
async execute(config, options = {}) {
const startTime = Date.now();
this.lastExecution = { rolledBack: [] };
const order = this.getExecutionOrder(config);
const outputs = {};
const created = [];
const results = [];
const timings = {};
try {
for (let i = 0; i < order.length; i++) {
const resourceId = order[i];
if (!resourceId)
continue;
const resource = config.resources.find(r => r.id === resourceId);
if (!resource)
continue;
this.reportProgress({
phase: 'creating',
resourceId,
resourceType: resource.type,
current: i + 1,
total: order.length,
});
const resourceStartTime = Date.now();
if (options.dryRun) {
results.push({
id: resourceId,
type: resource.type,
output: {},
status: 'would_create',
});
}
else {
const handler = this.handlers[resource.type];
if (!handler) {
throw new Error(`Unknown resource type: ${resource.type}`);
}
const resolvedParams = this.resolver.resolveObject(resource.params, outputs);
const output = await handler.create(resolvedParams, resource.output);
outputs[resourceId] = output;
created.push({ resource, output });
results.push({
id: resourceId,
type: resource.type,
output,
status: 'created',
});
this.trackCreatedResource(resourceId, output);
}
timings[resourceId] = Date.now() - resourceStartTime;
this.reportProgress({
phase: 'created',
resourceId,
resourceType: resource.type,
current: i + 1,
total: order.length,
});
}
const result = {
success: true,
resources: results,
duration: Date.now() - startTime,
resourceTimings: timings,
};
if (options.dryRun) {
result.dryRun = true;
}
return result;
}
catch (error) {
const failedAt = order[created.length] || 'unknown';
this.lastExecution.failedAt = failedAt;
for (let i = created.length - 1; i >= 0; i--) {
const createdItem = created[i];
if (!createdItem)
continue;
this.reportProgress({
phase: 'rolling_back',
resourceId: createdItem.resource.id,
resourceType: createdItem.resource.type,
});
try {
const handler = this.handlers[createdItem.resource.type];
if (handler?.rollback) {
await handler.rollback(createdItem.output);
}
this.lastExecution.rolledBack.push(createdItem.resource.id);
}
catch (rollbackError) {
console.error(`Rollback failed for ${createdItem.resource.id}:`, rollbackError);
}
this.reportProgress({
phase: 'rolled_back',
resourceId: createdItem.resource.id,
resourceType: createdItem.resource.type,
});
}
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Failed to create resource "${failedAt}": ${errorMessage}`);
}
}
getExecutionOrder(config) {
const resources = config.resources;
const ordered = [];
const visited = new Set();
const visiting = new Set();
const visit = (resource) => {
if (visited.has(resource.id)) {
return;
}
if (visiting.has(resource.id)) {
throw new Error(`Circular dependency detected at resource "${resource.id}"`);
}
visiting.add(resource.id);
if (resource.dependsOn) {
const deps = Array.isArray(resource.dependsOn)
? resource.dependsOn
: [resource.dependsOn];
for (const depId of deps) {
const depResource = resources.find(r => r.id === depId);
if (!depResource) {
throw new Error(`Dependency "${depId}" not found for resource "${resource.id}"`);
}
visit(depResource);
}
}
visiting.delete(resource.id);
visited.add(resource.id);
ordered.push(resource.id);
};
for (const resource of resources) {
visit(resource);
}
return ordered;
}
reportProgress(event) {
if (this.progressCallback) {
this.progressCallback(event);
}
}
trackCreatedResource(_id, _output) {
}
}
exports.SceneExecutor = SceneExecutor;
//# sourceMappingURL=scene-executor.js.map