@viewdo/dxp-story-cli
Version:
README.md
279 lines (238 loc) • 8.89 kB
JavaScript
module.exports = class SyncManager {
constructor(
{
config_only
}, {
file_service,
api_service,
task_service,
console_service
},
configuration_manager,
auth_manager) {
Object.assign(this, {
config_only,
configuration_manager,
auth_manager,
api_service,
file_service,
task_service,
console_service
})
}
// domain API -----
getStory(story_key) {
return this.api_service.getStory(story_key, this.auth_manager.token)
}
getOrganization(organization_key) {
return this.api_service.getOrganization(organization_key, this.auth_manager.token)
}
getOrganizationStories(organization_key) {
return this.api_service.getOrganizationStories(organization_key, this.auth_manager.token)
}
// PULL API ----------------------------------------------
// Organizations
pullOrganizations(organization_keys) {
return this.task_service.runTasks(
organization_keys.map(organization_key =>
this.task_service.getModelTask('Organization',
() => this.getOrganization(organization_key),
organization_key,
({model: organization}) => {
this.configuration_manager.setOrganizationConfig(organization)
if(this.config_only)
return {
title: 'Organization Config Only',
task: () => {}
}
return this.getOrganizationPullTasks(organization)
})
))
.then(ctx => {
return ctx.success == false ? 1 : 0
})
}
getOrganizationPullTasks(organization) {
let asset_config = this.configuration_manager.getOrganizationAssetConfig(organization.key)
return this.task_service.getAssetTasksPerType('Organization', organization, asset_config,
'Pulling',
({task, file}) => this.api_service.getFile(file.remote_path, this.auth_manager.token)
.then(content => {
this.file_service.write(file.local_path, content)
}).catch(e => task.skip(e.message))
)
}
// Stories
pullStories(story_keys) {
return this.task_service.runTasks(
story_keys.map(story_key => this.task_service.getModelTask('Story',
() => this.getStory(story_key),
story_key,
({model: story}) => {
this.configuration_manager.setStoryConfig(story)
if(this.config_only)
return {
title: 'Story Config Only',
task: () => {}
}
return this.getStoryPullTasks(story)
}
)))
.then(ctx => {
return ctx.success == false ? 1 : 0
})
}
getStoryPullTasks(story) {
let asset_config = this.configuration_manager.getStoryAssetConfig(story.key)
return this.task_service.getAssetTasksPerType('Story', story, asset_config,
'Pulling',
({task, file}) => this.api_service.getFile(file.remote_path, this.auth_manager.token)
.then(content => {
this.file_service.write(file.local_path, content)
})
.catch(e => task.skip(e.message))
)
}
// PUSH API ----------------------------------------------
pushStories(story_keys) {
return this.task_service.runTasks(
story_keys.map(story_key => this.task_service.getModelTask('Story',
() => this.getStory(story_key),
story_key,
({model: story}) => this.getStoryPushTasks(story)
)))
.then(ctx => {
return ctx.success == false ? 1 : 0
})
}
getStoryPushTasks(story) {
let story_asset_config = this.configuration_manager.getStoryAssetConfig(story.key)
return this.task_service.getAssetTasksPerType('Story', story, story_asset_config,
'Pushing',
({ctx, task, file}) => {
let content = this.file_service.read(file.local_path)
if(content != null) {
if(content.trim() == "") {
task.output = "Skipping Validation (Empty File)"
return this.api_service.putFile(file.remote_path, content, this.auth_manager.token)
.catch(e => task.skip('Empty files are not yet allowed through the API. Clear them by hand if necessary')) //e.message))
}
// no validation on js files
if(file.skip_validation) {
task.output = "Skipping Validation for this file-type."
return this.api_service.putFile(file.remote_path, content, this.auth_manager.token)
.catch(e => task.skip(e.message))
}
task.output = "Validating..."
return this.api_service.validateFile(story.key, content, this.auth_manager.token)
.then(results => {
if(results.isValid) {
task.output = "👍 Valid"
return this.api_service.putFile(file.remote_path, content, this.auth_manager.token)
}
let first_error = results.errors[0]
ctx.success = false
throw new Error(`Line ${first_error.line}: ${first_error.message}`)
})
}
task.skip('No local file to push.')
})
}
pushOrganizations(organization_keys) {
return this.task_service.runTasks(
organization_keys.map(organization_key => this.task_service.getModelTask('Organization',
() => this.getOrganization(organization_key),
organization_key,
({model: organization}) => this.getOrganizationPushTasks(organization)
)))
.then(ctx => {
return ctx.success == false ? 1 : 0
})
}
getOrganizationPushTasks(organization) {
let organization_asset_config = this.configuration_manager.getOrganizationAssetConfig(organization.key)
return this.task_service.getAssetTasksPerType('Organization', organization, organization_asset_config,
'Pushing',
({ctx, task, file}) => {
let content = this.file_service.read(file.local_path)
return this.api_service.putFile(file.remote_path, content, this.auth_manager.token)
.catch(e => task.skip(e.message))
})
}
// CHECK API ----------------------------------------------
checkStories(story_keys) {
return this.task_service.runTasks(
story_keys.map(story_key => this.task_service.getModelTask('Story',
() => this.getStory(story_key),
story_key,
({model: story}) => this.getStoryStatusTasks(story)
)))
.then(ctx => {
this.console_service.log(`${ctx.changes||0} changed files detected`)
return ctx.changes ? 1 : 0
})
}
getStoryStatusTasks(story) {
let story_asset_config = this.configuration_manager.getStoryAssetConfig(story.key)
return this.task_service.getAssetTasksPerType('Story', story, story_asset_config,
'Checking',
({ctx, task, file}) =>
this.api_service.getFile(file.remote_path, this.auth_manager.token)
.then(content => {
if(content != null) {
let local_content = this.file_service.read(file.local_path)
if(local_content != content) {
if(!ctx.changes)
ctx.changes = 1
else
ctx.changes++
task.skip('⚠️ Local file is different and will be replaced on the server (skipped=changed) ')
}
} else {
task.title = `No Remote ${task.title}`
}
})
//.catch(e => task.skip(e.message))
)
}
// VALIDATE API ----------------------------------------------
validateStories(story_keys) {
return this.task_service.runTasks(
story_keys.map(story_key => this.task_service.getModelTask(
'Story',
() => this.getStory(story_key),
story_key,
({model: story}) => this.getStoryValidateTasks(story)
)))
.then(ctx => {
return ctx.success == false ? 1 : 0
})
}
getStoryValidateTasks(story) {
let story_asset_config = this.configuration_manager.getStoryAssetConfig(story.key)
return this.task_service.getAssetTasksPerType('Story', story,
story_asset_config,
'Validating',
({ctx, task, file}) => {
let content = this.file_service.read(file.local_path)
if(content != null) {
task.output = "Validating..."
if(content.trim() == "") {
task.skip('Local file is empty.')
return
}
return this.api_service.validateFile(story.key, content, this.auth_manager.token)
.then(results => {
if(!results.isValid) {
task.output = "Invalid!"
let first_error = results.errors[0]
throw new Error(`Line ${first_error.line}: ${first_error.message}`)
}
task.output = "Valid!"
return true
})
}
task.skip('No local file to validate.')
})
}
}