diff --git a/CHANGELOG.md b/CHANGELOG.md index cce0ee4..5aafa17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log (vscode-deploy-reloaded) +## 0.5.0 (December 28th, 2017; improvements) + +* bugfixes +* code improvements +* [placeholders](https://github.com/mkloubert/vscode-deploy-reloaded/wiki/values) can be applied to properties of [packages](https://github.com/mkloubert/vscode-deploy-reloaded/wiki#packages-) and [targets](https://github.com/mkloubert/vscode-deploy-reloaded/wiki#targets-) now, s. [apply values](https://github.com/mkloubert/vscode-deploy-reloaded/wiki/apply_values) + ## 0.4.0 (December 28th, 2017; enhancements) * bugfixes diff --git a/package-lock.json b/package-lock.json index 0064b98..2504792 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-deploy-reloaded", - "version": "0.4.0", + "version": "0.5.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e5da18d..4e33daa 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-deploy-reloaded", "displayName": "Deploy (Reloaded)", "description": "Deploys files of a workspace to a destination.", - "version": "0.4.0", + "version": "0.5.0", "publisher": "mkloubert", "engines": { "vscode": "^1.19.0" @@ -313,6 +313,20 @@ "items": { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that package.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that package where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "button": { "oneOf": [ { @@ -674,6 +688,20 @@ "type": "string", "description": "The account name." }, + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -2602,6 +2630,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -4518,6 +4560,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -6451,6 +6507,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -8368,6 +8438,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -10315,6 +10399,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -12256,6 +12354,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -14214,6 +14326,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -16130,6 +16256,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -18092,6 +18232,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -20034,6 +20188,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -22062,6 +22230,20 @@ } ] }, + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -24005,6 +24187,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -25936,6 +26132,20 @@ "description": "Set to (true) to use OpenSSH agent forwarding (auth-agent@openssh.com) for the life of the connection. 'agent' property must also be set to use this feature.", "default": false }, + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -27908,6 +28118,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -29832,6 +30056,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -31838,6 +32076,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", @@ -33752,6 +34004,20 @@ { "type": "object", "properties": { + "applyValuesTo": { + "description": "Applies values to the properties of that target.", + "type": "object", + "patternProperties": { + "\\S+": { + "description": "The name of the property inside that target where the value should be applied to.", + "oneOf": [ + { + "description": "A value to apply. If a string, it is handled as template with placesholders, which should be parsed and used as value to apply." + } + ] + } + } + }, "beforeDelete": { "description": "One or more operations that should be invoked BEFORE a delete operation starts.", "type": "array", diff --git a/src/delete.ts b/src/delete.ts index 27b41d3..1bd38c0 100644 --- a/src/delete.ts +++ b/src/delete.ts @@ -17,6 +17,7 @@ import * as deploy_contracts from './contracts'; import * as deploy_helpers from './helpers'; +import * as deploy_gui from './gui'; import * as deploy_log from './log'; import * as deploy_packages from './packages'; import * as deploy_plugins from './plugins'; @@ -496,42 +497,19 @@ export async function deletePackage(pkg: deploy_packages.Package, return; } - const QUICK_PICK_ITEMS: deploy_contracts.ActionQuickPick[] = TARGETS.map((t, i) => { - return { - action: async () => { - await deleteFilesIn.apply(ME, - [ FILES_TO_DELETE, t, i + 1, deleteLocalFiles ]); - }, - description: deploy_helpers.toStringSafe( t.description ).trim(), - detail: t.__workspace.folder.uri.fsPath, - label: deploy_targets.getTargetName(t), - state: t, - }; - }).filter(qp => deploy_targets.isVisibleForPackage(qp.state, pkg)); - - if (QUICK_PICK_ITEMS.length < 1) { - ME.showWarningMessage( - ME.t('targets.noneFound') - ); - + const SELECTED_TARGET = await deploy_targets.showTargetQuickPick( + ME.context.extension, + TARGETS, + { + placeHolder: ME.t('DELETE.selectTarget'), + } + ); + if (!SELECTED_TARGET) { return; } - let selectedItem: deploy_contracts.ActionQuickPick; - if (1 === QUICK_PICK_ITEMS.length) { - selectedItem = QUICK_PICK_ITEMS[0]; - } - else { - selectedItem = await vscode.window.showQuickPick(QUICK_PICK_ITEMS, { - placeHolder: ME.t('DELETE.selectTarget') - }); - } - - if (selectedItem) { - await Promise.resolve( - selectedItem.action() - ); - } + await deleteFilesIn.apply(ME, + [ FILES_TO_DELETE, SELECTED_TARGET, SELECTED_TARGET.__index + 1, deleteLocalFiles ]); } /** diff --git a/src/deploy.ts b/src/deploy.ts index d4ebf07..8cd69fc 100644 --- a/src/deploy.ts +++ b/src/deploy.ts @@ -434,42 +434,19 @@ export async function deployPackage(pkg: deploy_packages.Package) { return; } - const QUICK_PICK_ITEMS: deploy_contracts.ActionQuickPick[] = TARGETS.map((t, i) => { - return { - action: async () => { - await deployFilesTo.apply(ME, - [ FILES_TO_DEPLOY, t, i + 1 ]); - }, - description: deploy_helpers.toStringSafe( t.description ).trim(), - detail: t.__workspace.folder.uri.fsPath, - label: deploy_targets.getTargetName(t), - state: t, - }; - }).filter(qp => deploy_targets.isVisibleForPackage(qp.state, pkg)); - - if (QUICK_PICK_ITEMS.length < 1) { - ME.showWarningMessage( - ME.t('targets.noneFound') - ); - - return; - } - - let selectedItem: deploy_contracts.ActionQuickPick; - if (1 === QUICK_PICK_ITEMS.length) { - selectedItem = QUICK_PICK_ITEMS[0]; - } - else { - selectedItem = await vscode.window.showQuickPick(QUICK_PICK_ITEMS, { + const SELECTED_TARGET = await deploy_targets.showTargetQuickPick( + ME.context.extension, + TARGETS, + { placeHolder: ME.t('deploy.selectTarget'), - }); - } - - if (selectedItem) { - await Promise.resolve( - selectedItem.action() - ); + } + ); + if (!SELECTED_TARGET) { + return; } + + await deployFilesTo.apply(ME, + [ FILES_TO_DEPLOY, SELECTED_TARGET, SELECTED_TARGET.__index + 1 ]); } finally { if (PACKAGE_BTN) { diff --git a/src/packages.ts b/src/packages.ts index 07a4bc8..e783b0f 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -21,6 +21,7 @@ import * as deploy_gui from './gui'; import * as deploy_helpers from './helpers'; import * as deploy_log from './log'; import * as deploy_targets from './targets'; +import * as deploy_values from './values'; import * as deploy_workspaces from './workspaces'; import * as Enumerable from 'node-enumerable'; import * as i18 from './i18'; @@ -33,7 +34,8 @@ import * as vscode from 'vscode'; /** * A package. */ -export interface Package extends deploy_contracts.ConditionalItem, +export interface Package extends deploy_values.Applyable, + deploy_contracts.ConditionalItem, deploy_contracts.FileFilter, deploy_contracts.PlatformItem, deploy_contracts.WithOptionalName, diff --git a/src/pull.ts b/src/pull.ts index 5e83e6d..a3dcd2f 100644 --- a/src/pull.ts +++ b/src/pull.ts @@ -488,40 +488,17 @@ export async function pullPackage(pkg: deploy_packages.Package) { return; } - const QUICK_PICK_ITEMS: deploy_contracts.ActionQuickPick[] = TARGETS.map((t, i) => { - return { - action: async () => { - await pullFilesFrom.apply(ME, - [ FILES_TO_PULL, t, i + 1 ]); - }, - description: deploy_helpers.toStringSafe( t.description ).trim(), - detail: t.__workspace.folder.uri.fsPath, - label: deploy_targets.getTargetName(t), - state: t, - }; - }).filter(qp => deploy_targets.isVisibleForPackage(qp.state, pkg)); - - if (QUICK_PICK_ITEMS.length < 1) { - await ME.showWarningMessage( - ME.t('targets.noneFound') - ); - + const SELECTED_TARGET = await deploy_targets.showTargetQuickPick( + ME.context.extension, + TARGETS, + { + placeHolder: ME.t('pull.selectSource'), + } + ); + if (!SELECTED_TARGET) { return; } - let selectedItem: deploy_contracts.ActionQuickPick; - if (1 === QUICK_PICK_ITEMS.length) { - selectedItem = QUICK_PICK_ITEMS[0]; - } - else { - selectedItem = await vscode.window.showQuickPick(QUICK_PICK_ITEMS, { - placeHolder: ME.t('pull.selectSource') - }); - } - - if (selectedItem) { - await Promise.resolve( - selectedItem.action() - ); - } + await pullFilesFrom.apply(ME, + [ FILES_TO_PULL, SELECTED_TARGET, SELECTED_TARGET.__index + 1 ]); } diff --git a/src/targets.ts b/src/targets.ts index add890a..9c35b2a 100644 --- a/src/targets.ts +++ b/src/targets.ts @@ -29,6 +29,7 @@ import * as deploy_targets_operations_script from './targets/operations/script'; import * as deploy_targets_operations_sql from './targets/operations/sql'; import * as deploy_targets_operations_wait from './targets/operations/wait'; import * as deploy_transformers from './transformers'; +import * as deploy_values from './values'; import * as deploy_workspaces from './workspaces'; import * as Enumerable from 'node-enumerable'; import * as i18 from './i18'; @@ -74,7 +75,8 @@ export interface ExecuteTargetOperationOptions { /** * A target. */ -export interface Target extends deploy_transformers.CanTransformData, +export interface Target extends deploy_values.Applyable, + deploy_transformers.CanTransformData, deploy_contracts.ConditionalItem, deploy_contracts.Encryptable, deploy_contracts.PlatformItem, diff --git a/src/values.ts b/src/values.ts index 60ce949..0489f37 100644 --- a/src/values.ts +++ b/src/values.ts @@ -22,6 +22,18 @@ import * as deploy_log from './log'; import * as OS from 'os'; +/** + * An object that can apply to (its) properties by using + * generated values by placeholders. + */ +export interface Applyable { + /** + * A list of property names and their values + * that should be applied to that object. + */ + readonly applyValuesTo?: { [prop: string]: any }; +} + /** * An item of a static value. */ @@ -195,6 +207,79 @@ export class StaticValue extends ValueBase { } +/** + * Applies values to an object. + * + * @param {TObj} obj The object to apply the values to. + * @param {Function} valueProvider The function that provides the values to apply to string based propertis. + * + * @return {TObj} The new object. + */ +export function applyValuesTo(obj: TObj, + valueProvider: () => Value | Value[]): TObj { + if (!valueProvider) { + valueProvider = () => []; + } + + const DO_NOT_APPLY_SELF = Symbol('DO_NOT_APPLY_SELF'); + const SELF_PROP = 'applyValuesTo'; + + if (obj) { + const NEW_OBJ: any = {}; + for (const P in obj) { + NEW_OBJ[P] = obj[P]; + } + + const APPLY_TO = obj[SELF_PROP]; + let selfValue: any = DO_NOT_APPLY_SELF; + + const MAKE_PLACEHOLDER_PROPERTY = (prop: string, val: any) => { + delete NEW_OBJ[prop]; + + Object.defineProperty(NEW_OBJ, prop, { + enumerable: true, + + get: () => { + let resultValue = val; + if (deploy_helpers.isString(resultValue)) { + // handle as template + // with placeholders + resultValue = replaceWithValues(valueProvider(), + resultValue); + } + + return resultValue; + }, + + set: (newValue) => { + val = newValue; + } + }); + }; + + if (APPLY_TO) { + for (const P in APPLY_TO) { + const VALUE = APPLY_TO[P]; + + if (SELF_PROP === P) { + selfValue = VALUE; + } + else { + MAKE_PLACEHOLDER_PROPERTY(P, VALUE); + } + } + } + + if (selfValue !== DO_NOT_APPLY_SELF) { + MAKE_PLACEHOLDER_PROPERTY(SELF_PROP, selfValue); + } + + obj = NEW_OBJ; + } + + return obj; +} + /** * Returns a list of predefined values. * diff --git a/src/workspaces.ts b/src/workspaces.ts index 12a4b79..c2b494d 100644 --- a/src/workspaces.ts +++ b/src/workspaces.ts @@ -284,6 +284,22 @@ export class Workspace extends deploy_objects.DisposableBase implements deploy_c this.state = new WorkspaceMemento(this); } + /** + * Applies values to an object. + * + * @param {TObj} obj The object to apply the values to. + * + * @return {TObj} The new object. + */ + public applyValuesTo(obj: TObj): TObj { + const ME = this; + + return deploy_values.applyValuesTo( + obj, + () => ME.getValues(), + ); + } + /** * Checks if an object can be handled by that workspace. * @@ -2068,12 +2084,14 @@ export class Workspace extends deploy_objects.DisposableBase implements deploy_c return 'object' === typeof p; }).select(p => { return deploy_helpers.cloneObject(p); - }).toArray() + }).toArray(); packages = deploy_helpers.filterPlatformItems(packages); let index = -1; - packages = Enumerable.from(packages).pipe(p => { + packages = Enumerable.from(packages).select(p => { + return ME.applyValuesTo(p); + }).pipe(p => { ++index; (p)['__index'] = index; @@ -2202,7 +2220,9 @@ export class Workspace extends deploy_objects.DisposableBase implements deploy_c targets = deploy_helpers.filterPlatformItems(targets); let index = -1; - targets = Enumerable.from(targets).pipe(t => { + targets = Enumerable.from(targets).select(t => { + return ME.applyValuesTo(t); + }).pipe(t => { ++index; (t)['__index'] = index;