From e9af402cdc1c1514a8e56fadcda067023d690237 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Mon, 11 Dec 2023 17:13:05 -0500 Subject: [PATCH 01/92] ProfileInfo: start impl. proposed APIs for schema mgmt. Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ProfileInfo.ts | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 6d15c63a3e..ee0f1e6a6c 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -52,6 +52,13 @@ import { IGetAllProfilesOptions } from "./doc/IProfInfoProps"; import { IConfig } from "./doc/IConfig"; import { IProfInfoRemoveKnownPropOpts } from "./doc/IProfInfoRemoveKnownPropOpts"; +export type IExtenderJson = { + profileTypes: Record; +}; + /** * This class provides functions to retrieve profile-related information. * It can load the relevant configuration files, merge all possible @@ -1218,6 +1225,68 @@ export class ProfileInfo { LoggerUtils.setProfileSchemas(this.mProfileSchemaCache); } + /** + * Adds a profile type to the schema, and tracks its contribution in extenders.json. + * + * @param {IProfileSchema} typeSchema The schema to add for the profile type + * @returns {boolean} `true` if added to the schema; `false` otherwise + */ + public addProfileTypeToSchema(typeSchema: IProfileSchema): boolean { + if (this.mLoadedConfig == null) { + return false; + } + + // TODO: Add profile type to extenders.json w/ version + + // TODO: prefix key in map with config layer + this.mProfileSchemaCache.set(typeSchema.title, typeSchema); + return true; + } + + /** + * Returns a list of all available profile types + * @param [sources] Include all available types from given source applications + */ + public getProfileTypes(sources?: string[]): string[] { + const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); + const extenderJson: IExtenderJson = jsonfile.readFileSync(extenderJsonPath); + const profileTypes = []; + for (const layer of this.getTeamConfig().mLayers) { + if (layer.properties.$schema == null) continue; + const schemaUri = new url.URL(layer.properties.$schema, url.pathToFileURL(layer.path)); + const schemaPath = url.fileURLToPath(schemaUri); + if (fs.existsSync(schemaPath)) { + const schemaJson = jsonfile.readFileSync(schemaPath); + for (const { type, schema } of ConfigSchema.loadSchema(schemaJson)) { + if (type in extenderJson.profileTypes) { + if (sources?.length > 0 && + lodash.difference(extenderJson.profileTypes[type].from, sources).length === 0) { + profileTypes.push(type); + } + } + } + } + } + + return lodash.uniq(profileTypes); + } + + /** + * Returns the schema object belonging to the specified profile type. + * + * @param {string} profileType The profile type to retrieve the schema from + * @returns {IProfileSchema} The schema object provided by the specified profile type + */ + public getSchemaForType(profileType: string): IProfileSchema { + for (const entry of this.mProfileSchemaCache.values()) { + if (entry.title === profileType) { + return entry; + } + } + + return null; + } + // _______________________________________________________________________ /** * Get all of the subprofiles in the configuration. From ae0be9e4dca1b19c6a2fbe4594ed6e8ad7f04803 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 12 Dec 2023 11:30:01 -0500 Subject: [PATCH 02/92] finish addProfileTypeToSchema, adjust getProfileTypes Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ProfileInfo.ts | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index ee0f1e6a6c..7e939cdff5 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -15,6 +15,7 @@ import * as path from "path"; import * as url from "url"; import * as jsonfile from "jsonfile"; import * as lodash from "lodash"; +import * as semver from "semver"; // for ProfileInfo structures import { IProfArgAttrs } from "./doc/IProfArgAttrs"; @@ -1225,21 +1226,48 @@ export class ProfileInfo { LoggerUtils.setProfileSchemas(this.mProfileSchemaCache); } + private readExtendersJson(): IExtenderJson { + const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); + const extenderJson = jsonfile.readFileSync(extenderJsonPath); + return extenderJson; + } + /** * Adds a profile type to the schema, and tracks its contribution in extenders.json. * * @param {IProfileSchema} typeSchema The schema to add for the profile type * @returns {boolean} `true` if added to the schema; `false` otherwise */ - public addProfileTypeToSchema(typeSchema: IProfileSchema): boolean { + public addProfileTypeToSchema(profileType: string, typeInfo: + { sourceApp: string; schema: IProfileSchema; version?: string }): boolean { if (this.mLoadedConfig == null) { return false; } - // TODO: Add profile type to extenders.json w/ version + // Track the contributed profile type in extenders.json + const extenderJson = this.readExtendersJson(); + if (profileType in extenderJson.profileTypes) { + const typeMetadata = extenderJson.profileTypes[profileType]; + // Update the schema version for this profile type if newer than the installed version + if (version != null && semver.gt(version, typeMetadata.version)) { + extenderJson.profileTypes[profileType] = { + version, + from: [...typeMetadata.from, typeInfo.sourceApp] + }; + this.mProfileSchemaCache.set(profileType, typeInfo.schema); + + if (semver.major(version) != semver.major(typeMetadata.version)) { + // TODO: User warning about new major schema version + } + } + } else { + extenderJson.profileTypes = { + version: version, + from: [typeInfo.sourceApp] + }; + this.mProfileSchemaCache.set(profileType, typeInfo.schema); + } - // TODO: prefix key in map with config layer - this.mProfileSchemaCache.set(typeSchema.title, typeSchema); return true; } @@ -1248,8 +1276,7 @@ export class ProfileInfo { * @param [sources] Include all available types from given source applications */ public getProfileTypes(sources?: string[]): string[] { - const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - const extenderJson: IExtenderJson = jsonfile.readFileSync(extenderJsonPath); + const extenderJson = this.readExtendersJson(); const profileTypes = []; for (const layer of this.getTeamConfig().mLayers) { if (layer.properties.$schema == null) continue; @@ -1259,8 +1286,7 @@ export class ProfileInfo { const schemaJson = jsonfile.readFileSync(schemaPath); for (const { type, schema } of ConfigSchema.loadSchema(schemaJson)) { if (type in extenderJson.profileTypes) { - if (sources?.length > 0 && - lodash.difference(extenderJson.profileTypes[type].from, sources).length === 0) { + if (sources?.length > 0 && sources.some((val) => extenderJson.profileTypes[type].from.includes(val))) { profileTypes.push(type); } } From 464fc66833e9db5709b90550aea54c2dd0bd0e07 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 12 Dec 2023 15:39:44 -0500 Subject: [PATCH 03/92] Schema mgmt: finish proposed API fns (prototype) Signed-off-by: Trae Yelovich --- .../src/config/src/ConfigBuilder.ts | 57 ++++---- .../imperative/src/config/src/ProfileInfo.ts | 127 ++++++++++++++---- 2 files changed, 136 insertions(+), 48 deletions(-) diff --git a/packages/imperative/src/config/src/ConfigBuilder.ts b/packages/imperative/src/config/src/ConfigBuilder.ts index 99be12380b..1d5b1ddcef 100644 --- a/packages/imperative/src/config/src/ConfigBuilder.ts +++ b/packages/imperative/src/config/src/ConfigBuilder.ts @@ -18,6 +18,7 @@ import { IConfig } from "./doc/IConfig"; import { IConfigBuilderOpts } from "./doc/IConfigBuilderOpts"; import { CredentialManagerFactory } from "../../security"; import { IConfigConvertResult } from "./doc/IConfigConvertResult"; +import { ICommandProfileTypeConfiguration } from "../../cmd"; export class ConfigBuilder { /** @@ -30,31 +31,10 @@ export class ConfigBuilder { const config: IConfig = Config.empty(); for (const profile of impConfig.profiles) { - const properties: { [key: string]: any } = {}; - const secureProps: string[] = []; - for (const [k, v] of Object.entries(profile.schema.properties)) { - if (opts.populateProperties && v.includeInTemplate) { - if (v.secure) { - secureProps.push(k); - } else { - if (v.optionDefinition != null) { - // Use default value of ICommandOptionDefinition if present - properties[k] = v.optionDefinition.defaultValue; - } - if (properties[k] === undefined) { - // Fall back to an empty value - properties[k] = this.getDefaultValue(v.type); - } - } - } - } + const defaultProfile = this.buildDefaultProfile(config, profile); // Add the profile to config and set it as default - lodash.set(config, `profiles.${profile.type}`, { - type: profile.type, - properties, - secure: secureProps - }); + lodash.set(config, `profiles.${profile.type}`, defaultProfile); if (opts.populateProperties) { config.defaults[profile.type] = profile.type; @@ -76,6 +56,37 @@ export class ConfigBuilder { return { ...config, autoStore: true }; } + public static buildDefaultProfile(config: IConfig, profile: ICommandProfileTypeConfiguration): { + type: string; + properties: Record; + secure: string[] + } { + const properties: { [key: string]: any } = {}; + const secureProps: string[] = []; + for (const [k, v] of Object.entries(profile.schema.properties)) { + if (v.includeInTemplate) { + if (v.secure) { + secureProps.push(k); + } else { + if (v.optionDefinition != null) { + // Use default value of ICommandOptionDefinition if present + properties[k] = v.optionDefinition.defaultValue; + } + if (properties[k] === undefined) { + // Fall back to an empty value + properties[k] = this.getDefaultValue(v.type); + } + } + } + } + + return { + type: profile.type, + properties, + secure: secureProps + }; + } + /** * Convert existing v1 profiles to a Config object and report any conversion failures. * @param profilesRootDir Root directory where v1 profiles are stored. diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 7e939cdff5..6faa81d2c3 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -23,6 +23,7 @@ import { IProfAttrs } from "./doc/IProfAttrs"; import { IArgTeamConfigLoc, IProfLoc, IProfLocOsLoc, IProfLocOsLocLayer, ProfLocType } from "./doc/IProfLoc"; import { IProfMergeArgOpts } from "./doc/IProfMergeArgOpts"; import { IProfMergedArg } from "./doc/IProfMergedArg"; +import { IConfigSchema } from "./doc/IConfigSchema"; import { IProfOpts } from "./doc/IProfOpts"; import { ProfileCredentials } from "./ProfileCredentials"; import { ProfInfoErr } from "./ProfInfoErr"; @@ -52,6 +53,7 @@ import { ConfigAutoStore } from "./ConfigAutoStore"; import { IGetAllProfilesOptions } from "./doc/IProfInfoProps"; import { IConfig } from "./doc/IConfig"; import { IProfInfoRemoveKnownPropOpts } from "./doc/IProfInfoRemoveKnownPropOpts"; +import { ConfigBuilder } from "./ConfigBuilder"; export type IExtenderJson = { profileTypes: Record; private mCredentials: ProfileCredentials; + private mExtendersJson: IExtenderJson; + // _______________________________________________________________________ /** * Constructor for ProfileInfo class. @@ -981,6 +985,7 @@ export class ProfileInfo { } this.loadAllSchemas(); + this.readExtendersJsonFromDisk(); } // _______________________________________________________________________ @@ -1226,10 +1231,31 @@ export class ProfileInfo { LoggerUtils.setProfileSchemas(this.mProfileSchemaCache); } - private readExtendersJson(): IExtenderJson { + private readExtendersJsonFromDisk(): void { const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - const extenderJson = jsonfile.readFileSync(extenderJsonPath); - return extenderJson; + this.mExtendersJson = jsonfile.readFileSync(extenderJsonPath); + } + + /** + * Adds a profile type to the loaded Zowe config. + * The profile type must first be added to the schema using `addProfileTypeToSchema`. + * + * @param {string} profileType The profile type to add + * @param [layerPath] A dot-separated path that points to a layer in the config (default: top-most layer) + * Example: “outer.prod” would add a profile into the “prod” layer (which is contained in “outer” layer) + * @returns {boolean} `true` if added to the loaded config; `false` otherwise + */ + public addProfileToConfig(profileType: string, layerPath?: string): boolean { + const profileSchema = [...this.getTeamConfig().mLayers].reverse() + .reduce((prev: IProfileSchema, layer) => { + const [, desiredSchema] = [...this.mProfileSchemaCache.entries()] + .filter(([typeWithPath, schema]) => typeWithPath.includes(`:${profileType}`))[0]; + return desiredSchema; + }, {} as IProfileSchema); + + this.getTeamConfig().api.profiles.set(layerPath ?? profileType, + ConfigBuilder.buildDefaultProfile(this.mLoadedConfig.mProperties, { type: profileType, schema: profileSchema })); + return true; } /** @@ -1244,57 +1270,102 @@ export class ProfileInfo { return false; } + const oldExtendersJson = { ...this.mExtendersJson }; + // Track the contributed profile type in extenders.json - const extenderJson = this.readExtendersJson(); - if (profileType in extenderJson.profileTypes) { - const typeMetadata = extenderJson.profileTypes[profileType]; + if (profileType in this.mExtendersJson.profileTypes) { + const typeMetadata = this.mExtendersJson.profileTypes[profileType]; // Update the schema version for this profile type if newer than the installed version - if (version != null && semver.gt(version, typeMetadata.version)) { - extenderJson.profileTypes[profileType] = { - version, + if (typeInfo.version != null && semver.gt(typeInfo.version, typeMetadata.version)) { + this.mExtendersJson.profileTypes[profileType] = { + version: typeInfo.version, from: [...typeMetadata.from, typeInfo.sourceApp] }; this.mProfileSchemaCache.set(profileType, typeInfo.schema); - if (semver.major(version) != semver.major(typeMetadata.version)) { + if (semver.major(typeInfo.version) != semver.major(typeMetadata.version)) { // TODO: User warning about new major schema version } } } else { - extenderJson.profileTypes = { - version: version, + this.mExtendersJson.profileTypes[profileType] = { + version: typeInfo.version, from: [typeInfo.sourceApp] }; this.mProfileSchemaCache.set(profileType, typeInfo.schema); } + if (!lodash.isEqual(oldExtendersJson, this.mExtendersJson)) { + const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); + fs.writeFileSync(extenderJsonPath, JSON.stringify(this.mExtendersJson)); + } + return true; } + /** + * Builds the entire schema based on the available profile types and application sources. + * + * @param [sources] Include profile types contributed by these sources when building the schema + * - Source applications are tracked in the “from” list for each profile type in extenders.json + * @returns {IConfigSchema} A config schema containing all applicable profile types + */ + public buildSchema(sources?: string[]): IConfigSchema { + const finalSchema: Record = {}; + const teamConfigLayers = this.getTeamConfig().mLayers; + + for (let i = teamConfigLayers.length; i > 0; i--) { + const layer = teamConfigLayers[i]; + if (layer.properties.$schema == null) continue; + const schemaUri = new url.URL(layer.properties.$schema, url.pathToFileURL(layer.path)); + const schemaPath = url.fileURLToPath(schemaUri); + + if (!fs.existsSync(schemaPath)) continue; + + const profileTypesInLayer = [...this.mProfileSchemaCache.entries()].filter(([type, schema]) => type.includes(`${layer.path}:`)); + for (const [type, schema] of profileTypesInLayer) { + if (type in this.mExtendersJson.profileTypes) { + if (sources?.length > 0 && sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { + finalSchema[type] = schema; + } + } + } + } + + return ConfigSchema.buildSchema(Object.entries(finalSchema).map(([type, schema]) => ({ + type, + schema + }))); + } + /** * Returns a list of all available profile types * @param [sources] Include all available types from given source applications */ public getProfileTypes(sources?: string[]): string[] { - const extenderJson = this.readExtendersJson(); - const profileTypes = []; + const profileTypes = new Set(); for (const layer of this.getTeamConfig().mLayers) { if (layer.properties.$schema == null) continue; const schemaUri = new url.URL(layer.properties.$schema, url.pathToFileURL(layer.path)); const schemaPath = url.fileURLToPath(schemaUri); - if (fs.existsSync(schemaPath)) { - const schemaJson = jsonfile.readFileSync(schemaPath); - for (const { type, schema } of ConfigSchema.loadSchema(schemaJson)) { - if (type in extenderJson.profileTypes) { - if (sources?.length > 0 && sources.some((val) => extenderJson.profileTypes[type].from.includes(val))) { - profileTypes.push(type); + if (!fs.existsSync(schemaPath)) continue; + + const profileTypesInLayer = [...this.mProfileSchemaCache.keys()].filter((key) => key.includes(`${layer.path}:`)); + for (const typeWithPath of profileTypesInLayer) { + const [, type] = typeWithPath.split(":"); + if (type in this.mExtendersJson.profileTypes) { + if (sources?.length > 0) { + if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { + profileTypes.add(type); } + } else { + profileTypes.add(type); } } } } - return lodash.uniq(profileTypes); + return [...profileTypes]; } /** @@ -1304,13 +1375,19 @@ export class ProfileInfo { * @returns {IProfileSchema} The schema object provided by the specified profile type */ public getSchemaForType(profileType: string): IProfileSchema { - for (const entry of this.mProfileSchemaCache.values()) { - if (entry.title === profileType) { - return entry; + let finalSchema: IProfileSchema = null; + for (let i = this.getTeamConfig().mLayers.length; i > 0; i--) { + const layer = this.getTeamConfig().mLayers[i]; + const profileTypesFromLayer = [...this.mProfileSchemaCache.entries()].filter(([key, value]) => key.includes(`${layer.path}:`)); + for (const [layerType, schema] of profileTypesFromLayer) { + const [, type] = layerType.split(":"); + if (type === profileType) { + finalSchema = schema[1]; + } } } - return null; + return finalSchema; } // _______________________________________________________________________ From 9c30a52f72ad2e423820c397e29bd66ad8fe6e81 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 12 Dec 2023 15:49:02 -0500 Subject: [PATCH 04/92] Schema mgmt.: add typedoc to fn; update buildSchema logic Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 6faa81d2c3..ff64f8536f 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1231,6 +1231,10 @@ export class ProfileInfo { LoggerUtils.setProfileSchemas(this.mProfileSchemaCache); } + /** + * Reads the `extenders.json` file from the CLI home directory. + * Called once in `readProfilesFromDisk` and cached to minimize I/O operations. + */ private readExtendersJsonFromDisk(): void { const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); this.mExtendersJson = jsonfile.readFileSync(extenderJsonPath); @@ -1265,7 +1269,7 @@ export class ProfileInfo { * @returns {boolean} `true` if added to the schema; `false` otherwise */ public addProfileTypeToSchema(profileType: string, typeInfo: - { sourceApp: string; schema: IProfileSchema; version?: string }): boolean { + { sourceApp: string; schema: IProfileSchema; version?: string }): boolean { if (this.mLoadedConfig == null) { return false; } @@ -1325,7 +1329,11 @@ export class ProfileInfo { const profileTypesInLayer = [...this.mProfileSchemaCache.entries()].filter(([type, schema]) => type.includes(`${layer.path}:`)); for (const [type, schema] of profileTypesInLayer) { if (type in this.mExtendersJson.profileTypes) { - if (sources?.length > 0 && sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { + if (sources?.length > 0) { + if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { + finalSchema[type] = schema; + } + } else { finalSchema[type] = schema; } } From 09555cc45aa91086f4b7928d7d202ad61de607be Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Thu, 14 Dec 2023 09:50:10 -0500 Subject: [PATCH 05/92] wip: update extenders.json if adding new profile type Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index ff64f8536f..bfe599f173 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1237,7 +1237,13 @@ export class ProfileInfo { */ private readExtendersJsonFromDisk(): void { const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - this.mExtendersJson = jsonfile.readFileSync(extenderJsonPath); + if (!fs.existsSync(extenderJsonPath)) { + jsonfile.writeFileSync(extenderJsonPath, { + profileTypes: {} + }); + } else { + this.mExtendersJson = jsonfile.readFileSync(extenderJsonPath); + } } /** @@ -1296,12 +1302,12 @@ export class ProfileInfo { version: typeInfo.version, from: [typeInfo.sourceApp] }; - this.mProfileSchemaCache.set(profileType, typeInfo.schema); + this.mProfileSchemaCache.set(`${this.mLoadedConfig.layerActive().path}:${profileType}`, typeInfo.schema); } if (!lodash.isEqual(oldExtendersJson, this.mExtendersJson)) { const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - fs.writeFileSync(extenderJsonPath, JSON.stringify(this.mExtendersJson)); + jsonfile.writeFileSync(extenderJsonPath, this.mExtendersJson); } return true; From ffe6420724d3fdc88752a7d9ec360d46ea2edb12 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 15 Dec 2023 10:04:33 -0500 Subject: [PATCH 06/92] Schema Mgmt: comments and adjustments to APIs Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index bfe599f173..3e460ce98c 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1263,7 +1263,7 @@ export class ProfileInfo { return desiredSchema; }, {} as IProfileSchema); - this.getTeamConfig().api.profiles.set(layerPath ?? profileType, + this.getTeamConfig().api.profiles.set(layerPath ? `${layerPath}.${profileType}` : profileType, ConfigBuilder.buildDefaultProfile(this.mLoadedConfig.mProperties, { type: profileType, schema: profileSchema })); return true; } @@ -1325,6 +1325,7 @@ export class ProfileInfo { const teamConfigLayers = this.getTeamConfig().mLayers; for (let i = teamConfigLayers.length; i > 0; i--) { + // Grab types from each layer, starting with the highest-priority layer const layer = teamConfigLayers[i]; if (layer.properties.$schema == null) continue; const schemaUri = new url.URL(layer.properties.$schema, url.pathToFileURL(layer.path)); @@ -1332,10 +1333,13 @@ export class ProfileInfo { if (!fs.existsSync(schemaPath)) continue; - const profileTypesInLayer = [...this.mProfileSchemaCache.entries()].filter(([type, schema]) => type.includes(`${layer.path}:`)); - for (const [type, schema] of profileTypesInLayer) { + const profileTypesInLayer = [...this.mProfileSchemaCache.entries()] + .filter(([type, schema]) => type.includes(`${layer.path}:`)); + for (const [typeWithPath, schema] of profileTypesInLayer) { + const [, type] = typeWithPath.split(":"); if (type in this.mExtendersJson.profileTypes) { if (sources?.length > 0) { + // If a list of sources were provided, ensure the type is contributed at least one of these sources if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { finalSchema[type] = schema; } @@ -1369,6 +1373,7 @@ export class ProfileInfo { const [, type] = typeWithPath.split(":"); if (type in this.mExtendersJson.profileTypes) { if (sources?.length > 0) { + // Only consider types contributed by at least one of these sources if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { profileTypes.add(type); } From b3bc075153667562262431c818ce5524844b9709 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 19 Dec 2023 17:06:19 -0500 Subject: [PATCH 07/92] wip: addProfileTypeToSchema logic, structure updates Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ProfileInfo.ts | 94 +++++++++++++++---- .../doc/config/IProfileTypeConfiguration.ts | 4 + 2 files changed, 78 insertions(+), 20 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 3e460ce98c..4166989a0b 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -55,13 +55,18 @@ import { IConfig } from "./doc/IConfig"; import { IProfInfoRemoveKnownPropOpts } from "./doc/IProfInfoRemoveKnownPropOpts"; import { ConfigBuilder } from "./ConfigBuilder"; -export type IExtenderJson = { +export type ExtenderJson = { profileTypes: Record; }; +export type AddProfToSchemaResult = { + success: boolean; + info: string; +}; + /** * This class provides functions to retrieve profile-related information. * It can load the relevant configuration files, merge all possible @@ -170,7 +175,7 @@ export class ProfileInfo { private mProfileSchemaCache: Map; private mCredentials: ProfileCredentials; - private mExtendersJson: IExtenderJson; + private mExtendersJson: ExtenderJson; // _______________________________________________________________________ /** @@ -1240,7 +1245,7 @@ export class ProfileInfo { if (!fs.existsSync(extenderJsonPath)) { jsonfile.writeFileSync(extenderJsonPath, { profileTypes: {} - }); + }, { spaces: 4 }); } else { this.mExtendersJson = jsonfile.readFileSync(extenderJsonPath); } @@ -1275,29 +1280,62 @@ export class ProfileInfo { * @returns {boolean} `true` if added to the schema; `false` otherwise */ public addProfileTypeToSchema(profileType: string, typeInfo: - { sourceApp: string; schema: IProfileSchema; version?: string }): boolean { + { sourceApp: string; schema: IProfileSchema; version?: string }): AddProfToSchemaResult { if (this.mLoadedConfig == null) { - return false; + return { + success: false, + info: "No config layers are available (none found, or method was called before readProfilesFromDisk)" + }; } - const oldExtendersJson = { ...this.mExtendersJson }; + const oldExtendersJson = lodash.cloneDeep(this.mExtendersJson); + + let successMsg = ""; - // Track the contributed profile type in extenders.json if (profileType in this.mExtendersJson.profileTypes) { + // Profile type was already contributed, determine whether its metadata should be updated const typeMetadata = this.mExtendersJson.profileTypes[profileType]; - // Update the schema version for this profile type if newer than the installed version - if (typeInfo.version != null && semver.gt(typeInfo.version, typeMetadata.version)) { - this.mExtendersJson.profileTypes[profileType] = { - version: typeInfo.version, - from: [...typeMetadata.from, typeInfo.sourceApp] - }; - this.mProfileSchemaCache.set(profileType, typeInfo.schema); - - if (semver.major(typeInfo.version) != semver.major(typeMetadata.version)) { - // TODO: User warning about new major schema version + if (typeInfo.version != null) { + const prevTypeVersion = typeMetadata.version; + if (prevTypeVersion != null) { + // eslint-disable-next-line no-console + console.log("Comparing versions w/ semver"); + // Update the schema version for this profile type if newer than the installed version + if (semver.gt(typeInfo.version, prevTypeVersion)) { + // eslint-disable-next-line no-console + console.log("new version > old version"); + this.mExtendersJson.profileTypes[profileType] = { + version: typeInfo.version, + from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) + }; + this.mProfileSchemaCache.set(profileType, typeInfo.schema); + if (semver.major(typeInfo.version) != semver.major(prevTypeVersion)) { + successMsg = + `Profile type ${profileType} was updated from schema version ${prevTypeVersion} to ${typeInfo.version}.\n`.concat( + `The following applications may be affected: ${typeMetadata.from.filter((src) => src !== typeInfo.sourceApp)}` + ); + } + } else if (semver.major(prevTypeVersion) > semver.major(typeInfo.version)) { + // eslint-disable-next-line no-console + console.log("old version > new version"); + // Warn user if we are expecting a newer major schema version than the one they are providing + return { + success: false, + info: `Profile type ${profileType} expects a newer schema version than provided by ${typeInfo.sourceApp}\n`.concat( + `(expected: v${typeInfo.version}, installed: v${prevTypeVersion})`) + }; + } + } else { + // There wasn't a previous version, so we can update the schema + this.mExtendersJson.profileTypes[profileType] = { + version: typeInfo.version, + from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) + }; + this.mProfileSchemaCache.set(profileType, typeInfo.schema); } } } else { + // Track the newly-contributed profile type in extenders.json this.mExtendersJson.profileTypes[profileType] = { version: typeInfo.version, from: [typeInfo.sourceApp] @@ -1305,12 +1343,28 @@ export class ProfileInfo { this.mProfileSchemaCache.set(`${this.mLoadedConfig.layerActive().path}:${profileType}`, typeInfo.schema); } + // Update contents of extenders.json if (!lodash.isEqual(oldExtendersJson, this.mExtendersJson)) { - const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - jsonfile.writeFileSync(extenderJsonPath, this.mExtendersJson); + try { + const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); + jsonfile.writeFileSync(extenderJsonPath, this.mExtendersJson, { spaces: 4 }); + } catch (err) { + if (err.code === "EACCES" || err.code === "EPERM") { + // Even if we failed to update extenders.json, it was technically added to the schema cache. + // Warn the user that the new type may not persist if the schema is regenerated elsewhere. + return { + success: true, + info: "Failed to update extenders.json: insufficient permissions or read-only file.\n".concat( + `Profile type ${profileType} may not persist if the schema is updated.`) + }; + } + } } - return true; + return { + success: true, + info: successMsg + }; } /** diff --git a/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts b/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts index 0a1bb86c31..f0ce01f23b 100644 --- a/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts +++ b/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts @@ -39,6 +39,10 @@ export interface IProfileTypeConfiguration { * @memberof IProfileTypeConfiguration */ schema: IProfileSchema; + /** + * The version for the JSON schema document (not required). + */ + schemaVersion?: string; /** * The profile dependency specification. Indicates the required or optional profiles that a profile is depedent * on. Dependencies are written as part of the profile, but you do NOT need to specify dependencies in your From b5468dc3ba54d1094a424629e79ee7a588bdcf82 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 19 Dec 2023 19:11:19 -0500 Subject: [PATCH 08/92] wip: writeExtendersJson helper fn, fix SemVer version checks Signed-off-by: Trae Yelovich --- npm-shrinkwrap.json | 187 +----------------- packages/imperative/package.json | 2 +- .../imperative/src/config/src/ProfileInfo.ts | 44 +++-- 3 files changed, 34 insertions(+), 199 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index fc11dc3409..543ef508fd 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1577,33 +1577,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/reporters/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@jest/reporters/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@jest/reporters/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -1633,12 +1606,6 @@ "node": ">=10.12.0" } }, - "node_modules/@jest/reporters/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@jest/source-map": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", @@ -16508,18 +16475,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jest-snapshot/node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -16540,21 +16495,6 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jest-snapshot/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -16570,12 +16510,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-snapshot/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/jest-sonar-reporter": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jest-sonar-reporter/-/jest-sonar-reporter-2.0.0.tgz", @@ -22266,9 +22200,9 @@ "dev": true }, "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -23756,39 +23690,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ts-jest/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/ts-jest/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", @@ -24814,7 +24715,7 @@ "progress": "2.0.3", "read": "1.0.7", "readline-sync": "1.4.10", - "semver": "7.5.2", + "semver": "7.5.4", "stack-trace": "0.0.10", "strip-ansi": "6.0.1", "which": "3.0.0", @@ -26441,24 +26342,6 @@ "supports-color": "^8.0.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -26478,12 +26361,6 @@ "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^2.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, @@ -32098,7 +31975,7 @@ "progress": "2.0.3", "read": "1.0.7", "readline-sync": "1.4.10", - "semver": "7.5.2", + "semver": "7.5.4", "serve": "^12.0.1", "stack-trace": "0.0.10", "stream-to-string": "^1.2.0", @@ -38462,15 +38339,6 @@ "supports-color": "^8.0.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -38488,15 +38356,6 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -38505,12 +38364,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, @@ -42883,9 +42736,9 @@ "dev": true }, "semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" }, @@ -44019,30 +43872,6 @@ "picomatch": "^2.2.3" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", diff --git a/packages/imperative/package.json b/packages/imperative/package.json index b3578720c2..568dfcd66a 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -72,7 +72,7 @@ "progress": "2.0.3", "read": "1.0.7", "readline-sync": "1.4.10", - "semver": "7.5.2", + "semver": "7.5.4", "stack-trace": "0.0.10", "strip-ansi": "6.0.1", "which": "3.0.0", diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 8ec12e10a1..cbe8326002 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1280,6 +1280,19 @@ export class ProfileInfo { return true; } + private writeExtendersJson(): boolean { + try { + const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); + jsonfile.writeFileSync(extenderJsonPath, this.mExtendersJson, { spaces: 4 }); + } catch (err) { + if (err.code === "EACCES" || err.code === "EPERM") { + return false; + } + } + + return true; + } + /** * Adds a profile type to the schema, and tracks its contribution in extenders.json. * @@ -1296,21 +1309,16 @@ export class ProfileInfo { } const oldExtendersJson = lodash.cloneDeep(this.mExtendersJson); - let successMsg = ""; if (profileType in this.mExtendersJson.profileTypes) { // Profile type was already contributed, determine whether its metadata should be updated const typeMetadata = this.mExtendersJson.profileTypes[profileType]; - if (typeInfo.version != null) { + if (semver.valid(typeInfo.version) != null) { const prevTypeVersion = typeMetadata.version; if (prevTypeVersion != null) { - // eslint-disable-next-line no-console - console.log("Comparing versions w/ semver"); // Update the schema version for this profile type if newer than the installed version if (semver.gt(typeInfo.version, prevTypeVersion)) { - // eslint-disable-next-line no-console - console.log("new version > old version"); this.mExtendersJson.profileTypes[profileType] = { version: typeInfo.version, from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) @@ -1323,8 +1331,6 @@ export class ProfileInfo { ); } } else if (semver.major(prevTypeVersion) > semver.major(typeInfo.version)) { - // eslint-disable-next-line no-console - console.log("old version > new version"); // Warn user if we are expecting a newer major schema version than the one they are providing return { success: false, @@ -1340,6 +1346,11 @@ export class ProfileInfo { }; this.mProfileSchemaCache.set(profileType, typeInfo.schema); } + } else if (typeInfo.version != null) { + return { + success: false, + info: `New schema type for profile type ${profileType} is not SemVer-compliant; schema was not updated.` + } } } else { // Track the newly-contributed profile type in extenders.json @@ -1352,19 +1363,14 @@ export class ProfileInfo { // Update contents of extenders.json if (!lodash.isEqual(oldExtendersJson, this.mExtendersJson)) { - try { - const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - jsonfile.writeFileSync(extenderJsonPath, this.mExtendersJson, { spaces: 4 }); - } catch (err) { - if (err.code === "EACCES" || err.code === "EPERM") { + if (!this.writeExtendersJson()) { + return { + success: true, // Even if we failed to update extenders.json, it was technically added to the schema cache. // Warn the user that the new type may not persist if the schema is regenerated elsewhere. - return { - success: true, - info: "Failed to update extenders.json: insufficient permissions or read-only file.\n".concat( - `Profile type ${profileType} may not persist if the schema is updated.`) - }; - } + info: "Failed to update extenders.json: insufficient permissions or read-only file.\n".concat( + `Profile type ${profileType} may not persist if the schema is updated.`) + }; } } From 38b08c84802d3fae940492d10f25fa049dca0121 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 20 Dec 2023 10:51:36 -0500 Subject: [PATCH 09/92] fix(ProfileInfo): get type from cache keys; sort getProfileTypes result Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ProfileInfo.ts | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index cbe8326002..cc4b7bae46 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1403,7 +1403,10 @@ export class ProfileInfo { const profileTypesInLayer = [...this.mProfileSchemaCache.entries()] .filter(([type, schema]) => type.includes(`${layer.path}:`)); for (const [typeWithPath, schema] of profileTypesInLayer) { - const [, type] = typeWithPath.split(":"); + const type = typeWithPath.split(":").pop(); + if (type == null) { + continue; + } if (type in this.mExtendersJson.profileTypes) { if (sources?.length > 0) { // If a list of sources were provided, ensure the type is contributed at least one of these sources @@ -1428,6 +1431,7 @@ export class ProfileInfo { * @param [sources] Include all available types from given source applications */ public getProfileTypes(sources?: string[]): string[] { + const filteredBySource = sources?.length > 0; const profileTypes = new Set(); for (const layer of this.getTeamConfig().mLayers) { if (layer.properties.$schema == null) continue; @@ -1437,9 +1441,12 @@ export class ProfileInfo { const profileTypesInLayer = [...this.mProfileSchemaCache.keys()].filter((key) => key.includes(`${layer.path}:`)); for (const typeWithPath of profileTypesInLayer) { - const [, type] = typeWithPath.split(":"); - if (type in this.mExtendersJson.profileTypes) { - if (sources?.length > 0) { + const type = typeWithPath.split(":").pop(); + if (type == null) { + continue; + } + // if (type in this.mExtendersJson.profileTypes) { + if (filteredBySource) { // Only consider types contributed by at least one of these sources if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { profileTypes.add(type); @@ -1447,11 +1454,18 @@ export class ProfileInfo { } else { profileTypes.add(type); } - } + //} } } - return [...profileTypes]; + // Include all profile types from extenders.json if we are not filtering by source + if (!filteredBySource) { + for (const type of Object.keys(this.mExtendersJson.profileTypes)) { + profileTypes.add(type); + } + } + + return [...profileTypes].sort(); } /** @@ -1466,7 +1480,10 @@ export class ProfileInfo { const layer = this.getTeamConfig().mLayers[i]; const profileTypesFromLayer = [...this.mProfileSchemaCache.entries()].filter(([key, value]) => key.includes(`${layer.path}:`)); for (const [layerType, schema] of profileTypesFromLayer) { - const [, type] = layerType.split(":"); + const type = layerType.split(":").pop(); + if (type == null) { + continue; + } if (type === profileType) { finalSchema = schema[1]; } From 28dedb6a5f15436c529e474fb8daa3f7d2e42df5 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 3 Jan 2024 11:18:51 -0500 Subject: [PATCH 10/92] chore: Add typedoc, clean up new ProfileInfo APIs Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ProfileInfo.ts | 171 ++++++++++-------- .../src/config/src/doc/IExtenderOpts.ts | 22 +++ 2 files changed, 119 insertions(+), 74 deletions(-) create mode 100644 packages/imperative/src/config/src/doc/IExtenderOpts.ts diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index cc4b7bae46..e08784fa45 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -54,18 +54,8 @@ import { IGetAllProfilesOptions } from "./doc/IProfInfoProps"; import { IConfig } from "./doc/IConfig"; import { IProfInfoRemoveKnownPropOpts } from "./doc/IProfInfoRemoveKnownPropOpts"; import { ConfigBuilder } from "./ConfigBuilder"; - -export type ExtenderJson = { - profileTypes: Record; -}; - -export type AddProfToSchemaResult = { - success: boolean; - info: string; -}; +import { IAddProfTypeResult, IExtendersJsonOpts } from "./doc/IExtenderOpts"; +import { IConfigLayer } from ".."; /** * This class provides functions to retrieve profile-related information. @@ -175,7 +165,7 @@ export class ProfileInfo { private mProfileSchemaCache: Map; private mCredentials: ProfileCredentials; - private mExtendersJson: ExtenderJson; + private mExtendersJson: IExtendersJsonOpts; // _______________________________________________________________________ /** @@ -1258,6 +1248,21 @@ export class ProfileInfo { } } + /** + * Attempts to write to the `extenders.json` file in the CLI home directory. + * @returns `true` if written successfully; `false` otherwise + */ + private writeExtendersJson(): boolean { + try { + const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); + jsonfile.writeFileSync(extenderJsonPath, this.mExtendersJson, { spaces: 4 }); + } catch (err) { + return false; + } + + return true; + } + /** * Adds a profile type to the loaded Zowe config. * The profile type must first be added to the schema using `addProfileTypeToSchema`. @@ -1268,70 +1273,98 @@ export class ProfileInfo { * @returns {boolean} `true` if added to the loaded config; `false` otherwise */ public addProfileToConfig(profileType: string, layerPath?: string): boolean { + // Find the schema in the cache, starting with the highest-priority layer and working up const profileSchema = [...this.getTeamConfig().mLayers].reverse() .reduce((prev: IProfileSchema, layer) => { - const [, desiredSchema] = [...this.mProfileSchemaCache.entries()] + const cachedSchema = [...this.mProfileSchemaCache.entries()] .filter(([typeWithPath, schema]) => typeWithPath.includes(`:${profileType}`))[0]; - return desiredSchema; - }, {} as IProfileSchema); + if (cachedSchema != null) { + prev = cachedSchema[1]; + } + return prev; + }, undefined); + + // Skip adding to config if the schema was not found + if (profileSchema == null) { + return false; + } this.getTeamConfig().api.profiles.set(layerPath ? `${layerPath}.${profileType}` : profileType, ConfigBuilder.buildDefaultProfile(this.mLoadedConfig.mProperties, { type: profileType, schema: profileSchema })); return true; } - private writeExtendersJson(): boolean { - try { - const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - jsonfile.writeFileSync(extenderJsonPath, this.mExtendersJson, { spaces: 4 }); - } catch (err) { - if (err.code === "EACCES" || err.code === "EPERM") { - return false; - } + /** + * Updates the schema to contain the new profile type. + * If the type exists in the cache, it will use the matching layer; if not found, it will use the schema at the active layer. + * + * @param {IProfileSchema} typeSchema The schema to add for the profile type + * @returns {boolean} `true` if added to the schema; `false` otherwise + */ + private updateSchemaAtLayer(profileType: string, schema: IProfileSchema): void { + // Check if type already exists in schema cache; if so, update schema at the same layer. + // Otherwise, update schema at the active layer. + const cachedType = [...this.mProfileSchemaCache.entries()] + .find(([typePath, _schema]) => typePath.includes(`:${profileType}`)); + + const layerPath = cachedType != null ? cachedType[0].substring(0, cachedType[0].indexOf(":")) : this.getTeamConfig().layerActive().path; + const layerToUpdate = this.getTeamConfig().mLayers.find((l) => l.path === layerPath); + const schemaUri = new url.URL(layerToUpdate.properties.$schema, url.pathToFileURL(layerPath)); + const schemaPath = url.fileURLToPath(schemaUri); + + if (fs.existsSync(schemaPath)) { + jsonfile.writeFileSync(schemaPath, this.buildSchema([], layerToUpdate)); } - - return true; } /** - * Adds a profile type to the schema, and tracks its contribution in extenders.json. + * Adds a profile type to the schema, and tracks its contribution in extenders.json. + * NOTE: `readProfilesFromDisk` must be called at least once before adding new profile types. * * @param {IProfileSchema} typeSchema The schema to add for the profile type * @returns {boolean} `true` if added to the schema; `false` otherwise */ public addProfileTypeToSchema(profileType: string, typeInfo: - { sourceApp: string; schema: IProfileSchema; version?: string }): AddProfToSchemaResult { - if (this.mLoadedConfig == null) { + { sourceApp: string; schema: IProfileSchema; version?: string }): IAddProfTypeResult { + // Get the active team config layer + const activeLayer = this.getTeamConfig()?.layerActive(); + if (activeLayer == null) { return { success: false, - info: "No config layers are available (none found, or method was called before readProfilesFromDisk)" + info: "This function only supports team configurations." }; } + // copy last value for `extenders.json` to compare against updated object const oldExtendersJson = lodash.cloneDeep(this.mExtendersJson); let successMsg = ""; if (profileType in this.mExtendersJson.profileTypes) { // Profile type was already contributed, determine whether its metadata should be updated const typeMetadata = this.mExtendersJson.profileTypes[profileType]; + if (semver.valid(typeInfo.version) != null) { + // The provided version is SemVer-compliant; compare against previous version (if exists) const prevTypeVersion = typeMetadata.version; if (prevTypeVersion != null) { - // Update the schema version for this profile type if newer than the installed version if (semver.gt(typeInfo.version, prevTypeVersion)) { + // Update the schema for this profile type, as its newer than the installed version this.mExtendersJson.profileTypes[profileType] = { version: typeInfo.version, from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) }; - this.mProfileSchemaCache.set(profileType, typeInfo.schema); + + this.updateSchemaAtLayer(profileType, typeInfo.schema); + if (semver.major(typeInfo.version) != semver.major(prevTypeVersion)) { + // Warn user if new major schema version is specified successMsg = `Profile type ${profileType} was updated from schema version ${prevTypeVersion} to ${typeInfo.version}.\n`.concat( `The following applications may be affected: ${typeMetadata.from.filter((src) => src !== typeInfo.sourceApp)}` ); } } else if (semver.major(prevTypeVersion) > semver.major(typeInfo.version)) { - // Warn user if we are expecting a newer major schema version than the one they are providing + // Warn user if previous schema version is a newer major version return { success: false, info: `Profile type ${profileType} expects a newer schema version than provided by ${typeInfo.sourceApp}\n`.concat( @@ -1339,29 +1372,30 @@ export class ProfileInfo { }; } } else { - // There wasn't a previous version, so we can update the schema + // No schema version specified previously; update the schema this.mExtendersJson.profileTypes[profileType] = { version: typeInfo.version, from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) }; - this.mProfileSchemaCache.set(profileType, typeInfo.schema); + this.updateSchemaAtLayer(profileType, typeInfo.schema); } } else if (typeInfo.version != null) { + // Warn user if this schema does not provide a valid version number return { success: false, - info: `New schema type for profile type ${profileType} is not SemVer-compliant; schema was not updated.` - } + info: `New schema type for profile type ${profileType} is not SemVer-compliant; schema was not updated` + }; } } else { - // Track the newly-contributed profile type in extenders.json + // Newly-contributed profile type; track in extenders.json this.mExtendersJson.profileTypes[profileType] = { version: typeInfo.version, from: [typeInfo.sourceApp] }; - this.mProfileSchemaCache.set(`${this.mLoadedConfig.layerActive().path}:${profileType}`, typeInfo.schema); + this.updateSchemaAtLayer(profileType, typeInfo.schema); } - // Update contents of extenders.json + // Update contents of extenders.json if it has changed if (!lodash.isEqual(oldExtendersJson, this.mExtendersJson)) { if (!this.writeExtendersJson()) { return { @@ -1387,35 +1421,25 @@ export class ProfileInfo { * - Source applications are tracked in the “from” list for each profile type in extenders.json * @returns {IConfigSchema} A config schema containing all applicable profile types */ - public buildSchema(sources?: string[]): IConfigSchema { + public buildSchema(sources?: string[], layer?: IConfigLayer): IConfigSchema { const finalSchema: Record = {}; - const teamConfigLayers = this.getTeamConfig().mLayers; - - for (let i = teamConfigLayers.length; i > 0; i--) { - // Grab types from each layer, starting with the highest-priority layer - const layer = teamConfigLayers[i]; - if (layer.properties.$schema == null) continue; - const schemaUri = new url.URL(layer.properties.$schema, url.pathToFileURL(layer.path)); - const schemaPath = url.fileURLToPath(schemaUri); - - if (!fs.existsSync(schemaPath)) continue; - - const profileTypesInLayer = [...this.mProfileSchemaCache.entries()] - .filter(([type, schema]) => type.includes(`${layer.path}:`)); - for (const [typeWithPath, schema] of profileTypesInLayer) { - const type = typeWithPath.split(":").pop(); - if (type == null) { - continue; - } - if (type in this.mExtendersJson.profileTypes) { - if (sources?.length > 0) { - // If a list of sources were provided, ensure the type is contributed at least one of these sources - if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { - finalSchema[type] = schema; - } - } else { + const desiredLayer = layer ?? this.getTeamConfig().layerActive(); + + const profileTypesInLayer = [...this.mProfileSchemaCache.entries()] + .filter(([type, _schema]) => type.includes(`${desiredLayer.path}:`)); + for (const [typeWithPath, schema] of profileTypesInLayer) { + const type = typeWithPath.split(":").pop(); + if (type == null) { + continue; + } + if (type in this.mExtendersJson.profileTypes) { + if (sources?.length > 0) { + // If a list of sources were provided, ensure the type is contributed at least one of these sources + if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { finalSchema[type] = schema; } + } else { + finalSchema[type] = schema; } } } @@ -1445,16 +1469,15 @@ export class ProfileInfo { if (type == null) { continue; } - // if (type in this.mExtendersJson.profileTypes) { - if (filteredBySource) { - // Only consider types contributed by at least one of these sources - if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { - profileTypes.add(type); - } - } else { + + if (filteredBySource) { + // Only consider types contributed by at least one of these sources + if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { profileTypes.add(type); } - //} + } else { + profileTypes.add(type); + } } } diff --git a/packages/imperative/src/config/src/doc/IExtenderOpts.ts b/packages/imperative/src/config/src/doc/IExtenderOpts.ts new file mode 100644 index 0000000000..4d150e45bc --- /dev/null +++ b/packages/imperative/src/config/src/doc/IExtenderOpts.ts @@ -0,0 +1,22 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +export type IExtendersJsonOpts = { + profileTypes: Record; +}; + +export type IAddProfTypeResult = { + success: boolean; + info: string; +}; \ No newline at end of file From 08c382e79d7a8b5414fb34a918d191206261538a Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 3 Jan 2024 13:52:42 -0500 Subject: [PATCH 11/92] fix: only write on-disk schema if changed or non-existent Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ProfileInfo.ts | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index e08784fa45..a62b5e51ae 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1309,11 +1309,19 @@ export class ProfileInfo { const layerPath = cachedType != null ? cachedType[0].substring(0, cachedType[0].indexOf(":")) : this.getTeamConfig().layerActive().path; const layerToUpdate = this.getTeamConfig().mLayers.find((l) => l.path === layerPath); + const cacheKey = `${layerPath}:${profileType}`; + + const sameSchemaExists = this.mProfileSchemaCache.has(cacheKey) && lodash.isEqual(this.mProfileSchemaCache.get(cacheKey), schema); + + // Update the cache with the newest schema for this profile type + this.mProfileSchemaCache.set(cacheKey, schema); + const schemaUri = new url.URL(layerToUpdate.properties.$schema, url.pathToFileURL(layerPath)); const schemaPath = url.fileURLToPath(schemaUri); - if (fs.existsSync(schemaPath)) { - jsonfile.writeFileSync(schemaPath, this.buildSchema([], layerToUpdate)); + // if profile type schema has changed or if it doesn't exist on-disk, rebuild schema and write to disk + if (!sameSchemaExists && fs.existsSync(schemaPath)) { + jsonfile.writeFileSync(schemaPath, this.buildSchema([], layerToUpdate), { spaces: 4 }); } } @@ -1432,15 +1440,14 @@ export class ProfileInfo { if (type == null) { continue; } - if (type in this.mExtendersJson.profileTypes) { - if (sources?.length > 0) { - // If a list of sources were provided, ensure the type is contributed at least one of these sources - if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { - finalSchema[type] = schema; - } - } else { + + if (sources?.length > 0 && type in this.mExtendersJson.profileTypes) { + // If a list of sources were provided, ensure the type is contributed by at least one of these sources + if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { finalSchema[type] = schema; } + } else { + finalSchema[type] = schema; } } From 2d767ceb07566a060ccc0e1fb06c6b6575f3ac7c Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 3 Jan 2024 14:22:51 -0500 Subject: [PATCH 12/92] fix: pass opts to buildDefaultProfile, v2 config checks Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ConfigBuilder.ts | 6 +++--- packages/imperative/src/config/src/ProfileInfo.ts | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/imperative/src/config/src/ConfigBuilder.ts b/packages/imperative/src/config/src/ConfigBuilder.ts index 1d5b1ddcef..8fbb4fafb8 100644 --- a/packages/imperative/src/config/src/ConfigBuilder.ts +++ b/packages/imperative/src/config/src/ConfigBuilder.ts @@ -31,7 +31,7 @@ export class ConfigBuilder { const config: IConfig = Config.empty(); for (const profile of impConfig.profiles) { - const defaultProfile = this.buildDefaultProfile(config, profile); + const defaultProfile = this.buildDefaultProfile(profile, opts); // Add the profile to config and set it as default lodash.set(config, `profiles.${profile.type}`, defaultProfile); @@ -56,7 +56,7 @@ export class ConfigBuilder { return { ...config, autoStore: true }; } - public static buildDefaultProfile(config: IConfig, profile: ICommandProfileTypeConfiguration): { + public static buildDefaultProfile(profile: ICommandProfileTypeConfiguration, opts?: IConfigBuilderOpts): { type: string; properties: Record; secure: string[] @@ -64,7 +64,7 @@ export class ConfigBuilder { const properties: { [key: string]: any } = {}; const secureProps: string[] = []; for (const [k, v] of Object.entries(profile.schema.properties)) { - if (v.includeInTemplate) { + if (opts.populateProperties && v.includeInTemplate) { if (v.secure) { secureProps.push(k); } else { diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index a62b5e51ae..f07bb269d3 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -984,10 +984,11 @@ export class ProfileInfo { this.mImpLogger.warn(err.message); } } + } else { + this.readExtendersJsonFromDisk(); } this.loadAllSchemas(); - this.readExtendersJsonFromDisk(); } // _______________________________________________________________________ @@ -1290,7 +1291,7 @@ export class ProfileInfo { } this.getTeamConfig().api.profiles.set(layerPath ? `${layerPath}.${profileType}` : profileType, - ConfigBuilder.buildDefaultProfile(this.mLoadedConfig.mProperties, { type: profileType, schema: profileSchema })); + ConfigBuilder.buildDefaultProfile({ type: profileType, schema: profileSchema }, { populateProperties: true })); return true; } From 92aea562de16a4139d5b69f0b1752eeb9564fed9 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 3 Jan 2024 14:40:22 -0500 Subject: [PATCH 13/92] fix: updateSchemaAtLayer optimizations when version is changed Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index f07bb269d3..cf6e500a34 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1302,7 +1302,7 @@ export class ProfileInfo { * @param {IProfileSchema} typeSchema The schema to add for the profile type * @returns {boolean} `true` if added to the schema; `false` otherwise */ - private updateSchemaAtLayer(profileType: string, schema: IProfileSchema): void { + private updateSchemaAtLayer(profileType: string, schema: IProfileSchema, versionChanged?: boolean): void { // Check if type already exists in schema cache; if so, update schema at the same layer. // Otherwise, update schema at the active layer. const cachedType = [...this.mProfileSchemaCache.entries()] @@ -1312,7 +1312,8 @@ export class ProfileInfo { const layerToUpdate = this.getTeamConfig().mLayers.find((l) => l.path === layerPath); const cacheKey = `${layerPath}:${profileType}`; - const sameSchemaExists = this.mProfileSchemaCache.has(cacheKey) && lodash.isEqual(this.mProfileSchemaCache.get(cacheKey), schema); + const sameSchemaExists = versionChanged ? false : + this.mProfileSchemaCache.has(cacheKey) && lodash.isEqual(this.mProfileSchemaCache.get(cacheKey), schema); // Update the cache with the newest schema for this profile type this.mProfileSchemaCache.set(cacheKey, schema); @@ -1363,7 +1364,7 @@ export class ProfileInfo { from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) }; - this.updateSchemaAtLayer(profileType, typeInfo.schema); + this.updateSchemaAtLayer(profileType, typeInfo.schema, true); if (semver.major(typeInfo.version) != semver.major(prevTypeVersion)) { // Warn user if new major schema version is specified @@ -1386,7 +1387,7 @@ export class ProfileInfo { version: typeInfo.version, from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) }; - this.updateSchemaAtLayer(profileType, typeInfo.schema); + this.updateSchemaAtLayer(profileType, typeInfo.schema, true); } } else if (typeInfo.version != null) { // Warn user if this schema does not provide a valid version number From 16904fe4a6a2322065bf6d75176cdaa9c995c776 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Thu, 4 Jan 2024 10:52:09 -0500 Subject: [PATCH 14/92] tests: coverage for ProfileInfo schema mgmt. (1/2) Signed-off-by: Trae Yelovich --- .../ProfileInfo.TeamConfig.unit.test.ts | 143 ++++++++++++++++++ .../imperative/src/config/src/ProfileInfo.ts | 19 +-- 2 files changed, 151 insertions(+), 11 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index c003154afb..56cfc5aab5 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -9,6 +9,7 @@ * */ +import * as fs from "fs"; import * as path from "path"; import * as jsonfile from "jsonfile"; import * as lodash from "lodash"; @@ -26,6 +27,7 @@ import { ConfigAutoStore } from "../src/ConfigAutoStore"; import { ImperativeConfig } from "../../utilities/src/ImperativeConfig"; import { ImperativeError } from "../../error"; import { IProfInfoUpdatePropOpts } from "../src/doc/IProfInfoUpdatePropOpts"; +import { ConfigProfiles } from "../src/api"; const testAppNm = "ProfInfoApp"; const testEnvPrefix = testAppNm.toUpperCase(); @@ -1317,4 +1319,145 @@ describe("TeamConfig ProfileInfo tests", () => { } expect(Date.now() - startTime).toBeLessThan(15000); }); + + // begin schema management tests + describe("readExtendersJsonFromDisk", () => { + // case 1: the JSON file doesn't exist at time of read + it("writes an empty extenders.json file if it doesn't exist on disk", async () => { + const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); + const profInfo = createNewProfInfo(teamProjDir); + (profInfo as any).mExtendersJson = { profileTypes: {} }; + jest.spyOn(fs, "existsSync").mockReturnValue(false); + (profInfo as any).readExtendersJsonFromDisk(); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); + + // case 2: JSON file exists on-disk at time of read + it("reads extenders.json from disk if it exists", async () => { + const readFileSyncMock = jest.spyOn(jsonfile, "readFileSync").mockReturnValueOnce({ profileTypes: { + "test": { + from: ["Zowe Client App"] + } + } }); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + expect(readFileSyncMock).toHaveBeenCalled(); + expect((profInfo as any).mExtendersJson).toEqual({ + profileTypes: { + "test": { + from: ["Zowe Client App"] + } + } + }); + }); + }); + + describe("writeExtendersJson", () => { + // case 1: Write operation is successful + it("returns true if written to disk successfully", async () => { + const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); + const profInfo = createNewProfInfo(teamProjDir); + (profInfo as any).mExtendersJson = { profileTypes: {} }; + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + expect((profInfo as any).writeExtendersJson()).toBe(true); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); + + // case 2: Write operation is unsuccessful + it("returns false if it couldn't write to disk", async () => { + const profInfo = createNewProfInfo(teamProjDir); + (profInfo as any).mExtendersJson = { profileTypes: {} }; + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync") + .mockImplementation(() => { throw new Error(); }); + expect((profInfo as any).writeExtendersJson()).toBe(false); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); + }); + + describe("updateSchemaAtLayer", () => { + const getBlockMocks = () => { + const writeFileSync = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); + const buildSchema = jest.spyOn(ProfileInfo.prototype, "buildSchema"); + return { + buildSchema, + writeFileSync + }; + }; + + // case 1: schema is the same as the cached one; do not write to disk + it("does not write schema to disk if it hasn't changed", async () => { + const blockMocks = getBlockMocks(); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const dummySchema = profInfo.getSchemaForType("dummy"); + blockMocks.buildSchema.mockReturnValueOnce({} as any); + (profInfo as any).updateSchemaAtLayer("dummy", dummySchema); + expect(blockMocks.writeFileSync).not.toHaveBeenCalled(); + }); + + // case 2: schema is different than cached schema; write to disk + it("writes schema to disk when changed", async () => { + const blockMocks = getBlockMocks(); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + // not a major adjustment to schema - mainly to test schema comparison + blockMocks.buildSchema.mockReturnValueOnce({} as any); + jest.spyOn(fs, "existsSync").mockReturnValue(true); + (profInfo as any).updateSchemaAtLayer("dummy", {}); + expect(blockMocks.writeFileSync).toHaveBeenCalled(); + }); + }); + + describe("addProfileToConfig", () => { + // case 1: Successfully added profile w/ defaults to config + it("returns true if the profile was added", async () => { + const setProfileMock = jest.spyOn(ConfigProfiles.prototype, "set").mockImplementation(); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const res = profInfo.addProfileToConfig("dummy", "some.config.path"); + expect(res).toBe(true); + expect(setProfileMock).toHaveBeenCalled(); + }); + + // case 2: Profile was not added to config + it("returns false if the profile was not added", async () => { + const setProfileMock = jest.spyOn(ConfigProfiles.prototype, "set").mockImplementation(); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + // scenario: user passes a type that does not have an entry in the schema cache + const res = profInfo.addProfileToConfig("type-that-doesnt-exist", "some.config.path"); + expect(res).toBe(false); + expect(setProfileMock).not.toHaveBeenCalled(); + }); + }); + + describe("getProfileTypes", () => { + // case 1: no sources specified, returns profile types without filtering + it("returns the default set of profile types", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const expectedTypes = [...profileTypes].concat(["ssh"]).sort(); + expect(profInfo.getProfileTypes()).toEqual(expectedTypes); + }); + // TODO: case 2: filtering by source + }); + + describe("getSchemaForType", () => { + // case 1: returns the schema for a registered profile type + it("returns the schema for 'dummy' type", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + expect(profInfo.getSchemaForType("dummy")).toBeDefined(); + }); + + // case 2: returns undefined if the profile type doesn't exist in the schema cache + it("returns undefined for a non-existent profile type", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + expect(profInfo.getSchemaForType("type-that-doesnt-exist")).toBeUndefined(); + }); + }); + // TODO: getProfileTypes, buildSchema, addProfileTypeToSchema + // end schema management tests }); diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index cf6e500a34..e813500dd2 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1276,9 +1276,9 @@ export class ProfileInfo { public addProfileToConfig(profileType: string, layerPath?: string): boolean { // Find the schema in the cache, starting with the highest-priority layer and working up const profileSchema = [...this.getTeamConfig().mLayers].reverse() - .reduce((prev: IProfileSchema, layer) => { + .reduce((prev: IProfileSchema, cfgLayer) => { const cachedSchema = [...this.mProfileSchemaCache.entries()] - .filter(([typeWithPath, schema]) => typeWithPath.includes(`:${profileType}`))[0]; + .filter(([typeWithPath, schema]) => typeWithPath.includes(`${cfgLayer.path}:${profileType}`))[0]; if (cachedSchema != null) { prev = cachedSchema[1]; } @@ -1308,13 +1308,12 @@ export class ProfileInfo { const cachedType = [...this.mProfileSchemaCache.entries()] .find(([typePath, _schema]) => typePath.includes(`:${profileType}`)); - const layerPath = cachedType != null ? cachedType[0].substring(0, cachedType[0].indexOf(":")) : this.getTeamConfig().layerActive().path; + const layerPath = cachedType != null ? cachedType[0].substring(0, cachedType[0].lastIndexOf(":")) : this.getTeamConfig().layerActive().path; const layerToUpdate = this.getTeamConfig().mLayers.find((l) => l.path === layerPath); const cacheKey = `${layerPath}:${profileType}`; const sameSchemaExists = versionChanged ? false : this.mProfileSchemaCache.has(cacheKey) && lodash.isEqual(this.mProfileSchemaCache.get(cacheKey), schema); - // Update the cache with the newest schema for this profile type this.mProfileSchemaCache.set(cacheKey, schema); @@ -1479,7 +1478,7 @@ export class ProfileInfo { continue; } - if (filteredBySource) { + if (filteredBySource && type in this.mExtendersJson.profileTypes) { // Only consider types contributed by at least one of these sources if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { profileTypes.add(type); @@ -1507,18 +1506,16 @@ export class ProfileInfo { * @returns {IProfileSchema} The schema object provided by the specified profile type */ public getSchemaForType(profileType: string): IProfileSchema { - let finalSchema: IProfileSchema = null; - for (let i = this.getTeamConfig().mLayers.length; i > 0; i--) { + let finalSchema: IProfileSchema = undefined; + for (let i = this.getTeamConfig().mLayers.length - 1; i > 0; i--) { const layer = this.getTeamConfig().mLayers[i]; const profileTypesFromLayer = [...this.mProfileSchemaCache.entries()].filter(([key, value]) => key.includes(`${layer.path}:`)); for (const [layerType, schema] of profileTypesFromLayer) { const type = layerType.split(":").pop(); - if (type == null) { + if (type !== profileType) { continue; } - if (type === profileType) { - finalSchema = schema[1]; - } + finalSchema = schema; } } From 2202b1a686d19e2cd754fbd87e1bd365bd32d81d Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Thu, 4 Jan 2024 11:41:09 -0500 Subject: [PATCH 15/92] fix: use localeCompare when sorting profile types Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index e813500dd2..9d16f9eab2 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1496,7 +1496,7 @@ export class ProfileInfo { } } - return [...profileTypes].sort(); + return [...profileTypes].sort((a, b) => a.localeCompare(b)); } /** From fba021a5e94a28cf6ccad175da3cdd38304a9299 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Thu, 4 Jan 2024 14:01:38 -0500 Subject: [PATCH 16/92] tests: addProfileTypeToSchema scenarios Signed-off-by: Trae Yelovich --- .../ProfileInfo.TeamConfig.unit.test.ts | 106 +++++++++++++++++- .../imperative/src/config/src/ProfileInfo.ts | 22 ++-- 2 files changed, 114 insertions(+), 14 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 56cfc5aab5..af8800b839 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -28,6 +28,7 @@ import { ImperativeConfig } from "../../utilities/src/ImperativeConfig"; import { ImperativeError } from "../../error"; import { IProfInfoUpdatePropOpts } from "../src/doc/IProfInfoUpdatePropOpts"; import { ConfigProfiles } from "../src/api"; +import { IExtendersJsonOpts } from "../src/doc/IExtenderOpts"; const testAppNm = "ProfInfoApp"; const testEnvPrefix = testAppNm.toUpperCase(); @@ -1436,16 +1437,24 @@ describe("TeamConfig ProfileInfo tests", () => { // case 1: no sources specified, returns profile types without filtering it("returns the default set of profile types", async () => { const profInfo = createNewProfInfo(teamProjDir); + jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); const expectedTypes = [...profileTypes].concat(["ssh"]).sort(); expect(profInfo.getProfileTypes()).toEqual(expectedTypes); }); // TODO: case 2: filtering by source + it("filters by source", async () => { + const profInfo = createNewProfInfo(teamProjDir); + jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + profInfo.addProfileTypeToSchema("some-type", { sourceApp: "Zowe Client App", schema: {} as any }); + expect(profInfo.getProfileTypes(["Zowe Client App"])).toEqual(["some-type"]); + }); }); describe("getSchemaForType", () => { // case 1: returns the schema for a registered profile type - it("returns the schema for 'dummy' type", async () => { + it("returns the schema for a registered type", async () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); expect(profInfo.getSchemaForType("dummy")).toBeDefined(); @@ -1458,6 +1467,99 @@ describe("TeamConfig ProfileInfo tests", () => { expect(profInfo.getSchemaForType("type-that-doesnt-exist")).toBeUndefined(); }); }); - // TODO: getProfileTypes, buildSchema, addProfileTypeToSchema + + describe("addProfileTypeToSchema", () => { + const expectAddToSchemaTester = async (testCase: { schema: any; previousVersion?: string; version?: string }, expected: { + extendersJson: IExtendersJsonOpts, + res: { + success: boolean; + info?: string; + }, + version?: string, + }) => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + if (testCase.previousVersion) { + (profInfo as any).mExtendersJson = { + profileTypes: { + "some-type": { + from: ["Zowe Client App"], + version: testCase.previousVersion === "none" ? undefined : testCase.previousVersion + } + } + }; + } else { + (profInfo as any).mExtendersJson = { + profileTypes: {} + }; + } + const updateSchemaAtLayerMock = jest.spyOn((ProfileInfo as any).prototype, "updateSchemaAtLayer").mockImplementation(); + const writeExtendersJsonMock = jest.spyOn((ProfileInfo as any).prototype, "writeExtendersJson").mockImplementation(); + const res = profInfo.addProfileTypeToSchema("some-type", { ...testCase, sourceApp: "Zowe Client App" }); + if (expected.res.success) { + expect(updateSchemaAtLayerMock).toHaveBeenCalled(); + expect(writeExtendersJsonMock).toHaveBeenCalled(); + } else { + expect(updateSchemaAtLayerMock).not.toHaveBeenCalled(); + expect(writeExtendersJsonMock).not.toHaveBeenCalled(); + } + expect((profInfo as any).mExtendersJson).toEqual(expected.extendersJson); + expect(res.success).toBe(expected.res.success); + if (expected.res.info) { + expect(res.info).toBe(expected.res.info); + } + }; + // case 1: Profile type did not exist + it("adds a new profile type to the schema", async () => { + expectAddToSchemaTester( + { schema: { title: "Mock Schema" } as any }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"] } } }, + res: { + success: true + } + } + ); + }); + + it("only updates a profile type in the schema if the version is newer", async () => { + expectAddToSchemaTester( + { previousVersion: "1.0.0", schema: { title: "Mock Schema" } as any, version: "2.0.0" }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "2.0.0" } } }, + res: { + success: true + } + } + ); + }); + + it("does not update a profile type in the schema if the version is older", async () => { + expectAddToSchemaTester( + { previousVersion: "2.0.0", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "2.0.0" } } }, + res: { + success: false + } + } + ); + }); + + it("updates a profile type in the schema - version provided, no previous schema version", async () => { + expectAddToSchemaTester( + { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "1.0.0" } } }, + res: { + success: true + } + } + ); + }); + }); + describe("buildSchema", () => { + // TODO + }); // end schema management tests }); diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 9d16f9eab2..7d33a6fd11 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1244,6 +1244,7 @@ export class ProfileInfo { jsonfile.writeFileSync(extenderJsonPath, { profileTypes: {} }, { spaces: 4 }); + this.mExtendersJson = { profileTypes: {} }; } else { this.mExtendersJson = jsonfile.readFileSync(extenderJsonPath); } @@ -1478,22 +1479,19 @@ export class ProfileInfo { continue; } - if (filteredBySource && type in this.mExtendersJson.profileTypes) { - // Only consider types contributed by at least one of these sources - if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { - profileTypes.add(type); - } - } else { - profileTypes.add(type); - } + profileTypes.add(type); } } // Include all profile types from extenders.json if we are not filtering by source - if (!filteredBySource) { - for (const type of Object.keys(this.mExtendersJson.profileTypes)) { - profileTypes.add(type); - } + if (filteredBySource) { + return [...profileTypes].filter((t) => { + if (!(t in this.mExtendersJson.profileTypes)) { + return false; + } + + return this.mExtendersJson.profileTypes[t].from.some((src) => sources.includes(src)); + }).sort((a, b) => a.localeCompare(b)); } return [...profileTypes].sort((a, b) => a.localeCompare(b)); From fdbe5ab3787f73fdd612299901275f3a0bbcc99c Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 5 Jan 2024 08:48:19 -0500 Subject: [PATCH 17/92] tests: ProfileInfo.buildSchema scenarios Signed-off-by: Trae Yelovich --- .../ProfileInfo.TeamConfig.unit.test.ts | 35 +++++++++++++++++++ .../imperative/src/config/src/ProfileInfo.ts | 23 ++++++++---- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index af8800b839..63a634cbf5 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -29,6 +29,7 @@ import { ImperativeError } from "../../error"; import { IProfInfoUpdatePropOpts } from "../src/doc/IProfInfoUpdatePropOpts"; import { ConfigProfiles } from "../src/api"; import { IExtendersJsonOpts } from "../src/doc/IExtenderOpts"; +import { ConfigSchema } from "../src/ConfigSchema"; const testAppNm = "ProfInfoApp"; const testEnvPrefix = testAppNm.toUpperCase(); @@ -1557,9 +1558,43 @@ describe("TeamConfig ProfileInfo tests", () => { } ); }); + + it("does not update the schema if schema version is invalid", async () => { + expectAddToSchemaTester( + { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "1.0.0" } } }, + res: { + success: true + } + } + ); + }); }); describe("buildSchema", () => { // TODO + it("builds a schema with the default types", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const cfgSchemaBuildMock = jest.spyOn(ConfigSchema, "buildSchema").mockImplementation(); + profInfo.buildSchema(); + expect(cfgSchemaBuildMock).toHaveBeenCalled(); + }); + + it("excludes types that do not match a given source", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + profInfo.addProfileTypeToSchema("some-type-with-source", { + sourceApp: "A Zowe App", + schema: {} as any + }); + const cfgSchemaBuildMock = jest.spyOn(ConfigSchema, "buildSchema").mockImplementation(); + profInfo.buildSchema(["A Zowe App"]); + expect(cfgSchemaBuildMock).toHaveBeenCalledWith([{ + type: "some-type-with-source", + schema: {} + }]); + }); }); // end schema management tests }); diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 7d33a6fd11..cdad5b5afb 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1443,17 +1443,26 @@ export class ProfileInfo { continue; } - if (sources?.length > 0 && type in this.mExtendersJson.profileTypes) { + finalSchema[type] = schema; + } + + let schemaEntries = Object.entries(finalSchema); + if (sources?.length > 0) { + schemaEntries = schemaEntries.filter(([typ, sch]) => { + if (!(typ in this.mExtendersJson.profileTypes)) { + return false; + } + // If a list of sources were provided, ensure the type is contributed by at least one of these sources - if (sources.some((val) => this.mExtendersJson.profileTypes[type].from.includes(val))) { - finalSchema[type] = schema; + if (sources.some((val) => this.mExtendersJson.profileTypes[typ].from.includes(val))) { + return true; } - } else { - finalSchema[type] = schema; - } + + return false; + }); } - return ConfigSchema.buildSchema(Object.entries(finalSchema).map(([type, schema]) => ({ + return ConfigSchema.buildSchema(schemaEntries.map(([type, schema]) => ({ type, schema }))); From eed79d0fce7acdecfdf7e9f927a589d933a1a1fe Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 5 Jan 2024 09:43:59 -0500 Subject: [PATCH 18/92] chore: update changelog Signed-off-by: Trae Yelovich --- packages/imperative/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index f87cd19d32..c0b13c0575 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- Enhancement: Added multiple APIs to manage schemas between Zowe client applications using the ProfileInfo class. + ## `5.19.0` - Enhancement: Deprecated function AbstractCommandYargs.getBrightYargsResponse in favor of AbstractCommandYargs.getZoweYargsResponse From b0f00711370affdfed49fc45d9948dd2b67d0405 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 5 Jan 2024 10:33:40 -0500 Subject: [PATCH 19/92] fix(tests): Mock jsonfile.writeFileSync to minimize I/O ops Signed-off-by: Trae Yelovich --- .../ProfileInfo.TeamConfig.unit.test.ts | 473 +++++++++--------- 1 file changed, 236 insertions(+), 237 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 63a634cbf5..beecaa9026 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -61,6 +61,7 @@ describe("TeamConfig ProfileInfo tests", () => { const envRFH = testEnvPrefix + "_OPT_RESPONSE_FORMAT_HEADER"; const envArray = testEnvPrefix + "_OPT_LIST"; + let writeFileSyncMock: jest.SpyInstance; beforeAll(() => { // remember our original directory origDir = process.cwd(); @@ -69,6 +70,8 @@ describe("TeamConfig ProfileInfo tests", () => { beforeEach(() => { // set our desired app home directory into the environment process.env[testEnvPrefix + "_CLI_HOME"] = teamProjDir; + // mock jsonfile.writeFileSync to avoid writing files to disk during testing + writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); }); afterAll(() => { @@ -1322,279 +1325,275 @@ describe("TeamConfig ProfileInfo tests", () => { expect(Date.now() - startTime).toBeLessThan(15000); }); - // begin schema management tests - describe("readExtendersJsonFromDisk", () => { - // case 1: the JSON file doesn't exist at time of read - it("writes an empty extenders.json file if it doesn't exist on disk", async () => { - const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); - const profInfo = createNewProfInfo(teamProjDir); - (profInfo as any).mExtendersJson = { profileTypes: {} }; - jest.spyOn(fs, "existsSync").mockReturnValue(false); - (profInfo as any).readExtendersJsonFromDisk(); - expect(writeFileSyncMock).toHaveBeenCalled(); - }); + describe("Schema management", () => { + // begin schema management tests + describe("readExtendersJsonFromDisk", () => { + // case 1: the JSON file doesn't exist at time of read + it("writes an empty extenders.json file if it doesn't exist on disk", async () => { + const profInfo = createNewProfInfo(teamProjDir); + (profInfo as any).mExtendersJson = { profileTypes: {} }; + jest.spyOn(fs, "existsSync").mockReturnValueOnce(false); + (profInfo as any).readExtendersJsonFromDisk(); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); - // case 2: JSON file exists on-disk at time of read - it("reads extenders.json from disk if it exists", async () => { - const readFileSyncMock = jest.spyOn(jsonfile, "readFileSync").mockReturnValueOnce({ profileTypes: { - "test": { - from: ["Zowe Client App"] - } - } }); - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - expect(readFileSyncMock).toHaveBeenCalled(); - expect((profInfo as any).mExtendersJson).toEqual({ - profileTypes: { + // case 2: JSON file exists on-disk at time of read + it("reads extenders.json from disk if it exists", async () => { + const readFileSyncMock = jest.spyOn(jsonfile, "readFileSync").mockReturnValueOnce({ profileTypes: { "test": { from: ["Zowe Client App"] } - } + } }); + const profInfo = createNewProfInfo(teamProjDir); + jest.spyOn(fs, "existsSync").mockReturnValueOnce(true); + (profInfo as any).readExtendersJsonFromDisk(); + expect(readFileSyncMock).toHaveBeenCalled(); + expect((profInfo as any).mExtendersJson).toEqual({ + profileTypes: { + "test": { + from: ["Zowe Client App"] + } + } + }); }); }); - }); - describe("writeExtendersJson", () => { - // case 1: Write operation is successful - it("returns true if written to disk successfully", async () => { - const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); - const profInfo = createNewProfInfo(teamProjDir); - (profInfo as any).mExtendersJson = { profileTypes: {} }; - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - expect((profInfo as any).writeExtendersJson()).toBe(true); - expect(writeFileSyncMock).toHaveBeenCalled(); - }); + describe("writeExtendersJson", () => { + // case 1: Write operation is successful + it("returns true if written to disk successfully", async () => { + const profInfo = createNewProfInfo(teamProjDir); + (profInfo as any).mExtendersJson = { profileTypes: {} }; + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + expect((profInfo as any).writeExtendersJson()).toBe(true); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); - // case 2: Write operation is unsuccessful - it("returns false if it couldn't write to disk", async () => { - const profInfo = createNewProfInfo(teamProjDir); - (profInfo as any).mExtendersJson = { profileTypes: {} }; - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync") - .mockImplementation(() => { throw new Error(); }); - expect((profInfo as any).writeExtendersJson()).toBe(false); - expect(writeFileSyncMock).toHaveBeenCalled(); + // case 2: Write operation is unsuccessful + it("returns false if it couldn't write to disk", async () => { + const profInfo = createNewProfInfo(teamProjDir); + (profInfo as any).mExtendersJson = { profileTypes: {} }; + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + writeFileSyncMock.mockImplementation(() => { throw new Error(); }); + expect((profInfo as any).writeExtendersJson()).toBe(false); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); }); - }); - describe("updateSchemaAtLayer", () => { - const getBlockMocks = () => { - const writeFileSync = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); - const buildSchema = jest.spyOn(ProfileInfo.prototype, "buildSchema"); - return { - buildSchema, - writeFileSync + describe("updateSchemaAtLayer", () => { + const getBlockMocks = () => { + return { + buildSchema: jest.spyOn(ProfileInfo.prototype, "buildSchema") + }; }; - }; - // case 1: schema is the same as the cached one; do not write to disk - it("does not write schema to disk if it hasn't changed", async () => { - const blockMocks = getBlockMocks(); - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - const dummySchema = profInfo.getSchemaForType("dummy"); - blockMocks.buildSchema.mockReturnValueOnce({} as any); - (profInfo as any).updateSchemaAtLayer("dummy", dummySchema); - expect(blockMocks.writeFileSync).not.toHaveBeenCalled(); - }); + // case 1: schema is the same as the cached one; do not write to disk + it("does not write schema to disk if it hasn't changed", async () => { + const blockMocks = getBlockMocks(); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const dummySchema = profInfo.getSchemaForType("dummy"); + blockMocks.buildSchema.mockReturnValueOnce({} as any); + writeFileSyncMock.mockClear(); + (profInfo as any).updateSchemaAtLayer("dummy", dummySchema); + expect(writeFileSyncMock).not.toHaveBeenCalled(); + }); - // case 2: schema is different than cached schema; write to disk - it("writes schema to disk when changed", async () => { - const blockMocks = getBlockMocks(); - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - // not a major adjustment to schema - mainly to test schema comparison - blockMocks.buildSchema.mockReturnValueOnce({} as any); - jest.spyOn(fs, "existsSync").mockReturnValue(true); - (profInfo as any).updateSchemaAtLayer("dummy", {}); - expect(blockMocks.writeFileSync).toHaveBeenCalled(); + // case 2: schema is different than cached schema; write to disk + it("writes schema to disk when changed", async () => { + const blockMocks = getBlockMocks(); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + // not a major adjustment to schema - mainly to test schema comparison + blockMocks.buildSchema.mockReturnValueOnce({} as any); + jest.spyOn(fs, "existsSync").mockReturnValueOnce(true); + (profInfo as any).updateSchemaAtLayer("dummy", {}); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); }); - }); - describe("addProfileToConfig", () => { - // case 1: Successfully added profile w/ defaults to config - it("returns true if the profile was added", async () => { - const setProfileMock = jest.spyOn(ConfigProfiles.prototype, "set").mockImplementation(); - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - const res = profInfo.addProfileToConfig("dummy", "some.config.path"); - expect(res).toBe(true); - expect(setProfileMock).toHaveBeenCalled(); - }); + describe("addProfileToConfig", () => { + // case 1: Successfully added profile w/ defaults to config + it("returns true if the profile was added", async () => { + const setProfileMock = jest.spyOn(ConfigProfiles.prototype, "set").mockImplementation(); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const res = profInfo.addProfileToConfig("dummy", "some.config.path"); + expect(res).toBe(true); + expect(setProfileMock).toHaveBeenCalled(); + }); - // case 2: Profile was not added to config - it("returns false if the profile was not added", async () => { - const setProfileMock = jest.spyOn(ConfigProfiles.prototype, "set").mockImplementation(); - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - // scenario: user passes a type that does not have an entry in the schema cache - const res = profInfo.addProfileToConfig("type-that-doesnt-exist", "some.config.path"); - expect(res).toBe(false); - expect(setProfileMock).not.toHaveBeenCalled(); + // case 2: Profile was not added to config + it("returns false if the profile was not added", async () => { + const setProfileMock = jest.spyOn(ConfigProfiles.prototype, "set").mockImplementation(); + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + // scenario: user passes a type that does not have an entry in the schema cache + const res = profInfo.addProfileToConfig("type-that-doesnt-exist", "some.config.path"); + expect(res).toBe(false); + expect(setProfileMock).not.toHaveBeenCalled(); + }); }); - }); - describe("getProfileTypes", () => { - // case 1: no sources specified, returns profile types without filtering - it("returns the default set of profile types", async () => { - const profInfo = createNewProfInfo(teamProjDir); - jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - const expectedTypes = [...profileTypes].concat(["ssh"]).sort(); - expect(profInfo.getProfileTypes()).toEqual(expectedTypes); - }); - // TODO: case 2: filtering by source - it("filters by source", async () => { - const profInfo = createNewProfInfo(teamProjDir); - jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - profInfo.addProfileTypeToSchema("some-type", { sourceApp: "Zowe Client App", schema: {} as any }); - expect(profInfo.getProfileTypes(["Zowe Client App"])).toEqual(["some-type"]); + describe("getProfileTypes", () => { + // case 1: no sources specified, returns profile types without filtering + it("returns the default set of profile types", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const expectedTypes = [...profileTypes].concat(["ssh"]).sort(); + expect(profInfo.getProfileTypes()).toEqual(expectedTypes); + }); + // TODO: case 2: filtering by source + it("filters by source", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + profInfo.addProfileTypeToSchema("some-type", { sourceApp: "Zowe Client App", schema: {} as any }); + expect(profInfo.getProfileTypes(["Zowe Client App"])).toEqual(["some-type"]); + }); }); - }); - describe("getSchemaForType", () => { - // case 1: returns the schema for a registered profile type - it("returns the schema for a registered type", async () => { - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - expect(profInfo.getSchemaForType("dummy")).toBeDefined(); - }); + describe("getSchemaForType", () => { + // case 1: returns the schema for a registered profile type + it("returns the schema for a registered type", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + expect(profInfo.getSchemaForType("dummy")).toBeDefined(); + }); - // case 2: returns undefined if the profile type doesn't exist in the schema cache - it("returns undefined for a non-existent profile type", async () => { - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - expect(profInfo.getSchemaForType("type-that-doesnt-exist")).toBeUndefined(); + // case 2: returns undefined if the profile type doesn't exist in the schema cache + it("returns undefined for a non-existent profile type", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + expect(profInfo.getSchemaForType("type-that-doesnt-exist")).toBeUndefined(); + }); }); - }); - describe("addProfileTypeToSchema", () => { - const expectAddToSchemaTester = async (testCase: { schema: any; previousVersion?: string; version?: string }, expected: { - extendersJson: IExtendersJsonOpts, - res: { - success: boolean; - info?: string; - }, - version?: string, - }) => { - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - if (testCase.previousVersion) { - (profInfo as any).mExtendersJson = { - profileTypes: { - "some-type": { - from: ["Zowe Client App"], - version: testCase.previousVersion === "none" ? undefined : testCase.previousVersion + describe("addProfileTypeToSchema", () => { + const expectAddToSchemaTester = async (testCase: { schema: any; previousVersion?: string; version?: string }, expected: { + extendersJson: IExtendersJsonOpts, + res: { + success: boolean; + info?: string; + }, + version?: string, + }) => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + if (testCase.previousVersion) { + (profInfo as any).mExtendersJson = { + profileTypes: { + "some-type": { + from: ["Zowe Client App"], + version: testCase.previousVersion === "none" ? undefined : testCase.previousVersion + } } - } - }; - } else { - (profInfo as any).mExtendersJson = { - profileTypes: {} - }; - } - const updateSchemaAtLayerMock = jest.spyOn((ProfileInfo as any).prototype, "updateSchemaAtLayer").mockImplementation(); - const writeExtendersJsonMock = jest.spyOn((ProfileInfo as any).prototype, "writeExtendersJson").mockImplementation(); - const res = profInfo.addProfileTypeToSchema("some-type", { ...testCase, sourceApp: "Zowe Client App" }); - if (expected.res.success) { - expect(updateSchemaAtLayerMock).toHaveBeenCalled(); - expect(writeExtendersJsonMock).toHaveBeenCalled(); - } else { - expect(updateSchemaAtLayerMock).not.toHaveBeenCalled(); - expect(writeExtendersJsonMock).not.toHaveBeenCalled(); - } - expect((profInfo as any).mExtendersJson).toEqual(expected.extendersJson); - expect(res.success).toBe(expected.res.success); - if (expected.res.info) { - expect(res.info).toBe(expected.res.info); - } - }; - // case 1: Profile type did not exist - it("adds a new profile type to the schema", async () => { - expectAddToSchemaTester( - { schema: { title: "Mock Schema" } as any }, - { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"] } } }, - res: { - success: true - } + }; + } else { + (profInfo as any).mExtendersJson = { + profileTypes: {} + }; } - ); - }); + const updateSchemaAtLayerMock = jest.spyOn((ProfileInfo as any).prototype, "updateSchemaAtLayer").mockImplementation(); + const writeExtendersJsonMock = jest.spyOn((ProfileInfo as any).prototype, "writeExtendersJson").mockImplementation(); + const res = profInfo.addProfileTypeToSchema("some-type", { ...testCase, sourceApp: "Zowe Client App" }); + if (expected.res.success) { + expect(updateSchemaAtLayerMock).toHaveBeenCalled(); + expect(writeExtendersJsonMock).toHaveBeenCalled(); + } else { + expect(updateSchemaAtLayerMock).not.toHaveBeenCalled(); + expect(writeExtendersJsonMock).not.toHaveBeenCalled(); + } + expect((profInfo as any).mExtendersJson).toEqual(expected.extendersJson); + expect(res.success).toBe(expected.res.success); + if (expected.res.info) { + expect(res.info).toBe(expected.res.info); + } + }; + // case 1: Profile type did not exist + it("adds a new profile type to the schema", async () => { + expectAddToSchemaTester( + { schema: { title: "Mock Schema" } as any }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"] } } }, + res: { + success: true + } + } + ); + }); - it("only updates a profile type in the schema if the version is newer", async () => { - expectAddToSchemaTester( - { previousVersion: "1.0.0", schema: { title: "Mock Schema" } as any, version: "2.0.0" }, - { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "2.0.0" } } }, - res: { - success: true + it("only updates a profile type in the schema if the version is newer", async () => { + expectAddToSchemaTester( + { previousVersion: "1.0.0", schema: { title: "Mock Schema" } as any, version: "2.0.0" }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "2.0.0" } } }, + res: { + success: true + } } - } - ); - }); + ); + }); - it("does not update a profile type in the schema if the version is older", async () => { - expectAddToSchemaTester( - { previousVersion: "2.0.0", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, - { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "2.0.0" } } }, - res: { - success: false + it("does not update a profile type in the schema if the version is older", async () => { + expectAddToSchemaTester( + { previousVersion: "2.0.0", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "2.0.0" } } }, + res: { + success: false + } } - } - ); - }); + ); + }); - it("updates a profile type in the schema - version provided, no previous schema version", async () => { - expectAddToSchemaTester( - { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, - { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "1.0.0" } } }, - res: { - success: true + it("updates a profile type in the schema - version provided, no previous schema version", async () => { + expectAddToSchemaTester( + { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "1.0.0" } } }, + res: { + success: true + } } - } - ); - }); + ); + }); - it("does not update the schema if schema version is invalid", async () => { - expectAddToSchemaTester( - { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, - { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "1.0.0" } } }, - res: { - success: true + it("does not update the schema if schema version is invalid", async () => { + expectAddToSchemaTester( + { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { + extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "1.0.0" } } }, + res: { + success: true + } } - } - ); - }); - }); - describe("buildSchema", () => { - // TODO - it("builds a schema with the default types", async () => { - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - const cfgSchemaBuildMock = jest.spyOn(ConfigSchema, "buildSchema").mockImplementation(); - profInfo.buildSchema(); - expect(cfgSchemaBuildMock).toHaveBeenCalled(); + ); + }); }); + describe("buildSchema", () => { + // TODO + it("builds a schema with the default types", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + const cfgSchemaBuildMock = jest.spyOn(ConfigSchema, "buildSchema").mockImplementation(); + profInfo.buildSchema(); + expect(cfgSchemaBuildMock).toHaveBeenCalled(); + }); - it("excludes types that do not match a given source", async () => { - const profInfo = createNewProfInfo(teamProjDir); - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - profInfo.addProfileTypeToSchema("some-type-with-source", { - sourceApp: "A Zowe App", - schema: {} as any + it("excludes types that do not match a given source", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + profInfo.addProfileTypeToSchema("some-type-with-source", { + sourceApp: "A Zowe App", + schema: {} as any + }); + const cfgSchemaBuildMock = jest.spyOn(ConfigSchema, "buildSchema").mockImplementation(); + profInfo.buildSchema(["A Zowe App"]); + expect(cfgSchemaBuildMock).toHaveBeenCalledWith([{ + type: "some-type-with-source", + schema: {} + }]); }); - const cfgSchemaBuildMock = jest.spyOn(ConfigSchema, "buildSchema").mockImplementation(); - profInfo.buildSchema(["A Zowe App"]); - expect(cfgSchemaBuildMock).toHaveBeenCalledWith([{ - type: "some-type-with-source", - schema: {} - }]); }); + // end schema management tests }); - // end schema management tests }); From fc01621105150e777a56c9333776a01d1e4faf6a Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 5 Jan 2024 15:18:20 -0500 Subject: [PATCH 20/92] tests: remove TODO comments Signed-off-by: Trae Yelovich --- .../src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index beecaa9026..f8a7c1108d 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1442,7 +1442,7 @@ describe("TeamConfig ProfileInfo tests", () => { const expectedTypes = [...profileTypes].concat(["ssh"]).sort(); expect(profInfo.getProfileTypes()).toEqual(expectedTypes); }); - // TODO: case 2: filtering by source + // case 2: filtering by source it("filters by source", async () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); From 3ad8d55f3e17b537378f8f37b9ddc501b81285ad Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Mon, 8 Jan 2024 09:23:42 -0500 Subject: [PATCH 21/92] chore: Add comments to IExtendersJsonOpts, add latestFrom Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/doc/IExtenderOpts.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/imperative/src/config/src/doc/IExtenderOpts.ts b/packages/imperative/src/config/src/doc/IExtenderOpts.ts index 4d150e45bc..12836e8591 100644 --- a/packages/imperative/src/config/src/doc/IExtenderOpts.ts +++ b/packages/imperative/src/config/src/doc/IExtenderOpts.ts @@ -11,12 +11,20 @@ export type IExtendersJsonOpts = { profileTypes: Record; }; export type IAddProfTypeResult = { + // Whether the `addProfileTypeToSchema` function successfully added the schema. success: boolean; + // Any additional information from the `addProfileTypeToSchema` result. + // If `success` is false, `info` contains any context for why the function failed. info: string; }; \ No newline at end of file From d13ab7a78f887800e167732f1e1499954bc9b16b Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Mon, 8 Jan 2024 09:24:37 -0500 Subject: [PATCH 22/92] chore(tests): Fix formatting of objects Signed-off-by: Trae Yelovich --- .../ProfileInfo.TeamConfig.unit.test.ts | 48 +++++++++++++++++-- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index f8a7c1108d..72aed68420 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1513,7 +1513,13 @@ describe("TeamConfig ProfileInfo tests", () => { expectAddToSchemaTester( { schema: { title: "Mock Schema" } as any }, { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"] } } }, + extendersJson: { + profileTypes: { + "some-type": { + from: ["Zowe Client App"] + } + } + }, res: { success: true } @@ -1525,7 +1531,15 @@ describe("TeamConfig ProfileInfo tests", () => { expectAddToSchemaTester( { previousVersion: "1.0.0", schema: { title: "Mock Schema" } as any, version: "2.0.0" }, { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "2.0.0" } } }, + extendersJson: { + profileTypes: { + "some-type": { + from: ["Zowe Client App"], + version: "2.0.0", + latestFrom: "Zowe Client App" + } + } + }, res: { success: true } @@ -1537,7 +1551,15 @@ describe("TeamConfig ProfileInfo tests", () => { expectAddToSchemaTester( { previousVersion: "2.0.0", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "2.0.0" } } }, + extendersJson: { + profileTypes: { + "some-type": { + from: ["Zowe Client App"], + version: "2.0.0", + latestFrom: "Zowe Client App" + } + } + }, res: { success: false } @@ -1549,7 +1571,15 @@ describe("TeamConfig ProfileInfo tests", () => { expectAddToSchemaTester( { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "1.0.0" } } }, + extendersJson: { + profileTypes: { + "some-type": { + from: ["Zowe Client App"], + version: "1.0.0", + latestFrom: "Zowe Client App" + } + } + }, res: { success: true } @@ -1561,7 +1591,15 @@ describe("TeamConfig ProfileInfo tests", () => { expectAddToSchemaTester( { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, { - extendersJson: { profileTypes: { "some-type": { from: ["Zowe Client App"], version: "1.0.0" } } }, + extendersJson: { + profileTypes: { + "some-type": { + from: ["Zowe Client App"], + version: "1.0.0", + latestFrom: "Zowe Client App" + } + } + }, res: { success: true } From ba027668fda04ed7eb540de2d6b7a73488300112 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Mon, 8 Jan 2024 09:37:53 -0500 Subject: [PATCH 23/92] chore,feat: improve typedoc/types, add latestFrom if applicable Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ProfileInfo.ts | 30 ++++++++++++------- .../src/config/src/doc/IExtenderOpts.ts | 13 ++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index cdad5b5afb..9666e4ab9b 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -54,7 +54,7 @@ import { IGetAllProfilesOptions } from "./doc/IProfInfoProps"; import { IConfig } from "./doc/IConfig"; import { IProfInfoRemoveKnownPropOpts } from "./doc/IProfInfoRemoveKnownPropOpts"; import { ConfigBuilder } from "./ConfigBuilder"; -import { IAddProfTypeResult, IExtendersJsonOpts } from "./doc/IExtenderOpts"; +import { IAddProfTypeResult, IExtenderTypeInfo, IExtendersJsonOpts } from "./doc/IExtenderOpts"; import { IConfigLayer } from ".."; /** @@ -1271,6 +1271,7 @@ export class ProfileInfo { * * @param {string} profileType The profile type to add * @param [layerPath] A dot-separated path that points to a layer in the config (default: top-most layer) + * * Example: “outer.prod” would add a profile into the “prod” layer (which is contained in “outer” layer) * @returns {boolean} `true` if added to the loaded config; `false` otherwise */ @@ -1300,7 +1301,9 @@ export class ProfileInfo { * Updates the schema to contain the new profile type. * If the type exists in the cache, it will use the matching layer; if not found, it will use the schema at the active layer. * - * @param {IProfileSchema} typeSchema The schema to add for the profile type + * @param {string} profileType The profile type to add into the schema + * @param {IProfileSchema} typeSchema The schema for the profile type + * @param [versionChanged] Whether the version has changed for the schema (optional) * @returns {boolean} `true` if added to the schema; `false` otherwise */ private updateSchemaAtLayer(profileType: string, schema: IProfileSchema, versionChanged?: boolean): void { @@ -1328,14 +1331,15 @@ export class ProfileInfo { } /** - * Adds a profile type to the schema, and tracks its contribution in extenders.json. + * Adds a profile type to the schema, and tracks its contribution in extenders.json. + * * NOTE: `readProfilesFromDisk` must be called at least once before adding new profile types. * - * @param {IProfileSchema} typeSchema The schema to add for the profile type + * @param {string} profileType The new profile type to add to the schema + * @param {IExtenderTypeInfo} typeInfo Type metadata for the profile type (schema, source app., optional version) * @returns {boolean} `true` if added to the schema; `false` otherwise */ - public addProfileTypeToSchema(profileType: string, typeInfo: - { sourceApp: string; schema: IProfileSchema; version?: string }): IAddProfTypeResult { + public addProfileTypeToSchema(profileType: string, typeInfo: IExtenderTypeInfo): IAddProfTypeResult { // Get the active team config layer const activeLayer = this.getTeamConfig()?.layerActive(); if (activeLayer == null) { @@ -1361,7 +1365,8 @@ export class ProfileInfo { // Update the schema for this profile type, as its newer than the installed version this.mExtendersJson.profileTypes[profileType] = { version: typeInfo.version, - from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) + from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]), + latestFrom: typeInfo.sourceApp }; this.updateSchemaAtLayer(profileType, typeInfo.schema, true); @@ -1385,7 +1390,8 @@ export class ProfileInfo { // No schema version specified previously; update the schema this.mExtendersJson.profileTypes[profileType] = { version: typeInfo.version, - from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) + from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]), + latestFrom: typeInfo.sourceApp }; this.updateSchemaAtLayer(profileType, typeInfo.schema, true); } @@ -1429,6 +1435,8 @@ export class ProfileInfo { * * @param [sources] Include profile types contributed by these sources when building the schema * - Source applications are tracked in the “from” list for each profile type in extenders.json + * @param [layer] The config layer to build a schema for + * - If a layer is not specified, `buildSchema` will use the active layer. * @returns {IConfigSchema} A config schema containing all applicable profile types */ public buildSchema(sources?: string[], layer?: IConfigLayer): IConfigSchema { @@ -1469,9 +1477,9 @@ export class ProfileInfo { } /** - * Returns a list of all available profile types - * @param [sources] Include all available types from given source applications - */ + * @param [sources] (optional) Only include available types from the given list of sources + * @returns a list of all available profile types + */ public getProfileTypes(sources?: string[]): string[] { const filteredBySource = sources?.length > 0; const profileTypes = new Set(); diff --git a/packages/imperative/src/config/src/doc/IExtenderOpts.ts b/packages/imperative/src/config/src/doc/IExtenderOpts.ts index 12836e8591..d11d27c8ad 100644 --- a/packages/imperative/src/config/src/doc/IExtenderOpts.ts +++ b/packages/imperative/src/config/src/doc/IExtenderOpts.ts @@ -9,7 +9,11 @@ * */ +import { IProfileSchema } from "../../../profiles"; + export type IExtendersJsonOpts = { + // A map of profile types to type metadata. + // Used to track contributed profile types between Zowe client applications. profileTypes: Record Date: Mon, 8 Jan 2024 10:42:23 -0500 Subject: [PATCH 24/92] fix(tests): add latestFrom to scenarios in unit tests Signed-off-by: Trae Yelovich --- .../src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 72aed68420..511cdee506 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1479,11 +1479,13 @@ describe("TeamConfig ProfileInfo tests", () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); if (testCase.previousVersion) { + const noPreviousVer = testCase.previousVersion === "none"; (profInfo as any).mExtendersJson = { profileTypes: { "some-type": { from: ["Zowe Client App"], - version: testCase.previousVersion === "none" ? undefined : testCase.previousVersion + version: noPreviousVer ? undefined : testCase.previousVersion, + latestFrom: noPreviousVer ? undefined : "Zowe Client App" } } }; From 743eab1c8b6525298a1b6de6755b6dce49bec465 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Mon, 8 Jan 2024 15:51:09 -0500 Subject: [PATCH 25/92] fix: update buildDefaultProfile, make extender.json methods static Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ConfigBuilder.ts | 2 +- .../imperative/src/config/src/ProfileInfo.ts | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/imperative/src/config/src/ConfigBuilder.ts b/packages/imperative/src/config/src/ConfigBuilder.ts index 8fbb4fafb8..ea94052006 100644 --- a/packages/imperative/src/config/src/ConfigBuilder.ts +++ b/packages/imperative/src/config/src/ConfigBuilder.ts @@ -31,7 +31,7 @@ export class ConfigBuilder { const config: IConfig = Config.empty(); for (const profile of impConfig.profiles) { - const defaultProfile = this.buildDefaultProfile(profile, opts); + const defaultProfile = ConfigBuilder.buildDefaultProfile(profile, opts); // Add the profile to config and set it as default lodash.set(config, `profiles.${profile.type}`, defaultProfile); diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 9666e4ab9b..bf2849a668 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -985,7 +985,7 @@ export class ProfileInfo { } } } else { - this.readExtendersJsonFromDisk(); + this.mExtendersJson = ProfileInfo.readExtendersJsonFromDisk(); } this.loadAllSchemas(); @@ -1237,27 +1237,29 @@ export class ProfileInfo { /** * Reads the `extenders.json` file from the CLI home directory. * Called once in `readProfilesFromDisk` and cached to minimize I/O operations. + * @internal */ - private readExtendersJsonFromDisk(): void { + public static readExtendersJsonFromDisk(): IExtendersJsonOpts { const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); if (!fs.existsSync(extenderJsonPath)) { jsonfile.writeFileSync(extenderJsonPath, { profileTypes: {} }, { spaces: 4 }); - this.mExtendersJson = { profileTypes: {} }; + return { profileTypes: {} }; } else { - this.mExtendersJson = jsonfile.readFileSync(extenderJsonPath); + return jsonfile.readFileSync(extenderJsonPath); } } /** * Attempts to write to the `extenders.json` file in the CLI home directory. * @returns `true` if written successfully; `false` otherwise + * @internal */ - private writeExtendersJson(): boolean { + public static writeExtendersJson(obj: IExtendersJsonOpts): boolean { try { const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - jsonfile.writeFileSync(extenderJsonPath, this.mExtendersJson, { spaces: 4 }); + jsonfile.writeFileSync(extenderJsonPath, obj, { spaces: 4 }); } catch (err) { return false; } @@ -1413,7 +1415,7 @@ export class ProfileInfo { // Update contents of extenders.json if it has changed if (!lodash.isEqual(oldExtendersJson, this.mExtendersJson)) { - if (!this.writeExtendersJson()) { + if (!ProfileInfo.writeExtendersJson(this.mExtendersJson)) { return { success: true, // Even if we failed to update extenders.json, it was technically added to the schema cache. From cc13857d16d431bd32f81941843c91f8c8f697b1 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Mon, 8 Jan 2024 15:51:41 -0500 Subject: [PATCH 26/92] fix(tests): update tests for static methods Signed-off-by: Trae Yelovich --- .../__tests__/ProfileInfo.TeamConfig.unit.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 511cdee506..6c85679a54 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1333,7 +1333,7 @@ describe("TeamConfig ProfileInfo tests", () => { const profInfo = createNewProfInfo(teamProjDir); (profInfo as any).mExtendersJson = { profileTypes: {} }; jest.spyOn(fs, "existsSync").mockReturnValueOnce(false); - (profInfo as any).readExtendersJsonFromDisk(); + ProfileInfo.readExtendersJsonFromDisk(); expect(writeFileSyncMock).toHaveBeenCalled(); }); @@ -1346,7 +1346,7 @@ describe("TeamConfig ProfileInfo tests", () => { } }); const profInfo = createNewProfInfo(teamProjDir); jest.spyOn(fs, "existsSync").mockReturnValueOnce(true); - (profInfo as any).readExtendersJsonFromDisk(); + (profInfo as any).mExtendersJson = ProfileInfo.readExtendersJsonFromDisk(); expect(readFileSyncMock).toHaveBeenCalled(); expect((profInfo as any).mExtendersJson).toEqual({ profileTypes: { @@ -1364,7 +1364,7 @@ describe("TeamConfig ProfileInfo tests", () => { const profInfo = createNewProfInfo(teamProjDir); (profInfo as any).mExtendersJson = { profileTypes: {} }; await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - expect((profInfo as any).writeExtendersJson()).toBe(true); + expect(ProfileInfo.writeExtendersJson((profInfo as any).mExtendersJson)).toBe(true); expect(writeFileSyncMock).toHaveBeenCalled(); }); @@ -1374,7 +1374,7 @@ describe("TeamConfig ProfileInfo tests", () => { (profInfo as any).mExtendersJson = { profileTypes: {} }; await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); writeFileSyncMock.mockImplementation(() => { throw new Error(); }); - expect((profInfo as any).writeExtendersJson()).toBe(false); + expect(ProfileInfo.writeExtendersJson((profInfo as any).mExtendersJson)).toBe(false); expect(writeFileSyncMock).toHaveBeenCalled(); }); }); @@ -1495,7 +1495,7 @@ describe("TeamConfig ProfileInfo tests", () => { }; } const updateSchemaAtLayerMock = jest.spyOn((ProfileInfo as any).prototype, "updateSchemaAtLayer").mockImplementation(); - const writeExtendersJsonMock = jest.spyOn((ProfileInfo as any).prototype, "writeExtendersJson").mockImplementation(); + const writeExtendersJsonMock = jest.spyOn(ProfileInfo, "writeExtendersJson").mockImplementation(); const res = profInfo.addProfileTypeToSchema("some-type", { ...testCase, sourceApp: "Zowe Client App" }); if (expected.res.success) { expect(updateSchemaAtLayerMock).toHaveBeenCalled(); From 85d418aff9e949acefb3a0ebc21310f7afcea6c9 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Mon, 8 Jan 2024 16:02:50 -0500 Subject: [PATCH 27/92] chore: adjust changelog after Imperative patch Signed-off-by: Trae Yelovich --- packages/imperative/CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index cbb477747e..330fdd7d8c 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,10 +2,13 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- Enhancement: Added multiple APIs to the `ProfileInfo` class to help manage schemas between client applications. [#2012](https://github.com/zowe/zowe-cli/issues/2012) + ## `5.20.1` - BugFix: Fixed error message shown for null option definition to include details about which command caused the error. [#2002](https://github.com/zowe/zowe-cli/issues/2002) -- Enhancement: Added multiple APIs to the `ProfileInfo` class to help manage schemas between client applications. ## `5.19.0` From ea0c875d42b5cb600b81366bb7e6a29f3fde16eb Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Mon, 8 Jan 2024 16:27:03 -0500 Subject: [PATCH 28/92] fix: add stripInternal back to tsconfig Signed-off-by: Trae Yelovich --- tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 454062485f..6ed3820b91 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,8 @@ "removeComments": false, "pretty": true, "sourceMap": true, - "newLine": "lf" + "newLine": "lf", + "stripInternal": true }, "exclude": [ "lib", From 06834dbdfc3e19edfb504e274f7a8fe9f8dd4d37 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 9 Jan 2024 14:10:26 -0500 Subject: [PATCH 29/92] fix: track latestFrom for new types in extenders.json Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index bf2849a668..23c1e42ca3 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1408,7 +1408,8 @@ export class ProfileInfo { // Newly-contributed profile type; track in extenders.json this.mExtendersJson.profileTypes[profileType] = { version: typeInfo.version, - from: [typeInfo.sourceApp] + from: [typeInfo.sourceApp], + latestFrom: typeInfo.version ? typeInfo.sourceApp : undefined }; this.updateSchemaAtLayer(profileType, typeInfo.schema); } From 6c18ab46e10c30450bcc4afe4246e232d3d15dc9 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 10 Jan 2024 13:26:45 -0500 Subject: [PATCH 30/92] feat(plugins): make install command additive, remove type during uninstall Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ConfigSchema.ts | 3 +- .../__tests__/plugins/__resources__/schema.ts | 19 +++ .../npm-interface/install.unit.test.ts | 120 +++++++++++++++++- .../npm-interface/uninstall.unit.test.ts | 76 ++++++++++- .../utilities/npm-interface/install.ts | 84 +++++++++++- .../utilities/npm-interface/uninstall.ts | 69 ++++++++++ 6 files changed, 359 insertions(+), 12 deletions(-) create mode 100644 packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts diff --git a/packages/imperative/src/config/src/ConfigSchema.ts b/packages/imperative/src/config/src/ConfigSchema.ts index 6a04334475..17a8cd77cb 100644 --- a/packages/imperative/src/config/src/ConfigSchema.ts +++ b/packages/imperative/src/config/src/ConfigSchema.ts @@ -104,8 +104,9 @@ export class ConfigSchema { * Transform a JSON schema to an Imperative profile schema. * @param schema The JSON schema for profile properties * @returns Imperative profile schema + * @internal */ - private static parseSchema(schema: any): IProfileSchema { + public static parseSchema(schema: any): IProfileSchema { const properties: { [key: string]: IProfileProperty } = {}; for (const [k, v] of Object.entries((schema.properties.properties || {}) as { [key: string]: any })) { properties[k] = { type: v.type }; diff --git a/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts b/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts new file mode 100644 index 0000000000..db39b96ce1 --- /dev/null +++ b/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts @@ -0,0 +1,19 @@ +import { IProfileTypeConfiguration } from "../../../.."; + +const mockSchema: IProfileTypeConfiguration = { + type: "test-type", + schema: { + title: "test-type", + description: "A test type profile", + type: "object", + required: [], + properties: { + host: { + type: "string", + secure: false + } + } + } +}; + +export default mockSchema; \ No newline at end of file diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts index 8c7ff5b02f..e738341c7b 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts @@ -58,7 +58,9 @@ import { ConfigurationLoader } from "../../../../src/ConfigurationLoader"; import { UpdateImpConfig } from "../../../../src/UpdateImpConfig"; import * as fs from "fs"; import * as path from "path"; - +import { gt as versionGreaterThan } from "semver"; +import { ProfileInfo } from "../../../../../config"; +import mockSchema from "../../__resources__/schema"; function setResolve(toResolve: string, resolveTo?: string) { expectedVal = toResolve; @@ -78,7 +80,12 @@ describe("PMF: Install Interface", () => { PMF_requirePluginModuleCallback: pmfI.requirePluginModuleCallback as Mock, ConfigurationLoader_load: ConfigurationLoader.load as Mock, UpdateImpConfig_addProfiles: UpdateImpConfig.addProfiles as Mock, - path: path as unknown as Mock + path: path as unknown as Mock, + ConfigSchema_loadSchema: jest.spyOn(ConfigSchema, "loadSchema"), + ProfileInfo: { + readExtendersJsonFromDisk: jest.spyOn(ProfileInfo, "readExtendersJsonFromDisk"), + writeExtendersJson: jest.spyOn(ProfileInfo, "writeExtendersJson") + } }; const packageName = "a"; @@ -101,7 +108,16 @@ describe("PMF: Install Interface", () => { mocks.sync.mockReturnValue("fake_find-up_sync_result" as any); jest.spyOn(path, "dirname").mockReturnValue("fake-dirname"); jest.spyOn(path, "join").mockReturnValue("/fake/join/path"); - mocks.ConfigurationLoader_load.mockReturnValue({ profiles: ["fake"] } as any); + mocks.ProfileInfo.readExtendersJsonFromDisk.mockReturnValue({ + profileTypes: { + "zosmf": { + from: ["Zowe CLI"] + } + } + }); + mocks.ProfileInfo.writeExtendersJson.mockImplementation(); + mocks.ConfigSchema_loadSchema.mockReturnValue([mockSchema]); + mocks.ConfigurationLoader_load.mockReturnValue({ profiles: [mockSchema] } as any); }); afterAll(() => { @@ -130,7 +146,7 @@ describe("PMF: Install Interface", () => { if (shouldUpdate) { expect(mocks.UpdateImpConfig_addProfiles).toHaveBeenCalledTimes(1); expect(mocks.ConfigSchema_updateSchema).toHaveBeenCalledTimes(1); - expect(mocks.ConfigSchema_updateSchema).toHaveBeenCalledWith({ layer: "global" }); + expect(mocks.ConfigSchema_updateSchema).toHaveBeenCalledWith(expect.objectContaining({ layer: "global" })); } else { expect(mocks.UpdateImpConfig_addProfiles).not.toHaveBeenCalled(); expect(mocks.ConfigSchema_updateSchema).not.toHaveBeenCalled(); @@ -165,7 +181,7 @@ describe("PMF: Install Interface", () => { describe("Basic install", () => { beforeEach(() => { mocks.getPackageInfo.mockResolvedValue({ name: packageName, version: packageVersion } as never); - jest.spyOn(fs, "existsSync").mockReturnValueOnce(true); + jest.spyOn(fs, "existsSync").mockReturnValue(true); jest.spyOn(path, "normalize").mockReturnValue("testing"); jest.spyOn(fs, "lstatSync").mockReturnValue({ isSymbolicLink: jest.fn().mockReturnValue(true) @@ -326,7 +342,7 @@ describe("PMF: Install Interface", () => { }); }); - it("should merge contents of previous json file", async () => { + it("should merge contents of previous plugins.json file", async () => { // value for our previous plugins.json const oneOldPlugin: IPluginJson = { plugin1: { @@ -355,6 +371,98 @@ describe("PMF: Install Interface", () => { }); }); + describe("Updating the global schema", () => { + const expectTestSchemaMgmt = async (opts: { + schemaExists: boolean; + newProfileType: boolean; + version?: string; + lastVersion?: string; + }) => { + const oneOldPlugin: IPluginJson = { + plugin1: { + package: "plugin1", + registry: packageRegistry, + version: "1.2.3" + } + }; + if (opts.newProfileType) { + const schema = { ...mockSchema, schemaVersion: opts.version }; + mocks.ConfigurationLoader_load.mockReturnValue({ + profiles: [ + schema + ] + } as any); + } + + mocks.getPackageInfo.mockResolvedValue({ name: packageName, version: packageVersion } as never); + jest.spyOn(fs, "existsSync").mockReturnValueOnce(true).mockReturnValueOnce(opts.schemaExists); + jest.spyOn(path, "normalize").mockReturnValue("testing"); + jest.spyOn(fs, "lstatSync").mockReturnValue({ + isSymbolicLink: jest.fn().mockReturnValue(true) + } as any); + mocks.readFileSync.mockReturnValue(oneOldPlugin as any); + + if (opts.lastVersion) { + mocks.ProfileInfo.readExtendersJsonFromDisk.mockReturnValueOnce({ + profileTypes: { + "test-type": { + from: [oneOldPlugin.plugin1.package], + version: opts.lastVersion, + latestFrom: oneOldPlugin.plugin1.package + } + } + }); + } + + setResolve(packageName); + await install(packageName, packageRegistry); + if (opts.schemaExists) { + expect(mocks.ConfigSchema_updateSchema).toHaveBeenCalled(); + } else { + expect(mocks.ConfigSchema_updateSchema).not.toHaveBeenCalled(); + } + + if (opts.version && opts.lastVersion) { + if (versionGreaterThan(opts.version, opts.lastVersion)) { + expect(mocks.ProfileInfo.writeExtendersJson).toHaveBeenCalled(); + } else { + expect(mocks.ProfileInfo.writeExtendersJson).not.toHaveBeenCalled(); + } + } + }; + it("should update the schema to contain the new profile type", async () => { + expectTestSchemaMgmt({ + schemaExists: true, + newProfileType: true + }); + }); + + it("should not update the schema if it doesn't exist", async () => { + expectTestSchemaMgmt({ + schemaExists: false, + newProfileType: true + }); + }); + + it("updates the schema with a newer schema version than the one present", () => { + expectTestSchemaMgmt({ + schemaExists: true, + newProfileType: true, + version: "2.0.0", + lastVersion: "1.0.0" + }); + }); + + it("doesn't update the schema with an older schema version than the one present", () => { + expectTestSchemaMgmt({ + schemaExists: true, + newProfileType: true, + version: "1.0.0", + lastVersion: "2.0.0" + }); + }); + }); + it("should throw errors", async () => { // Create a placeholder error object that should be set after the call to install let expectedError: ImperativeError = new ImperativeError({ diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts index 28204bd208..e1459d02cd 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts @@ -20,6 +20,7 @@ jest.mock("../../../../../cmd/src/response/CommandResponse"); jest.mock("../../../../../cmd/src/response/HandlerResponse"); import * as fs from "fs"; +import * as jsonfile from "jsonfile"; import { Console } from "../../../../../console"; import { sync } from "cross-spawn"; import { ImperativeError } from "../../../../../error"; @@ -29,7 +30,9 @@ import { PMFConstants } from "../../../../src/plugins/utilities/PMFConstants"; import { readFileSync, writeFileSync } from "jsonfile"; import { findNpmOnPath } from "../../../../src/plugins/utilities/NpmFunctions"; import { uninstall } from "../../../../src/plugins/utilities/npm-interface"; - +import { ConfigSchema, ProfileInfo } from "../../../../../config"; +import mockSchema from "../../__resources__/schema"; +import { ExecUtils } from "../../../../../utilities"; describe("PMF: Uninstall Interface", () => { // Objects created so types are correct. @@ -202,4 +205,75 @@ describe("PMF: Uninstall Interface", () => { expect(caughtError.message).toContain("Failed to uninstall plugin, install folder still exists"); }); }); + + describe("Schema management", () => { + const getBlockMocks = () => { + jest.spyOn(fs, "existsSync").mockRestore(); + return { + ConfigSchema: { + buildSchema: jest.spyOn(ConfigSchema, "buildSchema").mockImplementation(), + loadSchema: jest.spyOn(ConfigSchema, "loadSchema").mockReturnValueOnce([mockSchema]), + updateSchema: jest.spyOn(ConfigSchema, "updateSchema").mockImplementation() + }, + fs: { + existsSync: jest.spyOn(fs, "existsSync").mockReturnValueOnce(false) + }, + jsonfile: { + // avoid throwing error during plugin uninstall by marking plug-in folder as non-existent + writeFileSync: jest.spyOn(jsonfile, "writeFileSync").mockImplementation() + }, + ExecUtils: { + spawnAndGetOutput: jest.spyOn(ExecUtils, "spawnAndGetOutput").mockImplementation() + } + }; + }; + + const expectTestSchemaMgmt = (opts: { schemaUpdated?: boolean }) => { + const pluginJsonFile: IPluginJson = { + a: { + package: "a", + registry: packageRegistry, + version: "3.2.1" + }, + plugin2: { + package: "plugin1", + registry: packageRegistry, + version: "1.2.3" + } + }; + + mocks.readFileSync.mockReturnValue(pluginJsonFile as any); + const blockMocks = getBlockMocks(); + if (opts.schemaUpdated) { + blockMocks.fs.existsSync.mockReturnValueOnce(true); + jest.spyOn(ProfileInfo, "readExtendersJsonFromDisk").mockReturnValue({ + profileTypes: { + "test-type": { + from: ["a"], + } + } + }); + } + uninstall(packageName); + + // Check that schema was updated, if it was supposed to update + if (opts.schemaUpdated) { + expect(blockMocks.ConfigSchema.buildSchema).toHaveBeenCalled(); + expect(blockMocks.ConfigSchema.updateSchema).toHaveBeenCalled(); + expect(blockMocks.jsonfile.writeFileSync).toHaveBeenCalled(); + } else { + expect(blockMocks.ConfigSchema.buildSchema).not.toHaveBeenCalled(); + expect(blockMocks.ConfigSchema.updateSchema).not.toHaveBeenCalled(); + expect(blockMocks.jsonfile.writeFileSync).not.toHaveBeenCalledTimes(2); + } + }; + + it("Removes a type from the schema if the plug-in is the last source", () => { + expectTestSchemaMgmt({ schemaUpdated: true }); + }); + + it("Does not modify the schema if another source contributes to that profile type", () => { + expectTestSchemaMgmt({ schemaUpdated: false }); + }); + }); }); diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index f76354c168..d9867d584a 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -12,6 +12,7 @@ import { PMFConstants } from "../PMFConstants"; import * as path from "path"; import * as fs from "fs"; +import * as jsonfile from "jsonfile"; import { readFileSync, writeFileSync } from "jsonfile"; import { IPluginJson } from "../../doc/IPluginJson"; import { Logger } from "../../../../../logger"; @@ -24,6 +25,10 @@ import { PluginManagementFacility } from "../../PluginManagementFacility"; import { ConfigurationLoader } from "../../../ConfigurationLoader"; import { UpdateImpConfig } from "../../../UpdateImpConfig"; import { CredentialManagerOverride, ICredentialManagerNameMap } from "../../../../../security"; +import { fileURLToPath, pathToFileURL } from "url"; +import { IProfileTypeConfiguration } from "../../../../../profiles"; +import * as semver from "semver"; +import { ProfileInfo } from "../../../../../config"; /** * Common function that abstracts the install process. This function should be called for each @@ -134,14 +139,85 @@ export async function install(packageLocation: string, registry: string, install const pluginImpConfig = ConfigurationLoader.load(null, packageInfo, requirerFunction); iConsole.debug(`Checking for global team configuration files to update.`); - if (PMFConstants.instance.PLUGIN_USING_CONFIG && - PMFConstants.instance.PLUGIN_CONFIG.layers.filter((layer) => layer.global && layer.exists).length > 0) + if (PMFConstants.instance.PLUGIN_USING_CONFIG) { // Update the Imperative Configuration to add the profiles introduced by the recently installed plugin // This might be needed outside of PLUGIN_USING_CONFIG scenarios, but we haven't had issues with other APIs before - if (Array.isArray(pluginImpConfig.profiles)) { + const globalLayer = PMFConstants.instance.PLUGIN_CONFIG.layers.find((layer) => layer.global && layer.exists); + if (globalLayer && Array.isArray(pluginImpConfig.profiles)) { UpdateImpConfig.addProfiles(pluginImpConfig.profiles); - ConfigSchema.updateSchema({ layer: "global" }); + const schemaUri = new URL(globalLayer.properties.$schema, pathToFileURL(globalLayer.path)); + const schemaPath = fileURLToPath(schemaUri); + if (fs.existsSync(schemaPath)) { + let loadedSchema: IProfileTypeConfiguration[]; + try { + // load schema from disk to prevent removal of profile types from other applications + loadedSchema = ConfigSchema.loadSchema(jsonfile.readFileSync(schemaPath)); + } catch (err) { + iConsole.error("Error when adding new profile type for plugin %s: failed to parse schema", newPlugin.package); + } + + // Only update global schema if we were able to load it from disk + if (loadedSchema != null) { + const existingTypes = loadedSchema.map((obj) => obj.type); + const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); + + // Helper function to update extenders.json object during plugin install. + // Returns true if the object was updated, and false otherwise + const updateExtendersJson = (profile: IProfileTypeConfiguration): boolean => { + if (!(profile.type in extendersJson.profileTypes)) { + // If the type doesn't exist, add it to extenders.json and return + extendersJson.profileTypes[profile.type] = { + from: [packageInfo.name], + version: profile.schemaVersion + }; + return true; + } + + // Otherwise, only update extenders.json if the schema version is newer + const existingTypeInfo = extendersJson.profileTypes[profile.type]; + if (semver.valid(existingTypeInfo.version)) { + if (profile.schemaVersion && semver.lt(profile.schemaVersion, existingTypeInfo.version)) { + return false; + } + } + + extendersJson.profileTypes[profile.type] = { + from: [packageInfo.name], + version: profile.schemaVersion + }; + return true; + }; + + // Determine new profile types to add to schema + let shouldUpdate = false; + for (const profile of pluginImpConfig.profiles) { + if (!(profile.type in existingTypes)) { + loadedSchema.push(profile); + } else { + const existingType = loadedSchema.find((obj) => obj.type === profile.type); + if (semver.valid(existingType.schemaVersion)) { + if (semver.gt(profile.schemaVersion, existingType.schemaVersion)) { + existingType.schema = profile.schema; + existingType.schemaVersion = profile.schemaVersion; + } + } else { + existingType.schema = profile.schema; + existingType.schemaVersion = profile.schemaVersion; + } + } + shouldUpdate = shouldUpdate || updateExtendersJson(profile); + } + + if (shouldUpdate) { + // Update extenders.json (if necessary) after installing the plugin + ProfileInfo.writeExtendersJson(extendersJson); + } + const schema = ConfigSchema.buildSchema(loadedSchema); + ConfigSchema.updateSchema({ layer: "global", schema }); + jsonfile.writeFileSync(schemaPath, schema, { spaces: 4 }); + } + } } } diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index 4239da8dda..4b22b478f0 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -10,6 +10,7 @@ */ import * as fs from "fs"; +import * as jsonfile from "jsonfile"; import * as path from "path"; import { PMFConstants } from "../PMFConstants"; import { readFileSync, writeFileSync } from "jsonfile"; @@ -19,6 +20,9 @@ import { ImperativeError } from "../../../../../error"; import { ExecUtils, TextUtils } from "../../../../../utilities"; import { StdioOptions } from "child_process"; import { findNpmOnPath } from "../NpmFunctions"; +import { ConfigSchema, ProfileInfo } from "../../../../../config"; +import { fileURLToPath, pathToFileURL } from "url"; +import { IProfileTypeConfiguration } from "../../../../../profiles"; const npmCmd = findNpmOnPath(); /** @@ -84,6 +88,71 @@ export function uninstall(packageName: string): void { throw new Error("Failed to uninstall plugin, install folder still exists:\n " + installFolder); } + if (PMFConstants.instance.PLUGIN_USING_CONFIG) { + // Update the Imperative Configuration to add the profiles introduced by the recently installed plugin + // This might be needed outside of PLUGIN_USING_CONFIG scenarios, but we haven't had issues with other APIs before + const globalLayer = PMFConstants.instance.PLUGIN_CONFIG.layers.find((layer) => layer.global && layer.exists); + if (globalLayer) { + const schemaUri = new URL(globalLayer.properties.$schema, pathToFileURL(globalLayer.path)); + const schemaPath = fileURLToPath(schemaUri); + if (fs.existsSync(schemaPath)) { + const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); + const pluginTypes = Object.keys(extendersJson.profileTypes) + .filter((type) => type in extendersJson.profileTypes && + extendersJson.profileTypes[type].from.includes(npmPackage)); + const typesToRemove: string[] = []; + if (pluginTypes.length > 0) { + // Only remove a profile type contributed by this plugin if its the single source for that type. + for (const profileType of pluginTypes) { + const typeInfo = extendersJson.profileTypes[profileType]; + if (typeInfo.from.length > 1) { + // If there are other sources, remove the version for that type if this plugin provides the + // latest version. This will allow the next source to contribute a different schema version. + if (typeInfo.latestFrom === npmPackage) { + extendersJson.profileTypes[profileType] = { + ...typeInfo, + from: typeInfo.from.filter((v) => v !== npmPackage), + latestFrom: undefined, + version: undefined + }; + } else { + extendersJson.profileTypes[profileType] = { + ...typeInfo, + from: typeInfo.from.filter((v) => v !== npmPackage) + }; + } + } else { + extendersJson.profileTypes[profileType] = { + ...typeInfo, + from: typeInfo.from.filter((v) => v !== npmPackage) + }; + typesToRemove.push(profileType); + } + } + ProfileInfo.writeExtendersJson(extendersJson); + } + + let loadedSchema: IProfileTypeConfiguration[]; + try { + // load schema from disk to prevent removal of profile types from other applications + loadedSchema = ConfigSchema.loadSchema(jsonfile.readFileSync(schemaPath)); + } catch (err) { + iConsole.error("Error when removing profile type for plugin %s: failed to parse schema", npmPackage); + } + + // Only update global schema if we were able to load it from disk + if (loadedSchema != null) { + if (typesToRemove.length > 0) { + loadedSchema = loadedSchema.filter((typeCfg) => !typesToRemove.includes(typeCfg.type)); + const schema = ConfigSchema.buildSchema(loadedSchema); + ConfigSchema.updateSchema({ layer: "global", schema }); + jsonfile.writeFileSync(schemaPath, schema, { spaces: 4 }); + } + } + } + } + } + iConsole.info("Uninstall complete"); writeFileSync(PMFConstants.instance.PLUGIN_JSON, updatedInstalledPlugins, { From 84f71ad9d2587f7ab8d45d513845d92d8ae6429b Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 10 Jan 2024 15:18:32 -0500 Subject: [PATCH 31/92] fix: add missing license, resolve SonarCloud issue Signed-off-by: Trae Yelovich --- .../__tests__/plugins/__resources__/schema.ts | 11 +++++++++++ .../src/plugins/utilities/npm-interface/install.ts | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts b/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts index db39b96ce1..1495ada4c0 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts @@ -1,3 +1,14 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + import { IProfileTypeConfiguration } from "../../../.."; const mockSchema: IProfileTypeConfiguration = { diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index d9867d584a..4a99e71d01 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -192,7 +192,7 @@ export async function install(packageLocation: string, registry: string, install // Determine new profile types to add to schema let shouldUpdate = false; for (const profile of pluginImpConfig.profiles) { - if (!(profile.type in existingTypes)) { + if (!existingTypes.includes(profile.type)) { loadedSchema.push(profile); } else { const existingType = loadedSchema.find((obj) => obj.type === profile.type); From 13c1e94132a75fd7e50e0be322891d251d59b62b Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 10 Jan 2024 15:58:13 -0500 Subject: [PATCH 32/92] fix: avoid OR short-circuit when updating schema Signed-off-by: Trae Yelovich --- .../imperative/src/plugins/utilities/npm-interface/install.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index 4a99e71d01..fa6ab98440 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -206,7 +206,7 @@ export async function install(packageLocation: string, registry: string, install existingType.schemaVersion = profile.schemaVersion; } } - shouldUpdate = shouldUpdate || updateExtendersJson(profile); + shouldUpdate = updateExtendersJson(profile) || shouldUpdate; } if (shouldUpdate) { From b412e4dd2fb6d54a8856f90814235c0114470279 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 10 Jan 2024 15:59:38 -0500 Subject: [PATCH 33/92] chore: remove duplicated import Signed-off-by: Trae Yelovich --- .../src/plugins/utilities/npm-interface/install.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index fa6ab98440..9114c79bfd 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -12,7 +12,6 @@ import { PMFConstants } from "../PMFConstants"; import * as path from "path"; import * as fs from "fs"; -import * as jsonfile from "jsonfile"; import { readFileSync, writeFileSync } from "jsonfile"; import { IPluginJson } from "../../doc/IPluginJson"; import { Logger } from "../../../../../logger"; @@ -152,7 +151,7 @@ export async function install(packageLocation: string, registry: string, install let loadedSchema: IProfileTypeConfiguration[]; try { // load schema from disk to prevent removal of profile types from other applications - loadedSchema = ConfigSchema.loadSchema(jsonfile.readFileSync(schemaPath)); + loadedSchema = ConfigSchema.loadSchema(readFileSync(schemaPath)); } catch (err) { iConsole.error("Error when adding new profile type for plugin %s: failed to parse schema", newPlugin.package); } @@ -215,7 +214,7 @@ export async function install(packageLocation: string, registry: string, install } const schema = ConfigSchema.buildSchema(loadedSchema); ConfigSchema.updateSchema({ layer: "global", schema }); - jsonfile.writeFileSync(schemaPath, schema, { spaces: 4 }); + writeFileSync(schemaPath, schema, { spaces: 4 }); } } } From 98ab4acdee94276cca5105e3bf80ad6b0b090a30 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 10 Jan 2024 16:30:08 -0500 Subject: [PATCH 34/92] fix: remove redundant write calls for schema Signed-off-by: Trae Yelovich --- .../imperative/src/plugins/utilities/npm-interface/install.ts | 1 - .../src/plugins/utilities/npm-interface/uninstall.ts | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index 9114c79bfd..f19130f058 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -214,7 +214,6 @@ export async function install(packageLocation: string, registry: string, install } const schema = ConfigSchema.buildSchema(loadedSchema); ConfigSchema.updateSchema({ layer: "global", schema }); - writeFileSync(schemaPath, schema, { spaces: 4 }); } } } diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index 4b22b478f0..bf7e2ded2e 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -10,7 +10,6 @@ */ import * as fs from "fs"; -import * as jsonfile from "jsonfile"; import * as path from "path"; import { PMFConstants } from "../PMFConstants"; import { readFileSync, writeFileSync } from "jsonfile"; @@ -135,7 +134,7 @@ export function uninstall(packageName: string): void { let loadedSchema: IProfileTypeConfiguration[]; try { // load schema from disk to prevent removal of profile types from other applications - loadedSchema = ConfigSchema.loadSchema(jsonfile.readFileSync(schemaPath)); + loadedSchema = ConfigSchema.loadSchema(readFileSync(schemaPath)); } catch (err) { iConsole.error("Error when removing profile type for plugin %s: failed to parse schema", npmPackage); } @@ -146,7 +145,6 @@ export function uninstall(packageName: string): void { loadedSchema = loadedSchema.filter((typeCfg) => !typesToRemove.includes(typeCfg.type)); const schema = ConfigSchema.buildSchema(loadedSchema); ConfigSchema.updateSchema({ layer: "global", schema }); - jsonfile.writeFileSync(schemaPath, schema, { spaces: 4 }); } } } From 6a6089e7b82178d30d6ef00c7786bd6e2eb8c0d2 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 10 Jan 2024 17:43:43 -0500 Subject: [PATCH 35/92] fix(ProfileInfo): adhere to current behavior for Web URLs Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 23c1e42ca3..d5b790adab 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1324,6 +1324,9 @@ export class ProfileInfo { this.mProfileSchemaCache.set(cacheKey, schema); const schemaUri = new url.URL(layerToUpdate.properties.$schema, url.pathToFileURL(layerPath)); + if (schemaUri.protocol !== "file:") { + return; + } const schemaPath = url.fileURLToPath(schemaUri); // if profile type schema has changed or if it doesn't exist on-disk, rebuild schema and write to disk @@ -1489,6 +1492,7 @@ export class ProfileInfo { for (const layer of this.getTeamConfig().mLayers) { if (layer.properties.$schema == null) continue; const schemaUri = new url.URL(layer.properties.$schema, url.pathToFileURL(layer.path)); + if (schemaUri.protocol !== "file:") continue; const schemaPath = url.fileURLToPath(schemaUri); if (!fs.existsSync(schemaPath)) continue; From 3f20c4855ab91cea8ccaa1840fb9dc6d2600703a Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 10 Jan 2024 17:56:47 -0500 Subject: [PATCH 36/92] fix(plugins): Do not update schema if using web URL Signed-off-by: Trae Yelovich --- .../imperative/src/plugins/utilities/npm-interface/install.ts | 4 ++-- .../src/plugins/utilities/npm-interface/uninstall.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index f19130f058..97da69b93b 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -146,8 +146,8 @@ export async function install(packageLocation: string, registry: string, install if (globalLayer && Array.isArray(pluginImpConfig.profiles)) { UpdateImpConfig.addProfiles(pluginImpConfig.profiles); const schemaUri = new URL(globalLayer.properties.$schema, pathToFileURL(globalLayer.path)); - const schemaPath = fileURLToPath(schemaUri); - if (fs.existsSync(schemaPath)) { + const schemaPath = schemaUri.protocol === "file:" ? fileURLToPath(schemaUri) : undefined; + if (schemaPath && fs.existsSync(schemaPath)) { let loadedSchema: IProfileTypeConfiguration[]; try { // load schema from disk to prevent removal of profile types from other applications diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index bf7e2ded2e..49e24c179a 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -93,8 +93,8 @@ export function uninstall(packageName: string): void { const globalLayer = PMFConstants.instance.PLUGIN_CONFIG.layers.find((layer) => layer.global && layer.exists); if (globalLayer) { const schemaUri = new URL(globalLayer.properties.$schema, pathToFileURL(globalLayer.path)); - const schemaPath = fileURLToPath(schemaUri); - if (fs.existsSync(schemaPath)) { + const schemaPath = schemaUri.protocol === "file:" ? fileURLToPath(schemaUri) : undefined; + if (schemaPath && fs.existsSync(schemaPath)) { const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); const pluginTypes = Object.keys(extendersJson.profileTypes) .filter((type) => type in extendersJson.profileTypes && From be3717973f31a7da6ecb268eb0d0e495d51ddb36 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Thu, 11 Jan 2024 10:30:42 -0500 Subject: [PATCH 37/92] feat: move extenders.json logic into separate fn, add unit tests Signed-off-by: Trae Yelovich --- .../npm-interface/uninstall.unit.test.ts | 104 ++++++++++++++++++ .../utilities/npm-interface/uninstall.ts | 93 ++++++++-------- 2 files changed, 153 insertions(+), 44 deletions(-) diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts index e1459d02cd..a94c0bb420 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts @@ -33,6 +33,8 @@ import { uninstall } from "../../../../src/plugins/utilities/npm-interface"; import { ConfigSchema, ProfileInfo } from "../../../../../config"; import mockSchema from "../../__resources__/schema"; import { ExecUtils } from "../../../../../utilities"; +import { IExtendersJsonOpts } from "../../../../../config/src/doc/IExtenderOpts"; +import { updateAndGetRemovedTypes } from "../../../../src/plugins/utilities/npm-interface/uninstall"; describe("PMF: Uninstall Interface", () => { // Objects created so types are correct. @@ -276,4 +278,106 @@ describe("PMF: Uninstall Interface", () => { expectTestSchemaMgmt({ schemaUpdated: false }); }); }); + + describe("updateAndGetRemovedTypes", () => { + const getBlockMocks = () => { + const profileInfo = { + readExtendersJsonFromDisk: jest.spyOn(ProfileInfo, "readExtendersJsonFromDisk"), + writeExtendersJson: jest.spyOn(ProfileInfo, "writeExtendersJson").mockImplementation(), + }; + + return { + profileInfo, + }; + }; + + const expectUpdateExtendersJson = (shouldUpdate: { + extJson: boolean; + schema?: boolean; + }, extendersJson: IExtendersJsonOpts) => { + const blockMocks = getBlockMocks(); + blockMocks.profileInfo.readExtendersJsonFromDisk.mockReturnValue(extendersJson); + + const hasMultipleSources = extendersJson.profileTypes["some-type"].from.length > 1; + const wasLatestSource = extendersJson.profileTypes["some-type"].latestFrom === "aPluginPackage"; + + const typesToRemove = updateAndGetRemovedTypes("aPluginPackage"); + if (shouldUpdate.extJson) { + expect(blockMocks.profileInfo.writeExtendersJson).toHaveBeenCalled(); + } else { + expect(blockMocks.profileInfo.writeExtendersJson).not.toHaveBeenCalled(); + return; + } + + const newExtendersObj = blockMocks.profileInfo.writeExtendersJson.mock.calls[0][0]; + + if (hasMultipleSources) { + expect(blockMocks.profileInfo.writeExtendersJson).not.toHaveBeenCalledWith( + expect.objectContaining({ + profileTypes: { + "some-type": { + latestFrom: undefined + } + } + }) + ); + + const newFrom = newExtendersObj.profileTypes["some-type"].from; + expect(newFrom).not.toContain("aPluginPackage"); + } else { + expect("some-type" in newExtendersObj.profileTypes).toBe(false); + } + + if (wasLatestSource && hasMultipleSources) { + expect(newExtendersObj.profileTypes["some-type"].latestFrom).toBeUndefined(); + expect(newExtendersObj.profileTypes["some-type"].version).toBeUndefined(); + } + + expect(typesToRemove.length > 0).toBe(shouldUpdate.schema ?? false); + }; + + it("package is only source for profile type", () => { + expectUpdateExtendersJson({ extJson: true, schema: true }, { + profileTypes: { + "some-type": { + from: ["aPluginPackage"], + } + } + }); + }); + + it("package is latest source of profile type", () => { + expectUpdateExtendersJson({ extJson: true }, { + profileTypes: { + "some-type": { + from: ["aPluginPackage", "someOtherPlugin"], + latestFrom: "aPluginPackage" + } + } + }); + }); + + it("profile type has multiple sources", () => { + expectUpdateExtendersJson({ extJson: true }, { + profileTypes: { + "some-type": { + from: ["aPluginPackage", "someOtherPlugin"], + } + } + }); + }); + + it("returns an empty list when package does not contribute any profile types", () => { + const blockMocks = getBlockMocks(); + blockMocks.profileInfo.readExtendersJsonFromDisk.mockReturnValue({ + profileTypes: { + "some-type": { + from: ["anotherPkg"] + } + } + }); + expect(updateAndGetRemovedTypes("aPluginPackage").length).toBe(0); + }); + }); }); + diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index 49e24c179a..1676e03e89 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -24,6 +24,47 @@ import { fileURLToPath, pathToFileURL } from "url"; import { IProfileTypeConfiguration } from "../../../../../profiles"; const npmCmd = findNpmOnPath(); +/** + * Updates `extenders.json` and returns a list of types to remove from the schema, if applicable. + * @param npmPackage The package name for the plug-in that's being uninstalled + * @returns A list of types to remove from the schema + */ +export function updateAndGetRemovedTypes(npmPackage: string): string[] { + const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); + const pluginTypes = Object.keys(extendersJson.profileTypes) + .filter((type) => extendersJson.profileTypes[type].from.includes(npmPackage)); + const typesToRemove: string[] = []; + if (pluginTypes.length > 0) { + // Only remove a profile type contributed by this plugin if its the single source for that type. + for (const profileType of pluginTypes) { + const typeInfo = extendersJson.profileTypes[profileType]; + if (typeInfo.from.length > 1) { + // If there are other sources, remove the version for that type if this plugin provides the + // latest version. This will allow the next source to contribute a different schema version. + if (typeInfo.latestFrom === npmPackage) { + extendersJson.profileTypes[profileType] = { + ...typeInfo, + from: typeInfo.from.filter((v) => v !== npmPackage), + latestFrom: undefined, + version: undefined + }; + } else { + extendersJson.profileTypes[profileType] = { + ...typeInfo, + from: typeInfo.from.filter((v) => v !== npmPackage) + }; + } + } else { + delete extendersJson.profileTypes[profileType]; + typesToRemove.push(profileType); + } + } + ProfileInfo.writeExtendersJson(extendersJson); + } + + return typesToRemove; +} + /** * @TODO - allow multiple packages to be uninstalled? * Common function that abstracts the uninstall process. @@ -95,42 +136,6 @@ export function uninstall(packageName: string): void { const schemaUri = new URL(globalLayer.properties.$schema, pathToFileURL(globalLayer.path)); const schemaPath = schemaUri.protocol === "file:" ? fileURLToPath(schemaUri) : undefined; if (schemaPath && fs.existsSync(schemaPath)) { - const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); - const pluginTypes = Object.keys(extendersJson.profileTypes) - .filter((type) => type in extendersJson.profileTypes && - extendersJson.profileTypes[type].from.includes(npmPackage)); - const typesToRemove: string[] = []; - if (pluginTypes.length > 0) { - // Only remove a profile type contributed by this plugin if its the single source for that type. - for (const profileType of pluginTypes) { - const typeInfo = extendersJson.profileTypes[profileType]; - if (typeInfo.from.length > 1) { - // If there are other sources, remove the version for that type if this plugin provides the - // latest version. This will allow the next source to contribute a different schema version. - if (typeInfo.latestFrom === npmPackage) { - extendersJson.profileTypes[profileType] = { - ...typeInfo, - from: typeInfo.from.filter((v) => v !== npmPackage), - latestFrom: undefined, - version: undefined - }; - } else { - extendersJson.profileTypes[profileType] = { - ...typeInfo, - from: typeInfo.from.filter((v) => v !== npmPackage) - }; - } - } else { - extendersJson.profileTypes[profileType] = { - ...typeInfo, - from: typeInfo.from.filter((v) => v !== npmPackage) - }; - typesToRemove.push(profileType); - } - } - ProfileInfo.writeExtendersJson(extendersJson); - } - let loadedSchema: IProfileTypeConfiguration[]; try { // load schema from disk to prevent removal of profile types from other applications @@ -138,14 +143,14 @@ export function uninstall(packageName: string): void { } catch (err) { iConsole.error("Error when removing profile type for plugin %s: failed to parse schema", npmPackage); } - - // Only update global schema if we were able to load it from disk - if (loadedSchema != null) { - if (typesToRemove.length > 0) { - loadedSchema = loadedSchema.filter((typeCfg) => !typesToRemove.includes(typeCfg.type)); - const schema = ConfigSchema.buildSchema(loadedSchema); - ConfigSchema.updateSchema({ layer: "global", schema }); - } + // update extenders.json with any removed types - function returns the list of types to remove + const typesToRemove = updateAndGetRemovedTypes(npmPackage); + + // Only update global schema if there are types to remove and accessible from disk + if (loadedSchema != null && typesToRemove.length > 0) { + loadedSchema = loadedSchema.filter((typeCfg) => !typesToRemove.includes(typeCfg.type)); + const schema = ConfigSchema.buildSchema(loadedSchema); + ConfigSchema.updateSchema({ layer: "global", schema }); } } } From 4b72f50deeed88c3debf557a0158af890ab0e7a8 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Thu, 11 Jan 2024 12:27:59 -0500 Subject: [PATCH 38/92] doc: Add on-disk example to IExtendersJsonOpts Signed-off-by: Trae Yelovich --- .../src/config/src/doc/IExtenderOpts.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/imperative/src/config/src/doc/IExtenderOpts.ts b/packages/imperative/src/config/src/doc/IExtenderOpts.ts index d11d27c8ad..ec70b20a3e 100644 --- a/packages/imperative/src/config/src/doc/IExtenderOpts.ts +++ b/packages/imperative/src/config/src/doc/IExtenderOpts.ts @@ -11,6 +11,22 @@ import { IProfileSchema } from "../../../profiles"; +/** + * This type corresponds to the `extenders.json` file stored in the CLI home directory. + * + * Here is an example structure of what `extenders.json` could look like on disk: + * ```json + * { + * "profileTypes": { + * "banana": { + * "from": ["@zowe/banana-for-zowe-cli", "Zowe Explorer Banana Extension"], + * "version": "v1.1.0", + * "latestFrom": "Zowe Explorer Banana Extension" + * } + * } + * } + * ``` + */ export type IExtendersJsonOpts = { // A map of profile types to type metadata. // Used to track contributed profile types between Zowe client applications. From 60c7730269cc43f07fd381734de42e018da78a78 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Thu, 11 Jan 2024 13:38:12 -0500 Subject: [PATCH 39/92] fix: check for valid schemaVersion during install Signed-off-by: Trae Yelovich --- .../imperative/src/plugins/utilities/npm-interface/install.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index 97da69b93b..1e7fa4eca5 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -196,7 +196,7 @@ export async function install(packageLocation: string, registry: string, install } else { const existingType = loadedSchema.find((obj) => obj.type === profile.type); if (semver.valid(existingType.schemaVersion)) { - if (semver.gt(profile.schemaVersion, existingType.schemaVersion)) { + if (semver.valid(profile.schemaVersion) && semver.gt(profile.schemaVersion, existingType.schemaVersion)) { existingType.schema = profile.schema; existingType.schemaVersion = profile.schemaVersion; } From 10c2f9efa749f9f46db44dab45f7e156952d8795 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 12 Jan 2024 14:31:01 -0500 Subject: [PATCH 40/92] fix: removed unused TODO comment Signed-off-by: Trae Yelovich --- .../src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index b42bfd0b3f..286240b943 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1635,7 +1635,6 @@ describe("TeamConfig ProfileInfo tests", () => { }); }); describe("buildSchema", () => { - // TODO it("builds a schema with the default types", async () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); From 97373db8270b54e064761503956342df711e29a5 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 12 Jan 2024 14:43:25 -0500 Subject: [PATCH 41/92] fix: move 'version' into IProfileSchema; update tests Signed-off-by: Trae Yelovich --- .../ProfileInfo.TeamConfig.unit.test.ts | 10 ++++----- .../imperative/src/config/src/ProfileInfo.ts | 22 +++++++++---------- .../src/config/src/doc/IExtenderOpts.ts | 2 -- .../src/doc/definition/IProfileSchema.ts | 3 +++ 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 286240b943..0c80bc2f20 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1493,7 +1493,7 @@ describe("TeamConfig ProfileInfo tests", () => { }); describe("addProfileTypeToSchema", () => { - const expectAddToSchemaTester = async (testCase: { schema: any; previousVersion?: string; version?: string }, expected: { + const expectAddToSchemaTester = async (testCase: { schema: any; previousVersion?: string }, expected: { extendersJson: IExtendersJsonOpts, res: { success: boolean; @@ -1556,7 +1556,7 @@ describe("TeamConfig ProfileInfo tests", () => { it("only updates a profile type in the schema if the version is newer", async () => { expectAddToSchemaTester( - { previousVersion: "1.0.0", schema: { title: "Mock Schema" } as any, version: "2.0.0" }, + { previousVersion: "1.0.0", schema: { title: "Mock Schema", version: "2.0.0" } as any }, { extendersJson: { profileTypes: { @@ -1576,7 +1576,7 @@ describe("TeamConfig ProfileInfo tests", () => { it("does not update a profile type in the schema if the version is older", async () => { expectAddToSchemaTester( - { previousVersion: "2.0.0", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { previousVersion: "2.0.0", schema: { title: "Mock Schema", version: "1.0.0" } as any }, { extendersJson: { profileTypes: { @@ -1596,7 +1596,7 @@ describe("TeamConfig ProfileInfo tests", () => { it("updates a profile type in the schema - version provided, no previous schema version", async () => { expectAddToSchemaTester( - { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { previousVersion: "none", schema: { title: "Mock Schema", version: "1.0.0" } as any }, { extendersJson: { profileTypes: { @@ -1616,7 +1616,7 @@ describe("TeamConfig ProfileInfo tests", () => { it("does not update the schema if schema version is invalid", async () => { expectAddToSchemaTester( - { previousVersion: "none", schema: { title: "Mock Schema" } as any, version: "1.0.0" }, + { previousVersion: "none", schema: { title: "Mock Schema", version: "1.0.0" } as any }, { extendersJson: { profileTypes: { diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 06a994f867..32be785b51 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1364,45 +1364,45 @@ export class ProfileInfo { // Profile type was already contributed, determine whether its metadata should be updated const typeMetadata = this.mExtendersJson.profileTypes[profileType]; - if (semver.valid(typeInfo.version) != null) { + if (semver.valid(typeInfo.schema.version) != null) { // The provided version is SemVer-compliant; compare against previous version (if exists) const prevTypeVersion = typeMetadata.version; if (prevTypeVersion != null) { - if (semver.gt(typeInfo.version, prevTypeVersion)) { + if (semver.gt(typeInfo.schema.version, prevTypeVersion)) { // Update the schema for this profile type, as its newer than the installed version this.mExtendersJson.profileTypes[profileType] = { - version: typeInfo.version, + version: typeInfo.schema.version, from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]), latestFrom: typeInfo.sourceApp }; this.updateSchemaAtLayer(profileType, typeInfo.schema, true); - if (semver.major(typeInfo.version) != semver.major(prevTypeVersion)) { + if (semver.major(typeInfo.schema.version) != semver.major(prevTypeVersion)) { // Warn user if new major schema version is specified successMsg = - `Profile type ${profileType} was updated from schema version ${prevTypeVersion} to ${typeInfo.version}.\n`.concat( + `Profile type ${profileType} was updated from schema version ${prevTypeVersion} to ${typeInfo.schema.version}.\n`.concat( `The following applications may be affected: ${typeMetadata.from.filter((src) => src !== typeInfo.sourceApp)}` ); } - } else if (semver.major(prevTypeVersion) > semver.major(typeInfo.version)) { + } else if (semver.major(prevTypeVersion) > semver.major(typeInfo.schema.version)) { // Warn user if previous schema version is a newer major version return { success: false, info: `Profile type ${profileType} expects a newer schema version than provided by ${typeInfo.sourceApp}\n`.concat( - `(expected: v${typeInfo.version}, installed: v${prevTypeVersion})`) + `(expected: v${typeInfo.schema.version}, installed: v${prevTypeVersion})`) }; } } else { // No schema version specified previously; update the schema this.mExtendersJson.profileTypes[profileType] = { - version: typeInfo.version, + version: typeInfo.schema.version, from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]), latestFrom: typeInfo.sourceApp }; this.updateSchemaAtLayer(profileType, typeInfo.schema, true); } - } else if (typeInfo.version != null) { + } else if (typeInfo.schema.version != null) { // Warn user if this schema does not provide a valid version number return { success: false, @@ -1412,9 +1412,9 @@ export class ProfileInfo { } else { // Newly-contributed profile type; track in extenders.json this.mExtendersJson.profileTypes[profileType] = { - version: typeInfo.version, + version: typeInfo.schema.version, from: [typeInfo.sourceApp], - latestFrom: typeInfo.version ? typeInfo.sourceApp : undefined + latestFrom: typeInfo.schema.version ? typeInfo.sourceApp : undefined }; this.updateSchemaAtLayer(profileType, typeInfo.schema); } diff --git a/packages/imperative/src/config/src/doc/IExtenderOpts.ts b/packages/imperative/src/config/src/doc/IExtenderOpts.ts index ec70b20a3e..c5003c95c2 100644 --- a/packages/imperative/src/config/src/doc/IExtenderOpts.ts +++ b/packages/imperative/src/config/src/doc/IExtenderOpts.ts @@ -54,6 +54,4 @@ export type IExtenderTypeInfo = { sourceApp: string; // The schema for the new profile type. schema: IProfileSchema; - // A version for the new profile type's schema (optional). - version?: string; }; \ No newline at end of file diff --git a/packages/imperative/src/profiles/src/doc/definition/IProfileSchema.ts b/packages/imperative/src/profiles/src/doc/definition/IProfileSchema.ts index 5b515b5ad3..9513c49354 100644 --- a/packages/imperative/src/profiles/src/doc/definition/IProfileSchema.ts +++ b/packages/imperative/src/profiles/src/doc/definition/IProfileSchema.ts @@ -45,6 +45,9 @@ export interface IProfileSchema { [key: string]: IProfileProperty, }; + // A version for the schema (optional). + version?: string; + /** * An array of properties that must be present in the finished profile. * If any of these fields are missing, profile validation will fail. From ffec300ac7da30e46552e50b2b62854b559e2bd3 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 12 Jan 2024 14:45:39 -0500 Subject: [PATCH 42/92] chore: remove schemaVersion from IProfileTypeConfiguration Signed-off-by: Trae Yelovich --- .../src/profiles/src/doc/config/IProfileTypeConfiguration.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts b/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts index f0ce01f23b..0a1bb86c31 100644 --- a/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts +++ b/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts @@ -39,10 +39,6 @@ export interface IProfileTypeConfiguration { * @memberof IProfileTypeConfiguration */ schema: IProfileSchema; - /** - * The version for the JSON schema document (not required). - */ - schemaVersion?: string; /** * The profile dependency specification. Indicates the required or optional profiles that a profile is depedent * on. Dependencies are written as part of the profile, but you do NOT need to specify dependencies in your From 6a189e9b05518f5d4f4743096e6a1e9c69f19c6d Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 12 Jan 2024 14:47:58 -0500 Subject: [PATCH 43/92] fix: update install logic for relocated version property Signed-off-by: Trae Yelovich --- .../src/plugins/utilities/npm-interface/install.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index 1e7fa4eca5..b1eee7f6d8 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -168,7 +168,7 @@ export async function install(packageLocation: string, registry: string, install // If the type doesn't exist, add it to extenders.json and return extendersJson.profileTypes[profile.type] = { from: [packageInfo.name], - version: profile.schemaVersion + version: profile.schema.version }; return true; } @@ -176,14 +176,14 @@ export async function install(packageLocation: string, registry: string, install // Otherwise, only update extenders.json if the schema version is newer const existingTypeInfo = extendersJson.profileTypes[profile.type]; if (semver.valid(existingTypeInfo.version)) { - if (profile.schemaVersion && semver.lt(profile.schemaVersion, existingTypeInfo.version)) { + if (profile.schema.version && semver.lt(profile.schema.version, existingTypeInfo.version)) { return false; } } extendersJson.profileTypes[profile.type] = { from: [packageInfo.name], - version: profile.schemaVersion + version: profile.schema.version }; return true; }; @@ -195,14 +195,14 @@ export async function install(packageLocation: string, registry: string, install loadedSchema.push(profile); } else { const existingType = loadedSchema.find((obj) => obj.type === profile.type); - if (semver.valid(existingType.schemaVersion)) { - if (semver.valid(profile.schemaVersion) && semver.gt(profile.schemaVersion, existingType.schemaVersion)) { + if (semver.valid(existingType.schema.version)) { + if (semver.valid(profile.schema.version) && semver.gt(profile.schema.version, existingType.schema.version)) { existingType.schema = profile.schema; - existingType.schemaVersion = profile.schemaVersion; + existingType.schema.version = profile.schema.version; } } else { existingType.schema = profile.schema; - existingType.schemaVersion = profile.schemaVersion; + existingType.schema.version = profile.schema.version; } } shouldUpdate = updateExtendersJson(profile) || shouldUpdate; From 697fedd4984cd787a914bbc1c1ca6552fb81edfa Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 16 Jan 2024 08:55:35 -0500 Subject: [PATCH 44/92] fix: adjust tests for relocated version, rename resource Signed-off-by: Trae Yelovich --- .../__resources__/{schema.ts => typeConfiguration.ts} | 4 ++-- .../plugins/utilities/npm-interface/install.unit.test.ts | 8 ++++---- .../utilities/npm-interface/uninstall.unit.test.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) rename packages/imperative/src/imperative/__tests__/plugins/__resources__/{schema.ts => typeConfiguration.ts} (89%) diff --git a/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts b/packages/imperative/src/imperative/__tests__/plugins/__resources__/typeConfiguration.ts similarity index 89% rename from packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts rename to packages/imperative/src/imperative/__tests__/plugins/__resources__/typeConfiguration.ts index 1495ada4c0..c9a7b79830 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/__resources__/schema.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/__resources__/typeConfiguration.ts @@ -11,7 +11,7 @@ import { IProfileTypeConfiguration } from "../../../.."; -const mockSchema: IProfileTypeConfiguration = { +const mockTypeConfig: IProfileTypeConfiguration = { type: "test-type", schema: { title: "test-type", @@ -27,4 +27,4 @@ const mockSchema: IProfileTypeConfiguration = { } }; -export default mockSchema; \ No newline at end of file +export default mockTypeConfig; \ No newline at end of file diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts index e738341c7b..2687462043 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts @@ -60,7 +60,7 @@ import * as fs from "fs"; import * as path from "path"; import { gt as versionGreaterThan } from "semver"; import { ProfileInfo } from "../../../../../config"; -import mockSchema from "../../__resources__/schema"; +import mockTypeConfig from "../../__resources__/typeConfiguration"; function setResolve(toResolve: string, resolveTo?: string) { expectedVal = toResolve; @@ -116,8 +116,8 @@ describe("PMF: Install Interface", () => { } }); mocks.ProfileInfo.writeExtendersJson.mockImplementation(); - mocks.ConfigSchema_loadSchema.mockReturnValue([mockSchema]); - mocks.ConfigurationLoader_load.mockReturnValue({ profiles: [mockSchema] } as any); + mocks.ConfigSchema_loadSchema.mockReturnValue([mockTypeConfig]); + mocks.ConfigurationLoader_load.mockReturnValue({ profiles: [mockTypeConfig] } as any); }); afterAll(() => { @@ -386,7 +386,7 @@ describe("PMF: Install Interface", () => { } }; if (opts.newProfileType) { - const schema = { ...mockSchema, schemaVersion: opts.version }; + const schema = { ...mockTypeConfig, schema: { ...mockTypeConfig.schema, version: opts.version } }; mocks.ConfigurationLoader_load.mockReturnValue({ profiles: [ schema diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts index a94c0bb420..1a0230e89f 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts @@ -31,7 +31,7 @@ import { readFileSync, writeFileSync } from "jsonfile"; import { findNpmOnPath } from "../../../../src/plugins/utilities/NpmFunctions"; import { uninstall } from "../../../../src/plugins/utilities/npm-interface"; import { ConfigSchema, ProfileInfo } from "../../../../../config"; -import mockSchema from "../../__resources__/schema"; +import mockTypeConfig from "../../__resources__/typeConfiguration"; import { ExecUtils } from "../../../../../utilities"; import { IExtendersJsonOpts } from "../../../../../config/src/doc/IExtenderOpts"; import { updateAndGetRemovedTypes } from "../../../../src/plugins/utilities/npm-interface/uninstall"; @@ -214,7 +214,7 @@ describe("PMF: Uninstall Interface", () => { return { ConfigSchema: { buildSchema: jest.spyOn(ConfigSchema, "buildSchema").mockImplementation(), - loadSchema: jest.spyOn(ConfigSchema, "loadSchema").mockReturnValueOnce([mockSchema]), + loadSchema: jest.spyOn(ConfigSchema, "loadSchema").mockReturnValueOnce([mockTypeConfig]), updateSchema: jest.spyOn(ConfigSchema, "updateSchema").mockImplementation() }, fs: { From 945b255e41f9a88a902df58392ba54c8d452bff4 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 16 Jan 2024 11:10:31 -0500 Subject: [PATCH 45/92] refactor: move updateExtendersJson out of install function Signed-off-by: Trae Yelovich --- .../utilities/npm-interface/install.ts | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index b1eee7f6d8..bb33b3bec6 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -28,6 +28,37 @@ import { fileURLToPath, pathToFileURL } from "url"; import { IProfileTypeConfiguration } from "../../../../../profiles"; import * as semver from "semver"; import { ProfileInfo } from "../../../../../config"; +import { IExtendersJsonOpts } from "../../../../../config/src/doc/IExtenderOpts"; + +// Helper function to update extenders.json object during plugin install. +// Returns true if the object was updated, and false otherwise +const updateExtendersJson = ( + extendersJson: IExtendersJsonOpts, + packageInfo: { name: string; version: string; }, + profile: IProfileTypeConfiguration): boolean => { + if (!(profile.type in extendersJson.profileTypes)) { + // If the type doesn't exist, add it to extenders.json and return + extendersJson.profileTypes[profile.type] = { + from: [packageInfo.name], + version: profile.schema.version + }; + return true; + } + + // Otherwise, only update extenders.json if the schema version is newer + const existingTypeInfo = extendersJson.profileTypes[profile.type]; + if (semver.valid(existingTypeInfo.version)) { + if (profile.schema.version && semver.lt(profile.schema.version, existingTypeInfo.version)) { + return false; + } + } + + extendersJson.profileTypes[profile.type] = { + from: [packageInfo.name], + version: profile.schema.version + }; + return true; +}; /** * Common function that abstracts the install process. This function should be called for each @@ -161,33 +192,6 @@ export async function install(packageLocation: string, registry: string, install const existingTypes = loadedSchema.map((obj) => obj.type); const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); - // Helper function to update extenders.json object during plugin install. - // Returns true if the object was updated, and false otherwise - const updateExtendersJson = (profile: IProfileTypeConfiguration): boolean => { - if (!(profile.type in extendersJson.profileTypes)) { - // If the type doesn't exist, add it to extenders.json and return - extendersJson.profileTypes[profile.type] = { - from: [packageInfo.name], - version: profile.schema.version - }; - return true; - } - - // Otherwise, only update extenders.json if the schema version is newer - const existingTypeInfo = extendersJson.profileTypes[profile.type]; - if (semver.valid(existingTypeInfo.version)) { - if (profile.schema.version && semver.lt(profile.schema.version, existingTypeInfo.version)) { - return false; - } - } - - extendersJson.profileTypes[profile.type] = { - from: [packageInfo.name], - version: profile.schema.version - }; - return true; - }; - // Determine new profile types to add to schema let shouldUpdate = false; for (const profile of pluginImpConfig.profiles) { @@ -205,7 +209,7 @@ export async function install(packageLocation: string, registry: string, install existingType.schema.version = profile.schema.version; } } - shouldUpdate = updateExtendersJson(profile) || shouldUpdate; + shouldUpdate = updateExtendersJson(extendersJson, packageInfo, profile) || shouldUpdate; } if (shouldUpdate) { From b339ce06dca285d5c463faf9b4fa9b2fadbba639 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 16 Jan 2024 11:47:30 -0500 Subject: [PATCH 46/92] refactor: use Config.getSchemaInfo during install/uninstall Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/__mocks__/Config.ts | 9 ++++++++- .../src/plugins/utilities/npm-interface/install.ts | 8 +++----- .../src/plugins/utilities/npm-interface/uninstall.ts | 7 +++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/imperative/src/config/src/__mocks__/Config.ts b/packages/imperative/src/config/src/__mocks__/Config.ts index 0d3a961ad2..b302f9b08c 100644 --- a/packages/imperative/src/config/src/__mocks__/Config.ts +++ b/packages/imperative/src/config/src/__mocks__/Config.ts @@ -9,7 +9,7 @@ * */ -import { IConfigOpts } from "../.."; +import { IConfigOpts, IConfigSchemaInfo } from "../.."; import { IConfigLayer } from "../../src/doc/IConfigLayer"; export class Config { @@ -54,4 +54,11 @@ export class Config { return config; } + public getSchemaInfo(): IConfigSchemaInfo { + return { + local: true, + resolved: "/some/path/to/schema.json", + original: "/some/path/to/schema.json" + }; + } } \ No newline at end of file diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index bb33b3bec6..8532fcf7e9 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -24,7 +24,6 @@ import { PluginManagementFacility } from "../../PluginManagementFacility"; import { ConfigurationLoader } from "../../../ConfigurationLoader"; import { UpdateImpConfig } from "../../../UpdateImpConfig"; import { CredentialManagerOverride, ICredentialManagerNameMap } from "../../../../../security"; -import { fileURLToPath, pathToFileURL } from "url"; import { IProfileTypeConfiguration } from "../../../../../profiles"; import * as semver from "semver"; import { ProfileInfo } from "../../../../../config"; @@ -176,13 +175,12 @@ export async function install(packageLocation: string, registry: string, install const globalLayer = PMFConstants.instance.PLUGIN_CONFIG.layers.find((layer) => layer.global && layer.exists); if (globalLayer && Array.isArray(pluginImpConfig.profiles)) { UpdateImpConfig.addProfiles(pluginImpConfig.profiles); - const schemaUri = new URL(globalLayer.properties.$schema, pathToFileURL(globalLayer.path)); - const schemaPath = schemaUri.protocol === "file:" ? fileURLToPath(schemaUri) : undefined; - if (schemaPath && fs.existsSync(schemaPath)) { + const schemaInfo = PMFConstants.instance.PLUGIN_CONFIG.getSchemaInfo(); + if (schemaInfo.local && fs.existsSync(schemaInfo.resolved)) { let loadedSchema: IProfileTypeConfiguration[]; try { // load schema from disk to prevent removal of profile types from other applications - loadedSchema = ConfigSchema.loadSchema(readFileSync(schemaPath)); + loadedSchema = ConfigSchema.loadSchema(readFileSync(schemaInfo.resolved)); } catch (err) { iConsole.error("Error when adding new profile type for plugin %s: failed to parse schema", newPlugin.package); } diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index 1676e03e89..25d9bd5a78 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -133,13 +133,12 @@ export function uninstall(packageName: string): void { // This might be needed outside of PLUGIN_USING_CONFIG scenarios, but we haven't had issues with other APIs before const globalLayer = PMFConstants.instance.PLUGIN_CONFIG.layers.find((layer) => layer.global && layer.exists); if (globalLayer) { - const schemaUri = new URL(globalLayer.properties.$schema, pathToFileURL(globalLayer.path)); - const schemaPath = schemaUri.protocol === "file:" ? fileURLToPath(schemaUri) : undefined; - if (schemaPath && fs.existsSync(schemaPath)) { + const schemaInfo = PMFConstants.instance.PLUGIN_CONFIG.getSchemaInfo(); + if (schemaInfo.local && fs.existsSync(schemaInfo.resolved)) { let loadedSchema: IProfileTypeConfiguration[]; try { // load schema from disk to prevent removal of profile types from other applications - loadedSchema = ConfigSchema.loadSchema(readFileSync(schemaPath)); + loadedSchema = ConfigSchema.loadSchema(readFileSync(schemaInfo.resolved)); } catch (err) { iConsole.error("Error when removing profile type for plugin %s: failed to parse schema", npmPackage); } From 1a2909a3b28de5fe7ddd890682ae3852bd156659 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 16 Jan 2024 13:23:41 -0500 Subject: [PATCH 47/92] chore: remove unused imports from URL module Signed-off-by: Trae Yelovich --- .../imperative/src/plugins/utilities/npm-interface/uninstall.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index 25d9bd5a78..ec9e033747 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -20,7 +20,6 @@ import { ExecUtils, TextUtils } from "../../../../../utilities"; import { StdioOptions } from "child_process"; import { findNpmOnPath } from "../NpmFunctions"; import { ConfigSchema, ProfileInfo } from "../../../../../config"; -import { fileURLToPath, pathToFileURL } from "url"; import { IProfileTypeConfiguration } from "../../../../../profiles"; const npmCmd = findNpmOnPath(); From 3ad578600506e73b34a2ebb9e51f9c2380337a36 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 19 Jan 2024 08:03:23 -0500 Subject: [PATCH 48/92] style: Use arrow function for updateAndGetRemovedTypes Signed-off-by: Trae Yelovich --- .../imperative/src/plugins/utilities/npm-interface/uninstall.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index ec9e033747..f3661a7687 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -28,7 +28,7 @@ const npmCmd = findNpmOnPath(); * @param npmPackage The package name for the plug-in that's being uninstalled * @returns A list of types to remove from the schema */ -export function updateAndGetRemovedTypes(npmPackage: string): string[] { +export const updateAndGetRemovedTypes = (npmPackage: string): string[] => { const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); const pluginTypes = Object.keys(extendersJson.profileTypes) .filter((type) => extendersJson.profileTypes[type].from.includes(npmPackage)); From e2b026d715ebce31858747a3b8605ebba0891fc7 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 19 Jan 2024 08:26:48 -0500 Subject: [PATCH 49/92] tests: updateExtendersJson Signed-off-by: Trae Yelovich --- .../npm-interface/install.unit.test.ts | 26 +++++++++++++++++++ .../utilities/npm-interface/install.ts | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts index 2687462043..6d07a1a448 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts @@ -61,6 +61,8 @@ import * as path from "path"; import { gt as versionGreaterThan } from "semver"; import { ProfileInfo } from "../../../../../config"; import mockTypeConfig from "../../__resources__/typeConfiguration"; +import { updateExtendersJson } from "../../../../src/plugins/utilities/npm-interface/install"; +import { IExtendersJsonOpts } from "../../../../../config/src/doc/IExtenderOpts"; function setResolve(toResolve: string, resolveTo?: string) { expectedVal = toResolve; @@ -463,6 +465,30 @@ describe("PMF: Install Interface", () => { }); }); + describe("updating extenders.json", () => { + it("adds a new profile type if it doesn't exist", () => { + const extendersJson = { profileTypes: {} } as IExtendersJsonOpts; + updateExtendersJson(extendersJson, { name: "aPkg", version: "1.0.0" }, mockTypeConfig); + expect(extendersJson.profileTypes["test-type"]).not.toBeUndefined(); + }); + + it("replaces a profile type with a newer schema version", () => { + const extendersJson = { profileTypes: { "test-type": { from: ["Zowe Client App"], version: "0.9.0" } } }; + updateExtendersJson(extendersJson, { name: "aPkg", version: "1.0.0" }, + { ...mockTypeConfig, schema: { ...mockTypeConfig.schema, version: "1.0.0" } }); + expect(extendersJson.profileTypes["test-type"]).not.toBeUndefined(); + expect(extendersJson.profileTypes["test-type"].version).toBe("1.0.0"); + }); + + it("does not change the schema version if older", () => { + const extendersJson = { profileTypes: { "test-type": { from: ["Zowe Client App"], version: "1.2.0" } } }; + updateExtendersJson(extendersJson, { name: "aPkg", version: "1.0.0" }, + { ...mockTypeConfig, schema: { ...mockTypeConfig.schema, version: "1.0.0" } }); + expect(extendersJson.profileTypes["test-type"]).not.toBeUndefined(); + expect(extendersJson.profileTypes["test-type"].version).toBe("1.2.0"); + }); + }); + it("should throw errors", async () => { // Create a placeholder error object that should be set after the call to install let expectedError: ImperativeError = new ImperativeError({ diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index 8532fcf7e9..c627ac4dcc 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -31,7 +31,7 @@ import { IExtendersJsonOpts } from "../../../../../config/src/doc/IExtenderOpts" // Helper function to update extenders.json object during plugin install. // Returns true if the object was updated, and false otherwise -const updateExtendersJson = ( +export const updateExtendersJson = ( extendersJson: IExtendersJsonOpts, packageInfo: { name: string; version: string; }, profile: IProfileTypeConfiguration): boolean => { From b4fc89961c7af031bfa83016d7cdae370c499303 Mon Sep 17 00:00:00 2001 From: KevinLoesch1 Date: Fri, 19 Jan 2024 14:18:31 -0500 Subject: [PATCH 50/92] Updates for cross-lpar copy system tests Signed-off-by: KevinLoesch1 --- .../command_copy_data_set_cross_lpar.sh | 4 +- .../dsclp/cli.files.copy.dsclp.system.test.ts | 146 +++++++++++++----- 2 files changed, 113 insertions(+), 37 deletions(-) diff --git a/packages/cli/__tests__/zosfiles/__system__/copy/dsclp/__scripts__/command/command_copy_data_set_cross_lpar.sh b/packages/cli/__tests__/zosfiles/__system__/copy/dsclp/__scripts__/command/command_copy_data_set_cross_lpar.sh index 8d73a02ae2..7b679ae971 100755 --- a/packages/cli/__tests__/zosfiles/__system__/copy/dsclp/__scripts__/command/command_copy_data_set_cross_lpar.sh +++ b/packages/cli/__tests__/zosfiles/__system__/copy/dsclp/__scripts__/command/command_copy_data_set_cross_lpar.sh @@ -4,8 +4,8 @@ toDataSet=$2 options=$3 set -e -echo "================Z/OS FILES COPY DS===============" -zowe zos-files copy data-set $fromDataSet $toDataSet $options +echo "================Z/OS FILES COPY DSCLP===============" +zowe zos-files copy dsclp $fromDataSet $toDataSet $options if [ $? -gt 0 ] then diff --git a/packages/cli/__tests__/zosfiles/__system__/copy/dsclp/cli.files.copy.dsclp.system.test.ts b/packages/cli/__tests__/zosfiles/__system__/copy/dsclp/cli.files.copy.dsclp.system.test.ts index 50ae7c3807..8e4b753aec 100644 --- a/packages/cli/__tests__/zosfiles/__system__/copy/dsclp/cli.files.copy.dsclp.system.test.ts +++ b/packages/cli/__tests__/zosfiles/__system__/copy/dsclp/cli.files.copy.dsclp.system.test.ts @@ -11,9 +11,10 @@ import { Session } from "@zowe/imperative"; import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; +import { getRandomBytes } from "../../../../../../../__tests__/__src__/TestUtils"; import { TestEnvironment } from "../../../../../../../__tests__/__src__/environment/TestEnvironment"; import { ITestPropertiesSchema } from "../../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; -import { Delete, Create, CreateDataSetTypeEnum, Upload, Get } from "@zowe/zos-files-for-zowe-sdk"; +import { Delete, Create, ICreateDataSetOptions, CreateDataSetTypeEnum, Upload, Get } from "@zowe/zos-files-for-zowe-sdk"; import { join } from "path"; let REAL_SESSION: Session; @@ -27,6 +28,25 @@ const fromMemberName: string = "mem1"; const toMemberName: string = "mem2"; const responseTimeout = `--responseTimeout 5`; const replaceOption = `--replace`; +const largeDsSize = 1024 * 1024; +const largeDsOptions: ICreateDataSetOptions = { + alcunit: "CYL", + dsorg: "PS", + primary: 20, + recfm: "FB", + blksize: 6160, + lrecl: 80, + dirblk: 0 +} as any; +const largePdsOptions: ICreateDataSetOptions = { + alcunit: "CYL", + dsorg: "PO", + primary: 20, + recfm: "FB", + blksize: 6160, + lrecl: 80, + dirblk: 5 +} as any; describe("Copy data set", () => { beforeAll(async () => { @@ -41,7 +61,6 @@ describe("Copy data set", () => { user = defaultSystem.zosmf.user.trim().toUpperCase(); fromDataSetName = `${user}.COPY.FROM.SET`; toDataSetName = `${user}.COPY.TO.SET`; - }); afterAll(async () => { await TestEnvironment.cleanUp(TEST_ENVIRONMENT); @@ -54,13 +73,14 @@ describe("Copy data set", () => { }); describe("success scenarios", () => { const data = "1234"; - describe("sequential > sequential", () => { + let bigData:Buffer; + describe("sequential > sequential (Large Dataset)", () => { beforeEach(async () => { await Promise.all([ - Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, fromDataSetName), - Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, toDataSetName) + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, fromDataSetName, largeDsOptions) ]); - await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(data), fromDataSetName); + bigData = await getRandomBytes(largeDsSize); + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(bigData), fromDataSetName, { binary: true }); }); it("should copy a data set from the command", async () => { let response; @@ -73,7 +93,7 @@ describe("Copy data set", () => { TEST_ENVIRONMENT, [fromDataSetName, toDataSetName] ); - contents = await Get.dataSet(REAL_SESSION, toDataSetName); + contents = await Get.dataSet(REAL_SESSION, toDataSetName, { binary: true }); } catch(err) { error = err; } @@ -81,9 +101,17 @@ describe("Copy data set", () => { expect(error).toBe(undefined); expect(response.status).toBe(0); expect(response.stdout.toString()).toContain("Data set copied successfully."); - expect(contents.toString().trim()).toBe(data); + expect(contents.subarray(0, bigData.length)).toEqual(bigData); }); - it("should copy a data set from the command with response timeout", async () => { + }); + describe("sequential > sequential", () => { + beforeEach(async () => { + await Promise.all([ + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, fromDataSetName) + ]); + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(data), fromDataSetName); + }); + it("should copy a data set from the command", async () => { let response; let contents; let error; @@ -92,7 +120,7 @@ describe("Copy data set", () => { response = runCliScript( join(__dirname, "__scripts__", "command", "command_copy_data_set_cross_lpar.sh"), TEST_ENVIRONMENT, - [fromDataSetName, toDataSetName, responseTimeout] + [fromDataSetName, toDataSetName] ); contents = await Get.dataSet(REAL_SESSION, toDataSetName); } catch(err) { @@ -104,7 +132,7 @@ describe("Copy data set", () => { expect(response.stdout.toString()).toContain("Data set copied successfully."); expect(contents.toString().trim()).toBe(data); }); - it("should copy a data set from the command with replace option", async () => { + it("should copy a data set from the command with response timeout", async () => { let response; let contents; let error; @@ -113,7 +141,7 @@ describe("Copy data set", () => { response = runCliScript( join(__dirname, "__scripts__", "command", "command_copy_data_set_cross_lpar.sh"), TEST_ENVIRONMENT, - [fromDataSetName, toDataSetName, replaceOption] + [fromDataSetName, toDataSetName, responseTimeout] ); contents = await Get.dataSet(REAL_SESSION, toDataSetName); } catch(err) { @@ -171,27 +199,6 @@ describe("Copy data set", () => { error = err; } - expect(error).toBe(undefined); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Data set copied successfully."); - expect(contents.toString().trim()).toBe(data); - }); - it("should copy a data set from the command with replace option", async () => { - let response; - let contents; - let error; - - try { - response = runCliScript( - join(__dirname, "__scripts__", "command", "command_copy_data_set_cross_lpar.sh"), - TEST_ENVIRONMENT, - [`${fromDataSetName}(${fromMemberName})`, `${toDataSetName}(${toMemberName})`, replaceOption] - ); - contents = await Get.dataSet(REAL_SESSION, `${toDataSetName}(${toMemberName})`); - } catch(err) { - error = err; - } - expect(error).toBe(undefined); expect(response.status).toBe(0); expect(response.stdout.toString()).toContain("Data set copied successfully."); @@ -273,8 +280,7 @@ describe("Copy data set", () => { describe("member > sequential", () => { beforeEach(async () => { await Promise.all([ - Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, fromDataSetName), - Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, toDataSetName) + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, fromDataSetName) ]); await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(data), `${fromDataSetName}(${fromMemberName})`); }); @@ -320,6 +326,45 @@ describe("Copy data set", () => { expect(response.stdout.toString()).toContain("Data set copied successfully."); expect(contents.toString().trim()).toBe(data); }); + }); + describe("sequential > sequential with replace", () => { + beforeEach(async () => { + await Promise.all([ + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, fromDataSetName), + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, toDataSetName) + ]); + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(data), fromDataSetName); + }); + it("should copy a data set from the command with replace option", async () => { + let response; + let contents; + let error; + + try { + response = runCliScript( + join(__dirname, "__scripts__", "command", "command_copy_data_set_cross_lpar.sh"), + TEST_ENVIRONMENT, + [fromDataSetName, toDataSetName, replaceOption] + ); + contents = await Get.dataSet(REAL_SESSION, toDataSetName); + } catch(err) { + error = err; + } + + expect(error).toBe(undefined); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain("Data set copied successfully."); + expect(contents.toString().trim()).toBe(data); + }); + }); + describe("member > sequential with replace option", () => { + beforeEach(async () => { + await Promise.all([ + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, fromDataSetName), + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, toDataSetName) + ]); + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(data), `${fromDataSetName}(${fromMemberName})`); + }); it("should copy a data set from the command with replace option", async () => { let response; let contents; @@ -342,5 +387,36 @@ describe("Copy data set", () => { expect(contents.toString().trim()).toBe(data); }); }); + describe("member > member (Large file)", () => { + beforeEach(async () => { + await Promise.all([ + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, fromDataSetName, largePdsOptions), + Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, toDataSetName, largePdsOptions) + ]); + bigData = await getRandomBytes(largeDsSize); + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(bigData), `${fromDataSetName}(${fromMemberName})`, { binary: true }); + }); + it("should copy a member from the command", async () => { + let response; + let contents; + let error; + + try { + response = runCliScript( + join(__dirname, "__scripts__", "command", "command_copy_data_set_cross_lpar.sh"), + TEST_ENVIRONMENT, + [`${fromDataSetName}(${fromMemberName})`, `${toDataSetName}(${toMemberName})`] + ); + contents = await Get.dataSet(REAL_SESSION, `${toDataSetName}(${toMemberName})`, { binary: true }); + } catch(err) { + error = err; + } + + expect(error).toBe(undefined); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain("Data set copied successfully."); + expect(contents.subarray(0, bigData.length)).toEqual(bigData); + }); + }); }); }); From 4a76790f0eb805392f72f5fdc16f8327ef550560 Mon Sep 17 00:00:00 2001 From: KevinLoesch1 Date: Fri, 19 Jan 2024 14:29:44 -0500 Subject: [PATCH 51/92] Update change log Signed-off-by: KevinLoesch1 --- packages/cli/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 7a618b90e6..4609939ee1 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Zowe CLI package will be documented in this file. +## Recent Changes + +- BugFix: Update zos-files copy dsclp system tests to include large mock files. + ## `7.21.2` - BugFix: Correct extra character being displayed at the end of lines when issuing `zowe files compare` on Windows. [#1992](https://github.com/zowe/zowe-cli/issues/1992) From 9faf472cfd94ea09d897c7cb33d5aec0743dd50a Mon Sep 17 00:00:00 2001 From: KevinLoesch1 Date: Mon, 22 Jan 2024 13:39:43 -0500 Subject: [PATCH 52/92] Add additonal system test for large file view USS file Signed-off-by: KevinLoesch1 --- .../__system__/view/uss/View.uss.system.test.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/cli/__tests__/zosfiles/__system__/view/uss/View.uss.system.test.ts b/packages/cli/__tests__/zosfiles/__system__/view/uss/View.uss.system.test.ts index fc7f3f154b..9db8f91935 100644 --- a/packages/cli/__tests__/zosfiles/__system__/view/uss/View.uss.system.test.ts +++ b/packages/cli/__tests__/zosfiles/__system__/view/uss/View.uss.system.test.ts @@ -12,9 +12,10 @@ import { Imperative, Session } from "@zowe/imperative"; import * as path from "path"; -import { ZosFilesConstants, ZosmfRestClient, ZosmfHeaders } from "@zowe/cli"; +import { ZosFilesConstants, ZosmfRestClient, ZosmfHeaders, Upload } from "@zowe/cli"; import {ITestEnvironment, runCliScript} from "@zowe/cli-test-utils"; import {TestEnvironment} from "../../../../../../../__tests__/__src__/environment/TestEnvironment"; +import { getRandomBytes } from "../../../../../../../__tests__/__src__/TestUtils"; import {ITestPropertiesSchema} from "../../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; import { getUniqueDatasetName} from "../../../../../../../__tests__/__src__/TestUtils"; @@ -95,6 +96,19 @@ describe("View uss file", () => { expect(response.status).toBe(0); expect(response.stdout.toString().trim()).toEqual(data); }); + it("should view large uss file in binary", async () => { + const rawData:Buffer = await getRandomBytes(1024*64); + const data = encodeURIComponent(rawData.toLocaleString()); + await Upload.bufferToUssFile(REAL_SESSION, ussname, Buffer.from(data), { binary: true }); + + const shellScript = path.join(__dirname, "__scripts__", "command", "command_view_uss_file.sh"); + const response = runCliScript(shellScript, testEnvironment, [ussname.substr(1, ussname.length), "--binary"]); + const respdata = response.stdout.toLocaleString(); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(respdata.trim()).toEqual(data); + }); it("should view uss file with range", async () => { const data: string = "abcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyz\n"; const endpoint: string = ZosFilesConstants.RESOURCE + ZosFilesConstants.RES_USS_FILES + ussname; From 709f8bf8c0582094d7129dd20a9363d740b0050e Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Mon, 22 Jan 2024 19:02:15 +0000 Subject: [PATCH 53/92] Update packages Signed-off-by: Andrew W. Harn --- npm-shrinkwrap.json | 40 +++++-------------- packages/imperative/CHANGELOG.md | 4 ++ packages/imperative/package.json | 4 +- ...BasicProfileManager.save.unit.test.ts.snap | 2 +- ...cProfileManager.validate.unit.test.ts.snap | 2 +- 5 files changed, 19 insertions(+), 33 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 9dce7e980f..beebf6bc82 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -17276,9 +17276,9 @@ ] }, "node_modules/jsonschema": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.1.1.tgz", - "integrity": "sha1-PO3o4+QR03eHLu+8n98mODy8Ptk=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", "engines": { "node": "*" } @@ -18681,7 +18681,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "dev": true, "bin": { "mustache": "bin/mustache" } @@ -24801,12 +24800,12 @@ "jest-diff": "27.0.6", "js-yaml": "4.1.0", "jsonfile": "4.0.0", - "jsonschema": "1.1.1", + "jsonschema": "1.4.1", "lodash": "4.17.21", "lodash-deep": "2.0.0", "log4js": "6.4.6", "markdown-it": "12.3.2", - "mustache": "2.3.0", + "mustache": "4.2.0", "npm-package-arg": "9.1.0", "opener": "1.5.2", "pacote": "11.1.4", @@ -24989,17 +24988,6 @@ "node": ">=12" } }, - "packages/imperative/node_modules/mustache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz", - "integrity": "sha512-IgZ/cCHtDG1ft0vdDV9wrlNz20SvbUu2ECoDF6dhk2ZtedLNy1Kehy4oFlzmHPxcUQmVZuXYS2j+d0NkaEjTXQ==", - "bin": { - "mustache": "bin/mustache" - }, - "engines": { - "npm": ">=1.4.0" - } - }, "packages/imperative/node_modules/npm-package-arg": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz", @@ -32085,12 +32073,12 @@ "jest-diff": "27.0.6", "js-yaml": "4.1.0", "jsonfile": "4.0.0", - "jsonschema": "1.1.1", + "jsonschema": "1.4.1", "lodash": "4.17.21", "lodash-deep": "2.0.0", "log4js": "6.4.6", "markdown-it": "12.3.2", - "mustache": "2.3.0", + "mustache": "4.2.0", "npm-package-arg": "9.1.0", "opener": "1.5.2", "pacote": "11.1.4", @@ -32213,11 +32201,6 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" }, - "mustache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz", - "integrity": "sha512-IgZ/cCHtDG1ft0vdDV9wrlNz20SvbUu2ECoDF6dhk2ZtedLNy1Kehy4oFlzmHPxcUQmVZuXYS2j+d0NkaEjTXQ==" - }, "npm-package-arg": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz", @@ -39075,9 +39058,9 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" }, "jsonschema": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.1.1.tgz", - "integrity": "sha1-PO3o4+QR03eHLu+8n98mODy8Ptk=" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==" }, "JSONStream": { "version": "1.3.5", @@ -40165,8 +40148,7 @@ "mustache": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "dev": true + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" }, "mute-stream": { "version": "0.0.8", diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index eb6da797bb..0a37b378d7 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- BugFix: Updated `mustache` and `jsonschema` dependencies for technical currency. + ## `5.21.0` - Enhancement: Hid the progress bar if `CI` environment variable is set, or if `FORCE_COLOR` environment variable is set to `0`. [#1845](https://github.com/zowe/zowe-cli/issues/1845) diff --git a/packages/imperative/package.json b/packages/imperative/package.json index 0690ec6e56..5558fb00ab 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -59,12 +59,12 @@ "jest-diff": "27.0.6", "js-yaml": "4.1.0", "jsonfile": "4.0.0", - "jsonschema": "1.1.1", + "jsonschema": "1.4.1", "lodash": "4.17.21", "lodash-deep": "2.0.0", "log4js": "6.4.6", "markdown-it": "12.3.2", - "mustache": "2.3.0", + "mustache": "4.2.0", "npm-package-arg": "9.1.0", "opener": "1.5.2", "pacote": "11.1.4", diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.save.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.save.unit.test.ts.snap index bdd9d9b307..950e4aadfa 100644 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.save.unit.test.ts.snap +++ b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.save.unit.test.ts.snap @@ -61,7 +61,7 @@ exports[`Basic Profile Manager Save should detect that the dependencies are pres exports[`Basic Profile Manager Save should fail a save request if a profile has more properties than defined on the schema 1`] = ` "Errors located in profile \\"tasty_apple\\" of type \\"apple\\": -profile additionalProperty \\"seedless\\" exists in instance when not allowed +profile is not allowed to have the additional property \\"seedless\\" " `; diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.validate.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.validate.unit.test.ts.snap index 5d2a6372ff..0b4000e40e 100644 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.validate.unit.test.ts.snap +++ b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.validate.unit.test.ts.snap @@ -35,7 +35,7 @@ exports[`Basic Profile Manager Validate should detect undefined parms 1`] = `"Ex exports[`Basic Profile Manager Validate should fail a save request if a profile has more properties than defined on the schema 1`] = ` "Errors located in profile \\"good_apple\\" of type \\"apple\\": -profile additionalProperty \\"seedless\\" exists in instance when not allowed +profile is not allowed to have the additional property \\"seedless\\" " `; From dd73a7122f7ae1b4e089d82cf42fb5f712c3381b Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 23 Jan 2024 10:22:26 -0500 Subject: [PATCH 54/92] feat: replace schema if newer one has changed Signed-off-by: Trae Yelovich --- .../imperative/src/config/src/ProfileInfo.ts | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 95c67a24f2..c9959a4e02 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1403,12 +1403,24 @@ export class ProfileInfo { }; this.updateSchemaAtLayer(profileType, typeInfo.schema, true); } - } else if (typeInfo.schema.version != null) { - // Warn user if this schema does not provide a valid version number - return { - success: false, - info: `New schema type for profile type ${profileType} is not SemVer-compliant; schema was not updated` - }; + } else { + if (typeInfo.schema.version != null) { + // Warn user if this schema does not provide a valid version number + return { + success: false, + info: `New schema type for profile type ${profileType} is not SemVer-compliant; schema was not updated` + }; + } + + // If the old schema doesn't have a tracked version and its different from the one passed into this function, use the new schema + if (this.mExtendersJson.profileTypes[profileType].version == null && + !lodash.isEqual({ ...typeInfo.schema, version: undefined }, { ...this.getSchemaForType(profileType), version: undefined })) { + this.mExtendersJson.profileTypes[profileType] = { + version: typeInfo.schema.version, + from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) + }; + this.updateSchemaAtLayer(profileType, typeInfo.schema, true); + } } } else { // Newly-contributed profile type; track in extenders.json From e2ed3771193915fc032c29d408dbe543f4d27403 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 23 Jan 2024 11:33:49 -0500 Subject: [PATCH 55/92] feat: warn user when old/new unversioned schemas are different Signed-off-by: Trae Yelovich --- .../ProfileInfo.TeamConfig.unit.test.ts | 18 ++++++++++++++++++ .../imperative/src/config/src/ProfileInfo.ts | 12 ++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 9b4aa5e184..428326ccca 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1559,6 +1559,24 @@ describe("TeamConfig ProfileInfo tests", () => { ); }); + it("warns the user when old, unversioned schema is different from new, unversioned schema", () => { + jest.spyOn(ProfileInfo.prototype, "getSchemaForType").mockReturnValue({ title: "Mock Schema", otherKey: "otherVal" } as any); + expectAddToSchemaTester( + { schema: { title: "Mock Schema", someKey: "someValue" } as any, previousVersion: "none" }, + { + extendersJson: { + profileTypes: { + "some-type": { + from: ["Zowe Client App"] + } + } + }, + res: { success: false, info: "Both the old and new schemas are unversioned for some-type, but the schemas are different. " + .concat("The new schema was not written to disk, but will still be accessible in-memory.") } + } + ); + }); + it("only updates a profile type in the schema if the version is newer", async () => { expectAddToSchemaTester( { previousVersion: "1.0.0", schema: { title: "Mock Schema", version: "2.0.0" } as any }, diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index c9959a4e02..dc398da9a3 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1412,14 +1412,14 @@ export class ProfileInfo { }; } - // If the old schema doesn't have a tracked version and its different from the one passed into this function, use the new schema + // If the old schema doesn't have a tracked version and its different from the one passed into this function, warn the user if (this.mExtendersJson.profileTypes[profileType].version == null && - !lodash.isEqual({ ...typeInfo.schema, version: undefined }, { ...this.getSchemaForType(profileType), version: undefined })) { - this.mExtendersJson.profileTypes[profileType] = { - version: typeInfo.schema.version, - from: typeMetadata.from.filter((src) => src !== typeInfo.sourceApp).concat([typeInfo.sourceApp]) + !lodash.isEqual(typeInfo.schema, this.getSchemaForType(profileType))) { + return { + success: false, + info: `Both the old and new schemas are unversioned for ${profileType}, but the schemas are different. `.concat( + "The new schema was not written to disk, but will still be accessible in-memory.") }; - this.updateSchemaAtLayer(profileType, typeInfo.schema, true); } } } else { From 2e07dfd925379931f31ffa97af0868998ab4b05f Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 23 Jan 2024 13:20:18 -0500 Subject: [PATCH 56/92] feat: add helper fn to verify whether a schema was loaded Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index dc398da9a3..9806b6fdd2 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -157,6 +157,8 @@ export class ProfileInfo { private mOldSchoolProfileDefaults: { [key: string]: string } = null; private mOldSchoolProfileTypes: string[]; private mOverrideWithEnv: boolean = false; + + private mHasValidSchema: boolean = false; /** * Cache of profile schema objects mapped by profile type and config path * if applicable. Examples of map keys: @@ -1008,6 +1010,13 @@ export class ProfileInfo { return this.mUsingTeamConfig; } + /** + * Returns whether a valid schema was found (works for v1 and v2 configs) + */ + public get hasValidSchema(): boolean { + return this.mHasValidSchema; + } + /** * Gather information about the paths in osLoc * @param profile Profile attributes gathered from getAllProfiles @@ -1216,11 +1225,14 @@ export class ProfileInfo { } } } + + this.mHasValidSchema = lastSchema.path != null; } else { // Load profile schemas from meta files in profile root dir for (const type of this.mOldSchoolProfileTypes) { const metaPath = this.oldProfileFilePath(type, type + AbstractProfileManager.META_FILE_SUFFIX); if (fs.existsSync(metaPath)) { + this.mHasValidSchema = true; try { const metaProfile = ProfileIO.readMetaFile(metaPath); this.mProfileSchemaCache.set(type, metaProfile.configuration.schema); From 7206c65f68de22a522accaa077dc216e8ac383e4 Mon Sep 17 00:00:00 2001 From: zowe-robot Date: Fri, 26 Jan 2024 19:55:11 +0000 Subject: [PATCH 57/92] Bump version to 7.23.0 [ci skip] Signed-off-by: zowe-robot --- .../__packages__/cli-test-utils/package.json | 4 +- lerna.json | 2 +- npm-shrinkwrap.json | 206 +++++++++--------- packages/cli/CHANGELOG.md | 2 +- packages/cli/package.json | 26 +-- packages/core/package.json | 6 +- packages/imperative/CHANGELOG.md | 2 +- packages/imperative/package.json | 2 +- packages/provisioning/package.json | 8 +- packages/workflows/package.json | 10 +- packages/zosconsole/package.json | 8 +- packages/zosfiles/package.json | 10 +- packages/zosjobs/package.json | 10 +- packages/zoslogs/package.json | 8 +- packages/zosmf/package.json | 8 +- packages/zostso/package.json | 10 +- packages/zosuss/package.json | 6 +- 17 files changed, 164 insertions(+), 164 deletions(-) diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index 3b0830ce7f..bd6afe0b2c 100644 --- a/__tests__/__packages__/cli-test-utils/package.json +++ b/__tests__/__packages__/cli-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli-test-utils", - "version": "7.22.0", + "version": "7.23.0", "description": "Test utilities package for Zowe CLI plug-ins", "author": "Zowe", "license": "EPL-2.0", @@ -43,7 +43,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.21.0" + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" diff --git a/lerna.json b/lerna.json index fbfd4eccc2..3de5537bce 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "7.22.0", + "version": "7.23.0", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 983ffe9cb8..3190874ea2 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -51,7 +51,7 @@ }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", @@ -62,7 +62,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.21.0" + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" @@ -24604,21 +24604,21 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "7.22.0", + "version": "7.23.0", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/provisioning-for-zowe-sdk": "7.22.0", - "@zowe/zos-console-for-zowe-sdk": "7.22.0", - "@zowe/zos-files-for-zowe-sdk": "7.22.0", - "@zowe/zos-jobs-for-zowe-sdk": "7.22.0", - "@zowe/zos-logs-for-zowe-sdk": "7.22.0", - "@zowe/zos-tso-for-zowe-sdk": "7.22.0", - "@zowe/zos-uss-for-zowe-sdk": "7.22.0", - "@zowe/zos-workflows-for-zowe-sdk": "7.22.0", - "@zowe/zosmf-for-zowe-sdk": "7.22.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/provisioning-for-zowe-sdk": "7.23.0", + "@zowe/zos-console-for-zowe-sdk": "7.23.0", + "@zowe/zos-files-for-zowe-sdk": "7.23.0", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.0", + "@zowe/zos-logs-for-zowe-sdk": "7.23.0", + "@zowe/zos-tso-for-zowe-sdk": "7.23.0", + "@zowe/zos-uss-for-zowe-sdk": "7.23.0", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.0", + "@zowe/zosmf-for-zowe-sdk": "7.23.0", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -24633,7 +24633,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.22.0", + "@zowe/cli-test-utils": "7.23.0", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" @@ -24666,15 +24666,15 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "dependencies": { "comment-json": "4.1.1", "string-width": "4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" @@ -24682,7 +24682,7 @@ }, "packages/imperative": { "name": "@zowe/imperative", - "version": "5.21.0", + "version": "5.22.0", "license": "EPL-2.0", "dependencies": { "@types/yargs": "13.0.4", @@ -25019,16 +25019,16 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "dependencies": { "js-yaml": "4.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25050,15 +25050,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.22.0" + "@zowe/zos-files-for-zowe-sdk": "7.23.0" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25067,12 +25067,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25081,17 +25081,17 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "dependencies": { "get-stream": "6.0.1", "minimatch": "5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/zos-uss-for-zowe-sdk": "7.22.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/zos-uss-for-zowe-sdk": "7.23.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25119,15 +25119,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.22.0" + "@zowe/zos-files-for-zowe-sdk": "7.23.0" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25136,12 +25136,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25150,12 +25150,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25164,15 +25164,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.22.0" + "@zowe/zosmf-for-zowe-sdk": "7.23.0" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25181,15 +25181,15 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "license": "EPL-2.0", "dependencies": { "ssh2": "1.15.0" }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/imperative": "^5.2.0" @@ -31839,19 +31839,19 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/provisioning-for-zowe-sdk": "7.22.0", + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/provisioning-for-zowe-sdk": "7.23.0", "@zowe/secrets-for-zowe-sdk": "7.18.6", - "@zowe/zos-console-for-zowe-sdk": "7.22.0", - "@zowe/zos-files-for-zowe-sdk": "7.22.0", - "@zowe/zos-jobs-for-zowe-sdk": "7.22.0", - "@zowe/zos-logs-for-zowe-sdk": "7.22.0", - "@zowe/zos-tso-for-zowe-sdk": "7.22.0", - "@zowe/zos-uss-for-zowe-sdk": "7.22.0", - "@zowe/zos-workflows-for-zowe-sdk": "7.22.0", - "@zowe/zosmf-for-zowe-sdk": "7.22.0", + "@zowe/zos-console-for-zowe-sdk": "7.23.0", + "@zowe/zos-files-for-zowe-sdk": "7.23.0", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.0", + "@zowe/zos-logs-for-zowe-sdk": "7.23.0", + "@zowe/zos-tso-for-zowe-sdk": "7.23.0", + "@zowe/zos-uss-for-zowe-sdk": "7.23.0", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.0", + "@zowe/zosmf-for-zowe-sdk": "7.23.0", "comment-json": "^4.1.1", "find-process": "1.4.7", "get-stream": "6.0.1", @@ -31885,7 +31885,7 @@ "requires": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.21.0", + "@zowe/imperative": "5.22.0", "find-up": "^5.0.0", "js-yaml": "^4.0.0", "rimraf": "^3.0.2", @@ -31905,8 +31905,8 @@ "@zowe/core-for-zowe-sdk": { "version": "file:packages/core", "requires": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/imperative": "5.21.0", + "@zowe/cli-test-utils": "7.23.0", + "@zowe/imperative": "5.22.0", "comment-json": "4.1.1", "string-width": "4.2.3" } @@ -32160,9 +32160,9 @@ "version": "file:packages/provisioning", "requires": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", "js-yaml": "4.1.0" } }, @@ -32176,18 +32176,18 @@ "@zowe/zos-console-for-zowe-sdk": { "version": "file:packages/zosconsole", "requires": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" } }, "@zowe/zos-files-for-zowe-sdk": { "version": "file:packages/zosfiles", "requires": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/zos-uss-for-zowe-sdk": "7.22.0", + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/zos-uss-for-zowe-sdk": "7.23.0", "get-stream": "6.0.1", "minimatch": "5.0.1" }, @@ -32213,53 +32213,53 @@ "@zowe/zos-jobs-for-zowe-sdk": { "version": "file:packages/zosjobs", "requires": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/zos-files-for-zowe-sdk": "7.22.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/zos-files-for-zowe-sdk": "7.23.0" } }, "@zowe/zos-logs-for-zowe-sdk": { "version": "file:packages/zoslogs", "requires": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" } }, "@zowe/zos-tso-for-zowe-sdk": { "version": "file:packages/zostso", "requires": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/zosmf-for-zowe-sdk": "7.22.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/zosmf-for-zowe-sdk": "7.23.0" } }, "@zowe/zos-uss-for-zowe-sdk": { "version": "file:packages/zosuss", "requires": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.22.0", - "@zowe/imperative": "5.21.0", + "@zowe/cli-test-utils": "7.23.0", + "@zowe/imperative": "5.22.0", "ssh2": "1.15.0" } }, "@zowe/zos-workflows-for-zowe-sdk": { "version": "file:packages/workflows", "requires": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/zos-files-for-zowe-sdk": "7.22.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/zos-files-for-zowe-sdk": "7.23.0" } }, "@zowe/zosmf-for-zowe-sdk": { "version": "file:packages/zosmf", "requires": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" } }, "abbrev": { diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 21ca1e8775..bf3300f8d0 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Zowe CLI package will be documented in this file. -## Recent Changes +## `7.23.0` - BugFix: Update zos-files copy dsclp system tests to include large mock files. diff --git a/packages/cli/package.json b/packages/cli/package.json index b47e544c38..cb75cb3314 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", "license": "EPL-2.0", @@ -58,17 +58,17 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/provisioning-for-zowe-sdk": "7.22.0", - "@zowe/zos-console-for-zowe-sdk": "7.22.0", - "@zowe/zos-files-for-zowe-sdk": "7.22.0", - "@zowe/zos-jobs-for-zowe-sdk": "7.22.0", - "@zowe/zos-logs-for-zowe-sdk": "7.22.0", - "@zowe/zos-tso-for-zowe-sdk": "7.22.0", - "@zowe/zos-uss-for-zowe-sdk": "7.22.0", - "@zowe/zos-workflows-for-zowe-sdk": "7.22.0", - "@zowe/zosmf-for-zowe-sdk": "7.22.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/provisioning-for-zowe-sdk": "7.23.0", + "@zowe/zos-console-for-zowe-sdk": "7.23.0", + "@zowe/zos-files-for-zowe-sdk": "7.23.0", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.0", + "@zowe/zos-logs-for-zowe-sdk": "7.23.0", + "@zowe/zos-tso-for-zowe-sdk": "7.23.0", + "@zowe/zos-uss-for-zowe-sdk": "7.23.0", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.0", + "@zowe/zosmf-for-zowe-sdk": "7.23.0", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -79,7 +79,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.22.0", + "@zowe/cli-test-utils": "7.23.0", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" diff --git a/packages/core/package.json b/packages/core/package.json index 04efbf5ba2..c544c291ea 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Core libraries shared by Zowe SDK packages", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ "string-width": "4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 1307cea1af..b1aac3a280 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Imperative package will be documented in this file. -## Recent Changes +## `5.22.0` - BugFix: Updated `mustache` and `jsonschema` dependencies for technical currency. - Enhancement: Added multiple APIs to the `ProfileInfo` class to help manage schemas between client applications. [#2012](https://github.com/zowe/zowe-cli/issues/2012) diff --git a/packages/imperative/package.json b/packages/imperative/package.json index 59ee9a8d12..1fe9586e77 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "5.21.0", + "version": "5.22.0", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index e606a88a09..4c6a8e9ebf 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with the z/OS provisioning APIs", "author": "Zowe", "license": "EPL-2.0", @@ -49,9 +49,9 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/workflows/package.json b/packages/workflows/package.json index a8a05beb07..8f5777ce17 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.22.0" + "@zowe/zos-files-for-zowe-sdk": "7.23.0" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index 1c20c0a8d9..94c2bfe221 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with the z/OS console", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index 0ed2345fd6..05dd84e3ce 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -50,10 +50,10 @@ "minimatch": "5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0", - "@zowe/zos-uss-for-zowe-sdk": "7.22.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0", + "@zowe/zos-uss-for-zowe-sdk": "7.23.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index 9d2fc99fef..a2c4449814 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,12 +46,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.22.0" + "@zowe/zos-files-for-zowe-sdk": "7.23.0" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index 2cf3c794d6..f4f84d7ec9 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with the z/OS logs", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index 3a67ab1795..cf870b56fa 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with the z/OS Management Facility", "author": "Zowe", "license": "EPL-2.0", @@ -44,9 +44,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zostso/package.json b/packages/zostso/package.json index 1779a26b05..46b187a41c 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with TSO on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.22.0" + "@zowe/zosmf-for-zowe-sdk": "7.23.0" }, "devDependencies": { - "@zowe/cli-test-utils": "7.22.0", - "@zowe/core-for-zowe-sdk": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index 78cced0b31..a8d8c4d6e5 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.22.0", + "version": "7.23.0", "description": "Zowe SDK to interact with USS on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.22.0", - "@zowe/imperative": "5.21.0" + "@zowe/cli-test-utils": "7.23.0", + "@zowe/imperative": "5.22.0" }, "peerDependencies": { "@zowe/imperative": "^5.2.0" From 51159da5e5560026d6ebad1431d8c05187138b1d Mon Sep 17 00:00:00 2001 From: Amber Torrise Date: Mon, 29 Jan 2024 10:33:23 -0500 Subject: [PATCH 58/92] copying over changes from v3, still need to update tests Signed-off-by: Amber Torrise --- packages/cli/CHANGELOG.md | 6 +- .../__unit__/edit/Edit.utils.unit.test.ts | 128 +++++++++++++----- packages/cli/src/zosfiles/-strings-/en.ts | 12 +- .../cli/src/zosfiles/edit/Edit.handler.ts | 2 + .../cli/src/zosfiles/edit/Edit.options.ts | 28 +++- packages/cli/src/zosfiles/edit/Edit.utils.ts | 6 +- .../zosfiles/edit/ds/Dataset.definition.ts | 10 +- .../zosfiles/edit/uss/USSFile.definition.ts | 12 +- 8 files changed, 155 insertions(+), 49 deletions(-) diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index bf3300f8d0..8d4e86d8ab 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,9 +2,13 @@ All notable changes to the Zowe CLI package will be documented in this file. +## Recent Changes + +- Enhancement: Adding `--binary` and `--encoding` options to `zosfiles edit` to zowe V2 + ## `7.23.0` -- BugFix: Update zos-files copy dsclp system tests to include large mock files. +- BugFix: Update zos-files copy dsclp system tests to include large mock files. ## `7.22.0` diff --git a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts index 84297fedf4..e85b2a45e2 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts @@ -46,6 +46,7 @@ describe("Files Edit Utilities", () => { guiAvail: true, zosResp: null, encoding: null, + binary: null, conflict: false }; @@ -56,6 +57,7 @@ describe("Files Edit Utilities", () => { guiAvail: true, zosResp: null, encoding: null, + binary: null, conflict: false }; @@ -206,41 +208,7 @@ describe("Files Edit Utilities", () => { }); }); }); - describe("localDownload()", () => { - jest.spyOn(EditUtilities, "destroyTempFile").mockImplementation(jest.fn()); - const downloadDataSetSpy = jest.spyOn(Download, "dataSet"); - const downloadUssFileSpy = jest.spyOn(Download, "ussFile"); - it("should apply etag from remote to ILocalFile without overwriting stash - [fileType = 'uss', useStash = true]", async () => { - //TEST SETUP - downloadUssFileSpy.mockImplementation(jest.fn(async () => { - return zosResp; - })); - - //TEST CONFIRMATION - //test that lfFile etag is the same as remote - //test that lfFile contents are different from remote (wrote to temp location & called destroyTemp) - const response = await EditUtilities.localDownload(REAL_SESSION, localFileUSS, true); - expect(response.zosResp?.apiResponse.etag).toContain('remote etag'); - expect(EditUtilities.destroyTempFile).toHaveBeenCalledTimes(1); - }); - it("should download etag and copy of remote - [fileType = 'ds', useStash = false]", async () => { - //TEST SETUP - //download (to temp) AND grab etag - const localFile = cloneDeep(localFileDS); - localFile.tempPath = "temp"; - downloadDataSetSpy.mockImplementation(jest.fn(async () => { - return zosResp; - })); - - //TEST CONFIRMATION - //test that lfFile etag is the same as remote - //test that lfFile contents are the same as remote (did not write to temp location) - const response = await EditUtilities.localDownload(REAL_SESSION, localFile, false); - expect(response.zosResp?.apiResponse.etag).toContain('remote etag'); - expect(EditUtilities.destroyTempFile).toHaveBeenCalledTimes(0); - }); - }); describe("fileComparison()", () => { const guiAvailSpy = jest.spyOn(ProcessUtils, "isGuiAvailable"); const getFile1Spy = jest.spyOn(LocalfileDatasetHandler.prototype, "getFile1"); @@ -354,6 +322,98 @@ describe("Files Edit Utilities", () => { }); }); describe("uploadEdits()", () => { + it("should successfully pass binary option when uploading - ds", async () => { + //TEST SETUP + const localFile = cloneDeep(localFileDS); + localFile.zosResp = zosResp; + localFile.zosResp.apiResponse.encoding = "matching etag"; + localFile.binary = true; + const UploadSpy = jest.spyOn(Upload, "fileToDataset").mockImplementation(async() => { + return zosResp; + }); + jest.spyOn(EditUtilities, "makeEdits").mockImplementation(async () => { + return true; + }); + jest.spyOn(EditUtilities, "destroyTempFile").mockImplementation(); + + //TEST CONFIRMATION + await EditUtilities.uploadEdits(REAL_SESSION, commandParametersDs, localFile); + expect(UploadSpy).toHaveBeenCalledWith( + undefined, + null, + "TEST(DS)", + expect.objectContaining({ binary: true }) + ); + }); + it("should successfully pass binary option when uploading - uss", async () => { + //TEST SETUP + const localFile = cloneDeep(localFileUSS); + localFile.zosResp = zosResp; + localFile.zosResp.apiResponse.etag = "etag"; + localFile.binary = true; + const UploadSpy = jest.spyOn(Upload, "fileToUssFile").mockImplementation(async() => { + return zosResp; + }); + jest.spyOn(EditUtilities, "makeEdits").mockImplementation(async () => { + return true; + }); + jest.spyOn(EditUtilities, "destroyTempFile").mockImplementation(); + + //TEST CONFIRMATION + await EditUtilities.uploadEdits(REAL_SESSION, commandParametersDs, localFile); + expect(UploadSpy).toHaveBeenCalledWith( + undefined, + null, + "test_uss.jcl", + expect.objectContaining({ binary: true }) + ); + }); + it("should successfully pass encoding option when uploading - ds", async () => { + //TEST SETUP + const localFile = cloneDeep(localFileDS); + localFile.zosResp = zosResp; + localFile.zosResp.apiResponse.encoding = "matching etag"; + localFile.encoding = "1047"; + jest.spyOn(Upload, "fileToDataset").mockImplementation(async() => { + return zosResp; + }); + jest.spyOn(EditUtilities, "makeEdits").mockImplementation(async () => { + return true; + }); + jest.spyOn(EditUtilities, "destroyTempFile").mockImplementation(); + + //TEST CONFIRMATION + await EditUtilities.uploadEdits(REAL_SESSION, commandParametersDs, localFile); + expect(Upload.fileToDataset).toHaveBeenCalledWith( + undefined, + null, + "TEST(DS)", + expect.objectContaining({ encoding: "1047" }) + ); + }); + it("should successfully pass encoding option when uploading - uss", async () => { + //TEST SETUP + const localFile = cloneDeep(localFileUSS); + localFile.zosResp = zosResp; + localFile.zosResp.apiResponse.etag = "etag"; + localFile.encoding = "1047"; + const UploadSpy = jest.spyOn(Upload, "fileToUssFile").mockImplementation(async() => { + return zosResp; + }); + jest.spyOn(EditUtilities, "makeEdits").mockImplementation(async () => { + return true; + }); + jest.spyOn(EditUtilities, "destroyTempFile").mockImplementation(); + + //TEST CONFIRMATION + await EditUtilities.uploadEdits(REAL_SESSION, commandParametersDs, localFile); + expect(UploadSpy).toHaveBeenCalledWith( + undefined, + null, + "test_uss.jcl", + expect.objectContaining({ encoding: "1047" }) + ); + }); it("should successfully upload when etags are matching, then destroy temp - uss", async () => { //TEST SETUP const localFile = cloneDeep(localFileUSS); diff --git a/packages/cli/src/zosfiles/-strings-/en.ts b/packages/cli/src/zosfiles/-strings-/en.ts index 6f9563b562..461c0b0274 100644 --- a/packages/cli/src/zosfiles/-strings-/en.ts +++ b/packages/cli/src/zosfiles/-strings-/en.ts @@ -767,7 +767,8 @@ export default { }, EXAMPLES: { EX1: `Edit the contents of the data set member "ibmuser.cntl(iefbr14)"`, - EX2: `Edit the contents of the USS file "ibmuser.jcl(iefbr14)" and set extension as "jcl"`, + EX2: `Edit the contents of the data set member "ibmuser.jcl(iefbr14)" and set extension as "jcl"`, + EX3: `Edit the contents of the data set member "ibmuser.jcl(iefbr14)" with binary flag set`, } }, USS_FILE: { @@ -778,15 +779,18 @@ export default { }, EXAMPLES: { EX1: `Edit the contents of the USS file "/a/ibmuser/my_text.txt" in notepad`, - EX2: `Edit the contents of the USS file "/a/ibmuser/my_jcl.jcl" in notepad and set extension as "jcl"`, + EX2: `Edit the contents of the USS file "/a/ibmuser/my_jcl.jcl" with binary flag set`, } } }, OPTIONS: { - EDITOR: `Set the default editor that you wish to use for editing. Set the option to the editor's executable file location ` + + EDITOR: `Editor that overrides the default editor for this file type. Set the option to the editor's executable file location ` + `or the program's name: ie "--editor notepad"`, EXTENSION: `Set the file extension of the file for editing to leverage an editor's file-type-specific formatting: ` + - `ie "--extension jcl"` + `ie "--extension jcl"`, + BINARY: "Transfer the file content in binary mode (no EBCDIC to ASCII conversion).", + ENCODING: "Transfer the file content with encoding mode, which means that data conversion is performed using the file encoding " + + "specified." } }, COMPARE: { diff --git a/packages/cli/src/zosfiles/edit/Edit.handler.ts b/packages/cli/src/zosfiles/edit/Edit.handler.ts index 87161fcc52..065e74e11a 100644 --- a/packages/cli/src/zosfiles/edit/Edit.handler.ts +++ b/packages/cli/src/zosfiles/edit/Edit.handler.ts @@ -28,6 +28,8 @@ export default class EditHandler extends ZosFilesBaseHandler { fileType: commandParameters.positionals[2].includes('d') ? "ds" : "uss", guiAvail: ProcessUtils.isGuiAvailable() === GuiResult.GUI_AVAILABLE, conflict: false, + encoding: commandParameters.arguments.encoding, + binary: commandParameters.arguments.binary, zosResp: null }; lfFile.tempPath = commandParameters.arguments.localFilePath = await Utils.buildTempPath(lfFile, commandParameters); diff --git a/packages/cli/src/zosfiles/edit/Edit.options.ts b/packages/cli/src/zosfiles/edit/Edit.options.ts index 7d14cd8998..8289f9b12a 100644 --- a/packages/cli/src/zosfiles/edit/Edit.options.ts +++ b/packages/cli/src/zosfiles/edit/Edit.options.ts @@ -32,6 +32,10 @@ export const EditOptions: { [key: string]: ICommandOptionDefinition } = { type: "string", required: false }, + /** + * The option to label your file's data type + * @type {ICommandOptionDefinition} + */ extension: { name: "extension", aliases: ["ext"], @@ -39,4 +43,26 @@ export const EditOptions: { [key: string]: ICommandOptionDefinition } = { type: "string", required: false }, -}; + /** + * The binary option + * @type {ICommandOptionDefinition} + */ + binary: { + name: "binary", + aliases: ["b"], + description: strings.BINARY, + type: "boolean" + }, + + /** + * The encoding option + * @type {ICommandOptionDefinition} + */ + encoding: { + name: "encoding", + aliases: ["ec"], + description: strings.ENCODING, + type: "string", + conflictsWith: ["binary"] + }, +}; \ No newline at end of file diff --git a/packages/cli/src/zosfiles/edit/Edit.utils.ts b/packages/cli/src/zosfiles/edit/Edit.utils.ts index dac8df3f00..024315c6e1 100644 --- a/packages/cli/src/zosfiles/edit/Edit.utils.ts +++ b/packages/cli/src/zosfiles/edit/Edit.utils.ts @@ -53,6 +53,7 @@ export interface ILocalFile { zosResp: IZosFilesResponse | null; conflict: boolean; encoding?: string | null; + binary?: boolean; } /** @@ -158,8 +159,8 @@ export class EditUtilities { lfFile.fileName, { returnEtag: true, - binary: null, - encoding: null, + binary: lfFile.binary, + encoding: lfFile.encoding, file: tempPath } ]; @@ -272,6 +273,7 @@ export class EditUtilities { lfFile.tempPath, lfFile.fileName, { + binary: lfFile.binary, encoding: lfFile.encoding, etag: lfFile.zosResp.apiResponse.etag, returnEtag: true diff --git a/packages/cli/src/zosfiles/edit/ds/Dataset.definition.ts b/packages/cli/src/zosfiles/edit/ds/Dataset.definition.ts index 8648e5ce70..32eb70f06f 100644 --- a/packages/cli/src/zosfiles/edit/ds/Dataset.definition.ts +++ b/packages/cli/src/zosfiles/edit/ds/Dataset.definition.ts @@ -40,7 +40,9 @@ export const DatasetDefinition: ICommandDefinition = { ], options: [ EditOptions.editor, - EditOptions.extension + EditOptions.extension, + EditOptions.binary, + EditOptions.encoding, ], examples: [ { @@ -52,8 +54,8 @@ export const DatasetDefinition: ICommandDefinition = { options: `ibmuser.cntl(iefbr14) --editor C:\\Windows\\System32\\Notepad.exe` }, { - description: strings.ACTIONS.USS_FILE.EXAMPLES.EX2, - options: `ibmuser.jcl(iefbr14) --editor notepad --extension jcl` + description: strings.ACTIONS.DATA_SET.EXAMPLES.EX2, + options: `ibmuser.jcl(iefbr14) --binary` } ] -}; +}; \ No newline at end of file diff --git a/packages/cli/src/zosfiles/edit/uss/USSFile.definition.ts b/packages/cli/src/zosfiles/edit/uss/USSFile.definition.ts index e0a3016b72..7743a225ec 100644 --- a/packages/cli/src/zosfiles/edit/uss/USSFile.definition.ts +++ b/packages/cli/src/zosfiles/edit/uss/USSFile.definition.ts @@ -39,7 +39,9 @@ export const USSFileDefinition: ICommandDefinition = { }, ], options: [ - EditOptions.editor + EditOptions.editor, + EditOptions.binary, + EditOptions.encoding ], examples: [ { @@ -49,6 +51,10 @@ export const USSFileDefinition: ICommandDefinition = { { description: strings.ACTIONS.USS_FILE.EXAMPLES.EX1, options: `/a/ibmuser/my_text.txt --editor C:\\Windows\\System32\\Notepad.exe` - } + }, + { + description: strings.ACTIONS.USS_FILE.EXAMPLES.EX2, + options: `/a/ibmuser/my_text.txt --binary` + }, ] -}; +}; \ No newline at end of file From 26da48f79b8ef42451f5c5ddee57273163b900fa Mon Sep 17 00:00:00 2001 From: Amber Torrise Date: Mon, 29 Jan 2024 10:52:45 -0500 Subject: [PATCH 59/92] by updating tests i meant snapshots Signed-off-by: Amber Torrise --- .../edit.ds.integration.test.ts.snap | 24 ++++++++++++------ .../edit.uss.integration.test.ts.snap | 23 ++++++++++++++--- .../__unit__/edit/Edit.utils.unit.test.ts | 2 +- .../Dataset.definition.unit.test.ts.snap | 25 ++++++++++++++++--- .../UssFile.definition.unit.test.ts.snap | 25 ++++++++++++++++++- .../utilities/npm-interface/uninstall.ts | 2 +- 6 files changed, 84 insertions(+), 17 deletions(-) diff --git a/packages/cli/__tests__/zosfiles/__integration__/edit/ds/__snapshots__/edit.ds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/edit/ds/__snapshots__/edit.ds.integration.test.ts.snap index d055f15c7a..3a5cb005f3 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/edit/ds/__snapshots__/edit.ds.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/edit/ds/__snapshots__/edit.ds.integration.test.ts.snap @@ -30,14 +30,24 @@ exports[`Edit Data Set should display the help 1`] = ` --editor | --ed (string) - Set the default editor that you wish to use for editing. Set the option to the - editor's executable file location or the program's name: ie \\"--editor notepad\\" + Editor that overrides the default editor for this file type. Set the option to + the editor's executable file location or the program's name: ie \\"--editor + notepad\\" --extension | --ext (string) Set the file extension of the file for editing to leverage an editor's file-type-specific formatting: ie \\"--extension jcl\\" + --binary | -b (boolean) + + Transfer the file content in binary mode (no EBCDIC to ASCII conversion). + + --encoding | --ec (string) + + Transfer the file content with encoding mode, which means that data conversion + is performed using the file encoding specified. + --response-timeout | --rto (number) The maximum amount of time in seconds the z/OSMF Files TSO servlet should run @@ -147,10 +157,10 @@ exports[`Edit Data Set should display the help 1`] = ` $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor C:\\\\Windows\\\\System32\\\\Notepad.exe - - Edit the contents of the USS file \\"/a/ibmuser/my_jcl.jcl\\" - in notepad and set extension as \\"jcl\\": + - Edit the contents of the data set member + \\"ibmuser.jcl(iefbr14)\\" and set extension as \\"jcl\\": - $ zowe zos-files edit data-set ibmuser.jcl(iefbr14) --editor notepad --extension jcl + $ zowe zos-files edit data-set ibmuser.jcl(iefbr14) --binary " `; @@ -161,8 +171,8 @@ exports[`Edit Data Set should display the help in json format 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Edit content from a z/OS data set with your terminal and default editor.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files edit data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set you want to edit.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Set the default editor that you wish to use for editing. Set the option to the\\\\n editor's executable file location or the program's name: ie \\\\\\"--editor notepad\\\\\\"\\\\n\\\\n --extension | --ext (string)\\\\n\\\\n Set the file extension of the file for editing to leverage an editor's\\\\n file-type-specific formatting: ie \\\\\\"--extension jcl\\\\\\"\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.cntl(iefbr14)\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor notepad\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.cntl(iefbr14)\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor C:\\\\\\\\Windows\\\\\\\\System32\\\\\\\\Notepad.exe\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_jcl.jcl\\\\\\"\\\\n in notepad and set extension as \\\\\\"jcl\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.jcl(iefbr14) --editor notepad --extension jcl\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Edit content from a z/OS data set with your terminal and default editor.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files edit data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set you want to edit.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Editor that overrides the default editor for this file type. Set the option to\\\\n the editor's executable file location or the program's name: ie \\\\\\"--editor\\\\n notepad\\\\\\"\\\\n\\\\n --extension | --ext (string)\\\\n\\\\n Set the file extension of the file for editing to leverage an editor's\\\\n file-type-specific formatting: ie \\\\\\"--extension jcl\\\\\\"\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Transfer the file content in binary mode (no EBCDIC to ASCII conversion).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Transfer the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.cntl(iefbr14)\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor notepad\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.cntl(iefbr14)\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor C:\\\\\\\\Windows\\\\\\\\System32\\\\\\\\Notepad.exe\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.jcl(iefbr14)\\\\\\" and set extension as \\\\\\"jcl\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.jcl(iefbr14) --binary\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Edit content from a z/OS data set with your terminal and default editor.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files edit data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set you want to edit.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Set the default editor that you wish to use for editing. Set the option to the\\\\n editor's executable file location or the program's name: ie \\\\\\"--editor notepad\\\\\\"\\\\n\\\\n --extension | --ext (string)\\\\n\\\\n Set the file extension of the file for editing to leverage an editor's\\\\n file-type-specific formatting: ie \\\\\\"--extension jcl\\\\\\"\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.cntl(iefbr14)\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor notepad\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.cntl(iefbr14)\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor C:\\\\\\\\Windows\\\\\\\\System32\\\\\\\\Notepad.exe\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_jcl.jcl\\\\\\"\\\\n in notepad and set extension as \\\\\\"jcl\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.jcl(iefbr14) --editor notepad --extension jcl\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Edit content from a z/OS data set with your terminal and default editor.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files edit data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set you want to edit.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Editor that overrides the default editor for this file type. Set the option to\\\\n the editor's executable file location or the program's name: ie \\\\\\"--editor\\\\n notepad\\\\\\"\\\\n\\\\n --extension | --ext (string)\\\\n\\\\n Set the file extension of the file for editing to leverage an editor's\\\\n file-type-specific formatting: ie \\\\\\"--extension jcl\\\\\\"\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Transfer the file content in binary mode (no EBCDIC to ASCII conversion).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Transfer the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.cntl(iefbr14)\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor notepad\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.cntl(iefbr14)\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.cntl(iefbr14) --editor C:\\\\\\\\Windows\\\\\\\\System32\\\\\\\\Notepad.exe\\\\n\\\\n - Edit the contents of the data set member\\\\n \\\\\\"ibmuser.jcl(iefbr14)\\\\\\" and set extension as \\\\\\"jcl\\\\\\":\\\\n\\\\n $ zowe zos-files edit data-set ibmuser.jcl(iefbr14) --binary\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/edit/uss/__snapshots__/edit.uss.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/edit/uss/__snapshots__/edit.uss.integration.test.ts.snap index 15e586a88a..7ea83480bf 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/edit/uss/__snapshots__/edit.uss.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/edit/uss/__snapshots__/edit.uss.integration.test.ts.snap @@ -31,8 +31,18 @@ exports[`View USS file should display the help 1`] = ` --editor | --ed (string) - Set the default editor that you wish to use for editing. Set the option to the - editor's executable file location or the program's name: ie \\"--editor notepad\\" + Editor that overrides the default editor for this file type. Set the option to + the editor's executable file location or the program's name: ie \\"--editor + notepad\\" + + --binary | -b (boolean) + + Transfer the file content in binary mode (no EBCDIC to ASCII conversion). + + --encoding | --ec (string) + + Transfer the file content with encoding mode, which means that data conversion + is performed using the file encoding specified. --response-timeout | --rto (number) @@ -143,6 +153,11 @@ exports[`View USS file should display the help 1`] = ` $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor C:\\\\Windows\\\\System32\\\\Notepad.exe + - Edit the contents of the USS file \\"/a/ibmuser/my_jcl.jcl\\" + with binary flag set: + + $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --binary + " `; @@ -152,8 +167,8 @@ exports[`View USS file should display the help in json format 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: uss-file.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uss | uf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Edit content from a Unix System Services (USS) file with your terminal and\\\\n default editor.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files edit uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussFilePath\\\\t\\\\t (string)\\\\n\\\\n The path of the USS file you want to edit.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Set the default editor that you wish to use for editing. Set the option to the\\\\n editor's executable file location or the program's name: ie \\\\\\"--editor notepad\\\\\\"\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n in notepad:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor notepad\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n in notepad:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor C:\\\\\\\\Windows\\\\\\\\System32\\\\\\\\Notepad.exe\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uss | uf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Edit content from a Unix System Services (USS) file with your terminal and\\\\n default editor.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files edit uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussFilePath\\\\t\\\\t (string)\\\\n\\\\n The path of the USS file you want to edit.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Editor that overrides the default editor for this file type. Set the option to\\\\n the editor's executable file location or the program's name: ie \\\\\\"--editor\\\\n notepad\\\\\\"\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Transfer the file content in binary mode (no EBCDIC to ASCII conversion).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Transfer the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n in notepad:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor notepad\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n in notepad:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor C:\\\\\\\\Windows\\\\\\\\System32\\\\\\\\Notepad.exe\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_jcl.jcl\\\\\\"\\\\n with binary flag set:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --binary\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uss | uf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Edit content from a Unix System Services (USS) file with your terminal and\\\\n default editor.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files edit uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussFilePath\\\\t\\\\t (string)\\\\n\\\\n The path of the USS file you want to edit.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Set the default editor that you wish to use for editing. Set the option to the\\\\n editor's executable file location or the program's name: ie \\\\\\"--editor notepad\\\\\\"\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n in notepad:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor notepad\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n in notepad:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor C:\\\\\\\\Windows\\\\\\\\System32\\\\\\\\Notepad.exe\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uss | uf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Edit content from a Unix System Services (USS) file with your terminal and\\\\n default editor.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files edit uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussFilePath\\\\t\\\\t (string)\\\\n\\\\n The path of the USS file you want to edit.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Editor that overrides the default editor for this file type. Set the option to\\\\n the editor's executable file location or the program's name: ie \\\\\\"--editor\\\\n notepad\\\\\\"\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Transfer the file content in binary mode (no EBCDIC to ASCII conversion).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Transfer the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n in notepad:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor notepad\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n in notepad:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --editor C:\\\\\\\\Windows\\\\\\\\System32\\\\\\\\Notepad.exe\\\\n\\\\n - Edit the contents of the USS file \\\\\\"/a/ibmuser/my_jcl.jcl\\\\\\"\\\\n with binary flag set:\\\\n\\\\n $ zowe zos-files edit uss-file /a/ibmuser/my_text.txt --binary\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts index e85b2a45e2..c8a2991e38 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts @@ -16,7 +16,7 @@ import { EditDefinition } from "../../../../src/zosfiles/edit/Edit.definition"; import { EditUtilities, ILocalFile, Prompt } from "../../../../src/zosfiles/edit/Edit.utils"; import { cloneDeep } from "lodash"; import * as fs from "fs"; -import { Download, IZosFilesResponse, Upload } from "@zowe/zos-files-for-zowe-sdk"; +import { IZosFilesResponse, Upload } from "@zowe/zos-files-for-zowe-sdk"; import LocalfileDatasetHandler from "../../../../src/zosfiles/compare/lf-ds/LocalfileDataset.handler"; import { CompareBaseHelper } from "../../../../src/zosfiles/compare/CompareBaseHelper"; import LocalfileUssHandler from "../../../../src/zosfiles/compare/lf-uss/LocalfileUss.handler"; diff --git a/packages/cli/__tests__/zosfiles/__unit__/edit/ds/__snapshots__/Dataset.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/edit/ds/__snapshots__/Dataset.definition.unit.test.ts.snap index 5ccb0e2d52..13f97a5516 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/edit/ds/__snapshots__/Dataset.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/edit/ds/__snapshots__/Dataset.definition.unit.test.ts.snap @@ -6,7 +6,7 @@ Array [ "aliases": Array [ "ed", ], - "description": "Set the default editor that you wish to use for editing. Set the option to the editor's executable file location or the program's name: ie \\"--editor notepad\\"", + "description": "Editor that overrides the default editor for this file type. Set the option to the editor's executable file location or the program's name: ie \\"--editor notepad\\"", "name": "editor", "required": false, "type": "string", @@ -20,6 +20,25 @@ Array [ "required": false, "type": "string", }, + Object { + "aliases": Array [ + "b", + ], + "description": "Transfer the file content in binary mode (no EBCDIC to ASCII conversion).", + "name": "binary", + "type": "boolean", + }, + Object { + "aliases": Array [ + "ec", + ], + "conflictsWith": Array [ + "binary", + ], + "description": "Transfer the file content with encoding mode, which means that data conversion is performed using the file encoding specified.", + "name": "encoding", + "type": "string", + }, ] `; @@ -34,8 +53,8 @@ Array [ "options": "ibmuser.cntl(iefbr14) --editor C:\\\\Windows\\\\System32\\\\Notepad.exe", }, Object { - "description": "Edit the contents of the USS file \\"/a/ibmuser/my_jcl.jcl\\" in notepad and set extension as \\"jcl\\"", - "options": "ibmuser.jcl(iefbr14) --editor notepad --extension jcl", + "description": "Edit the contents of the data set member \\"ibmuser.jcl(iefbr14)\\" and set extension as \\"jcl\\"", + "options": "ibmuser.jcl(iefbr14) --binary", }, ] `; diff --git a/packages/cli/__tests__/zosfiles/__unit__/edit/uss/__snapshots__/UssFile.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/edit/uss/__snapshots__/UssFile.definition.unit.test.ts.snap index 3fe73a8c4e..4f3c0d3f2b 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/edit/uss/__snapshots__/UssFile.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/edit/uss/__snapshots__/UssFile.definition.unit.test.ts.snap @@ -6,11 +6,30 @@ Array [ "aliases": Array [ "ed", ], - "description": "Set the default editor that you wish to use for editing. Set the option to the editor's executable file location or the program's name: ie \\"--editor notepad\\"", + "description": "Editor that overrides the default editor for this file type. Set the option to the editor's executable file location or the program's name: ie \\"--editor notepad\\"", "name": "editor", "required": false, "type": "string", }, + Object { + "aliases": Array [ + "b", + ], + "description": "Transfer the file content in binary mode (no EBCDIC to ASCII conversion).", + "name": "binary", + "type": "boolean", + }, + Object { + "aliases": Array [ + "ec", + ], + "conflictsWith": Array [ + "binary", + ], + "description": "Transfer the file content with encoding mode, which means that data conversion is performed using the file encoding specified.", + "name": "encoding", + "type": "string", + }, ] `; @@ -24,5 +43,9 @@ Array [ "description": "Edit the contents of the USS file \\"/a/ibmuser/my_text.txt\\" in notepad", "options": "/a/ibmuser/my_text.txt --editor C:\\\\Windows\\\\System32\\\\Notepad.exe", }, + Object { + "description": "Edit the contents of the USS file \\"/a/ibmuser/my_jcl.jcl\\" with binary flag set", + "options": "/a/ibmuser/my_text.txt --binary", + }, ] `; diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index f3661a7687..c03909a690 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -62,7 +62,7 @@ export const updateAndGetRemovedTypes = (npmPackage: string): string[] => { } return typesToRemove; -} +}; /** * @TODO - allow multiple packages to be uninstalled? From c9e4c8d09839d5c25e4b539db9cf376e72587c91 Mon Sep 17 00:00:00 2001 From: Amber Torrise <112635587+ATorrise@users.noreply.github.com> Date: Mon, 29 Jan 2024 11:01:43 -0500 Subject: [PATCH 60/92] Update uninstall.ts to remove a linting fix that breaks my workflows Signed-off-by: Amber Torrise <112635587+ATorrise@users.noreply.github.com> --- .../imperative/src/plugins/utilities/npm-interface/uninstall.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index c03909a690..f3661a7687 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -62,7 +62,7 @@ export const updateAndGetRemovedTypes = (npmPackage: string): string[] => { } return typesToRemove; -}; +} /** * @TODO - allow multiple packages to be uninstalled? From 320ebb5e254c0892a2f47623c4a57a7463535d4a Mon Sep 17 00:00:00 2001 From: Amber Torrise <112635587+ATorrise@users.noreply.github.com> Date: Tue, 30 Jan 2024 12:05:43 -0500 Subject: [PATCH 61/92] Update Edit.utils.unit.test.ts Signed-off-by: Amber Torrise <112635587+ATorrise@users.noreply.github.com> --- .../__unit__/edit/Edit.utils.unit.test.ts | 117 +++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts index c8a2991e38..66370a903d 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts @@ -16,7 +16,7 @@ import { EditDefinition } from "../../../../src/zosfiles/edit/Edit.definition"; import { EditUtilities, ILocalFile, Prompt } from "../../../../src/zosfiles/edit/Edit.utils"; import { cloneDeep } from "lodash"; import * as fs from "fs"; -import { IZosFilesResponse, Upload } from "@zowe/zos-files-for-zowe-sdk"; +import { Download, IZosFilesResponse, Upload } from "@zowe/zos-files-for-zowe-sdk"; import LocalfileDatasetHandler from "../../../../src/zosfiles/compare/lf-ds/LocalfileDataset.handler"; import { CompareBaseHelper } from "../../../../src/zosfiles/compare/CompareBaseHelper"; import LocalfileUssHandler from "../../../../src/zosfiles/compare/lf-uss/LocalfileUss.handler"; @@ -208,7 +208,122 @@ describe("Files Edit Utilities", () => { }); }); }); + describe("localDownload()", () => { + jest.spyOn(EditUtilities, "destroyTempFile").mockImplementation(jest.fn()); + const downloadDataSetSpy = jest.spyOn(Download, "dataSet"); + const downloadUssFileSpy = jest.spyOn(Download, "ussFile"); + it("should apply etag from remote to ILocalFile without overwriting stash - [fileType = 'uss', useStash = true]", async () => { + //TEST SETUP + downloadUssFileSpy.mockImplementation(jest.fn(async () => { + return zosResp; + })); + + //TEST CONFIRMATION + //test that lfFile etag is the same as remote + //test that lfFile contents are different from remote (wrote to temp location & called destroyTemp) + const response = await EditUtilities.localDownload(REAL_SESSION, localFileUSS, true); + expect(response.zosResp?.apiResponse.etag).toContain('remote etag'); + expect(EditUtilities.destroyTempFile).toHaveBeenCalledTimes(1); + }); + + it("should download etag and copy of remote - [fileType = 'ds', useStash = false]", async () => { + //TEST SETUP + //download (to temp) AND grab etag + const localFile = cloneDeep(localFileDS); + localFile.tempPath = "temp"; + downloadDataSetSpy.mockImplementation(jest.fn(async () => { + return zosResp; + })); + + //TEST CONFIRMATION + //test that lfFile etag is the same as remote + //test that lfFile contents are the same as remote (did not write to temp location) + const response = await EditUtilities.localDownload(REAL_SESSION, localFile, false); + expect(response.zosResp?.apiResponse.etag).toContain('remote etag'); + expect(EditUtilities.destroyTempFile).toHaveBeenCalledTimes(0); + }); + + it("localDownload should properly pass non-falsy binary option to Download.dataSet", async () => { + //TEST SETUP + const localFile = cloneDeep(localFileDS); + localFile.binary = true; + downloadDataSetSpy.mockImplementation(jest.fn(async () => { + return zosResp; + })); + + //TEST CONFIRMATION + //test that binary option is passed to downloadDS + await EditUtilities.localDownload(REAL_SESSION, localFile, false); + expect(downloadDataSetSpy).toHaveBeenCalledTimes(1); + expect(downloadDataSetSpy).toHaveBeenCalledWith(undefined, "TEST(DS)", { + "binary": true, + "encoding": null, + "file": null, + "returnEtag": true + }); + }); + + it("localDownload should properly pass non-falsy encoding option to Download.dataSet", async () => { + //TEST SETUP + const localFile = cloneDeep(localFileDS); + localFile.encoding = "1047"; + downloadDataSetSpy.mockImplementation(jest.fn(async () => { + return zosResp; + })); + + //TEST CONFIRMATION + //test that encoding option is passed to downloadDS + await EditUtilities.localDownload(REAL_SESSION, localFile, false); + expect(downloadDataSetSpy).toHaveBeenCalledTimes(1); + expect(downloadDataSetSpy).toHaveBeenCalledWith(undefined, "TEST(DS)", { + "binary": null, + "encoding": "1047", + "file": null, + "returnEtag": true + }); + }); + + it("localDownload should properly pass non-falsy binary option to Download.ussFile", async () => { + //TEST SETUP + const localFile = cloneDeep(localFileUSS); + localFile.binary = true; + downloadUssFileSpy.mockImplementation(jest.fn(async () => { + return zosResp; + })); + + //TEST CONFIRMATION + //test that encoding option is passed to downloadDS + await EditUtilities.localDownload(REAL_SESSION, localFile, false); + expect(downloadUssFileSpy).toHaveBeenCalledTimes(1); + expect(downloadUssFileSpy).toHaveBeenCalledWith(undefined, "test_uss.jcl", { + "binary": true, + "encoding": null, + "file": null, + "returnEtag": true + }); + }); + + it("localDownload should properly pass non-falsy encoding option to Download.ussFile", async () => { + //TEST SETUP + const localFile = cloneDeep(localFileUSS); + localFile.encoding = "1047"; + downloadUssFileSpy.mockImplementation(jest.fn(async () => { + return zosResp; + })); + + //TEST CONFIRMATION + //test that encoding option is passed to downloadDS + await EditUtilities.localDownload(REAL_SESSION, localFile, false); + expect(downloadUssFileSpy).toHaveBeenCalledTimes(1); + expect(downloadUssFileSpy).toHaveBeenCalledWith(undefined, "test_uss.jcl", { + "binary": null, + "encoding": "1047", + "file": null, + "returnEtag": true + }); + }); + }); describe("fileComparison()", () => { const guiAvailSpy = jest.spyOn(ProcessUtils, "isGuiAvailable"); const getFile1Spy = jest.spyOn(LocalfileDatasetHandler.prototype, "getFile1"); From 8e0b70ea1bebe11098296438837f0fcd700bf93c Mon Sep 17 00:00:00 2001 From: Amber Torrise <112635587+ATorrise@users.noreply.github.com> Date: Tue, 30 Jan 2024 12:14:10 -0500 Subject: [PATCH 62/92] Update Edit.utils.unit.test.ts Signed-off-by: Amber Torrise <112635587+ATorrise@users.noreply.github.com> From 8e73cb5b59eceea8f8e09c90d8e47e96ff6d5b4d Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Tue, 30 Jan 2024 16:00:44 -0500 Subject: [PATCH 63/92] Add script to build offline tgz for CLI package Signed-off-by: Timothy Johnson --- package.json | 3 ++- scripts/bundleCliTgz.js | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 scripts/bundleCliTgz.js diff --git a/package.json b/package.json index 7f7a132acb..953f93846a 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "typedoc:packages": "lerna run --parallel typedoc", "audit:public": "npm audit --registry https://registry.npmjs.org/", "bundle:webHelp": "cd packages/imperative/web-help && node build.js", - "prepare": "husky install && npm run bundle:webHelp" + "prepare": "husky install && npm run bundle:webHelp", + "package": "node scripts/bundleCliTgz.js" }, "dependencies": {}, "devDependencies": { diff --git a/scripts/bundleCliTgz.js b/scripts/bundleCliTgz.js new file mode 100644 index 0000000000..ab06e9c232 --- /dev/null +++ b/scripts/bundleCliTgz.js @@ -0,0 +1,49 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +const childProcess = require("child_process"); +const fs = require("fs-extra"); +const path = require("path"); + +// Workaround for https://github.com/npm/cli/issues/3466 +process.chdir(__dirname + "/.."); +const cliPkgDir = path.join(process.cwd(), "packages", "cli"); +const pkgJsonFile = path.join(cliPkgDir, "package.json"); +const execCmd = (cmd) => childProcess.execSync(cmd, { cwd: cliPkgDir, stdio: "inherit" }); +fs.mkdirpSync("dist"); +fs.renameSync(path.join(cliPkgDir, "node_modules"), path.join(cliPkgDir, "node_modules_old")); +fs.copyFileSync(pkgJsonFile, pkgJsonFile + ".bak"); + +try { + // Install node_modules directly inside packages/cli + execCmd("npm run preshrinkwrap"); + execCmd("npm install --ignore-scripts --workspaces=false"); + for (const zowePkgDir of fs.readdirSync(path.join(cliPkgDir, "node_modules", "@zowe"))) { + const srcDir = path.join("node_modules", "@zowe", zowePkgDir); + const destDir = path.join(cliPkgDir, srcDir); + fs.rmSync(destDir, { recursive: true, force: true }); + fs.copySync(fs.realpathSync(srcDir), destDir); + } + + // Define bundled dependencies in package.json and package the TGZ + const pkgJson = JSON.parse(fs.readFileSync(pkgJsonFile, "utf-8")); + pkgJson.bundledDependencies = [ + ...Object.keys(pkgJson.dependencies), + ...Object.keys(pkgJson.optionalDependencies ?? {}) + ]; + fs.writeFileSync(pkgJsonFile, JSON.stringify(pkgJson, null, 2)); + execCmd("npm pack --pack-destination=../../dist"); +} finally { + fs.rmSync(path.join(cliPkgDir, "node_modules"), { recursive: true, force: true }); + fs.renameSync(path.join(cliPkgDir, "node_modules_old"), path.join(cliPkgDir, "node_modules")); + fs.rmSync(path.join(cliPkgDir, "npm-shrinkwrap.json"), { force: true }); + fs.renameSync(pkgJsonFile + ".bak", pkgJsonFile); +} From 3dcafb94544439678181936223768d44daac97f1 Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Tue, 30 Jan 2024 16:00:54 -0500 Subject: [PATCH 64/92] Add dist to gitignore and fix lint warning Signed-off-by: Timothy Johnson --- .gitignore | 1 + .../imperative/src/plugins/utilities/npm-interface/uninstall.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ce098d3bf2..c056f35af1 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ CCS141/ src/brightside.iml package-lock.json /packages/cli/npm-shrinkwrap.json +/dist/ # Sonar Files .sonar_lock .scannerwork/ diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index f3661a7687..c03909a690 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -62,7 +62,7 @@ export const updateAndGetRemovedTypes = (npmPackage: string): string[] => { } return typesToRemove; -} +}; /** * @TODO - allow multiple packages to be uninstalled? From 6eb0288858a888a4f332d20f66dd4d816a20493c Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Wed, 31 Jan 2024 14:14:33 +0000 Subject: [PATCH 65/92] Add ARM runner Signed-off-by: Andrew W. Harn --- .github/workflows/zowe-cli.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/zowe-cli.yml b/.github/workflows/zowe-cli.yml index d933e32e62..871ab243c0 100644 --- a/.github/workflows/zowe-cli.yml +++ b/.github/workflows/zowe-cli.yml @@ -28,7 +28,7 @@ jobs: fail-fast: false matrix: node-version: [18.x, 20.x] - os: [windows-latest, ubuntu-latest, macos-latest] + os: [windows-latest, ubuntu-latest, macos-latest, macos-14] env: OS: ${{ matrix.os }} From f4328b9ed6d631a17eeb6e3be81a975967eb888f Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Wed, 31 Jan 2024 16:43:45 +0000 Subject: [PATCH 66/92] Test change Signed-off-by: Andrew W. Harn --- .github/workflows/zowe-cli.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/zowe-cli.yml b/.github/workflows/zowe-cli.yml index 871ab243c0..62a355b529 100644 --- a/.github/workflows/zowe-cli.yml +++ b/.github/workflows/zowe-cli.yml @@ -16,6 +16,13 @@ on: description: Specify whether to run tests using the `binary` or regular `nodejs` executable default: binary required: false + macos-type: + type: choice + description: Run against x86-based MacOS (12), otherwise run against ARM64-based MacOS (14) + default: macos-14 + options: + - macos-12 + - macos-14 jobs: test: @@ -28,7 +35,7 @@ jobs: fail-fast: false matrix: node-version: [18.x, 20.x] - os: [windows-latest, ubuntu-latest, macos-latest, macos-14] + os: [windows-latest, ubuntu-latest, ${{ github.event.inputs.macos-type }}] env: OS: ${{ matrix.os }} From a30666e75562483d40fad4a7668db1b69875762f Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Wed, 31 Jan 2024 16:44:49 +0000 Subject: [PATCH 67/92] Attempt number 2 Signed-off-by: Andrew W. Harn --- .github/workflows/zowe-cli.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/zowe-cli.yml b/.github/workflows/zowe-cli.yml index 62a355b529..995be0113d 100644 --- a/.github/workflows/zowe-cli.yml +++ b/.github/workflows/zowe-cli.yml @@ -35,7 +35,10 @@ jobs: fail-fast: false matrix: node-version: [18.x, 20.x] - os: [windows-latest, ubuntu-latest, ${{ github.event.inputs.macos-type }}] + os: + - windows-latest + - ubuntu-latest + - ${{ github.event.inputs.macos-type }} env: OS: ${{ matrix.os }} From aa37c9ba7f8787bcc84af8596b89d6a529b9f689 Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Wed, 31 Jan 2024 16:47:00 +0000 Subject: [PATCH 68/92] Third time's the charm Signed-off-by: Andrew W. Harn --- .github/workflows/zowe-cli.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/zowe-cli.yml b/.github/workflows/zowe-cli.yml index 995be0113d..1885e9fedb 100644 --- a/.github/workflows/zowe-cli.yml +++ b/.github/workflows/zowe-cli.yml @@ -38,7 +38,7 @@ jobs: os: - windows-latest - ubuntu-latest - - ${{ github.event.inputs.macos-type }} + - ${{ github.event.inputs.macos-type || 'macos-14'}} env: OS: ${{ matrix.os }} From affa1e7fcde79c0508254ec75744a96d386a1835 Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Fri, 2 Feb 2024 14:03:02 +0000 Subject: [PATCH 69/92] Update CLI workflows to Node 20 versions Signed-off-by: Andrew W. Harn --- .github/workflows/audit.yml | 4 ++-- .github/workflows/auto-comment.yml | 2 +- .github/workflows/changelog.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/linter.yml | 4 ++-- .github/workflows/rust-cli-publish.yml | 2 +- .github/workflows/rust-cli.yml | 12 ++++++------ .github/workflows/secrets-sdk-publish.yml | 4 ++-- .github/workflows/secrets-sdk.yml | 18 +++++++++--------- .github/workflows/sonar.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/zowe-cli.yml | 14 +++++++------- 12 files changed, 34 insertions(+), 34 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index f8f5a43b4e..f20812b55e 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -15,10 +15,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Use Node.js LTS - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* diff --git a/.github/workflows/auto-comment.yml b/.github/workflows/auto-comment.yml index e5ac484317..1d707b5af8 100644 --- a/.github/workflows/auto-comment.yml +++ b/.github/workflows/auto-comment.yml @@ -9,7 +9,7 @@ jobs: name: Process Label Action runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Process Label Action uses: hramos/respond-to-issue-based-on-label@v2 diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 1b2f0ffb75..dbcf70835d 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 32b54d14ec..94718d6832 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 6b2375cb20..0fd38c2ad9 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -17,10 +17,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Use Node.js LTS - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* diff --git a/.github/workflows/rust-cli-publish.yml b/.github/workflows/rust-cli-publish.yml index 84309e5c5c..65901b6431 100644 --- a/.github/workflows/rust-cli-publish.yml +++ b/.github/workflows/rust-cli-publish.yml @@ -19,7 +19,7 @@ jobs: ZOWEX_VERSION: ${{ steps.get-version.outputs.ZOWEX_VERSION }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get version id: get-version diff --git a/.github/workflows/rust-cli.yml b/.github/workflows/rust-cli.yml index 97edb5c689..594cebf2bd 100644 --- a/.github/workflows/rust-cli.yml +++ b/.github/workflows/rust-cli.yml @@ -18,7 +18,7 @@ jobs: if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) && !contains(github.event.head_commit.message, '[ci skip]') steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable @@ -41,7 +41,7 @@ jobs: - name: Archive Results id: upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: zowe-linux.tgz path: zowex/target/x86_64-unknown-linux-gnu/debug/zowe.tgz @@ -59,7 +59,7 @@ jobs: if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) && !contains(github.event.head_commit.message, '[ci skip]') steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable @@ -81,7 +81,7 @@ jobs: - name: Archive Results id: upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: zowe-macos.tgz path: zowex/target/debug/zowe.tgz @@ -95,7 +95,7 @@ jobs: if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) && !contains(github.event.head_commit.message, '[ci skip]') steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable @@ -112,7 +112,7 @@ jobs: - name: Archive Results id: upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: zowe-windows.tgz path: zowex/target/debug/zowe.tgz diff --git a/.github/workflows/secrets-sdk-publish.yml b/.github/workflows/secrets-sdk-publish.yml index 3ae4d2050b..6015eeb40c 100644 --- a/.github/workflows/secrets-sdk-publish.yml +++ b/.github/workflows/secrets-sdk-publish.yml @@ -11,9 +11,9 @@ jobs: run: working-directory: packages/secrets steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 check-latest: true diff --git a/.github/workflows/secrets-sdk.yml b/.github/workflows/secrets-sdk.yml index e069cd6d8a..c03956a729 100644 --- a/.github/workflows/secrets-sdk.yml +++ b/.github/workflows/secrets-sdk.yml @@ -93,9 +93,9 @@ jobs: name: stable - ${{ matrix.settings.target }} - node@20 runs-on: ${{ matrix.settings.host }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 if: ${{ !matrix.settings.docker }} with: node-version: 20 @@ -108,7 +108,7 @@ jobs: toolchain: stable target: ${{ matrix.settings.target }} - name: Cache cargo - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo/registry/index/ @@ -127,7 +127,7 @@ jobs: working-directory: "." run: npm ci --ignore-scripts - name: Setup node x86 - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 if: matrix.settings.target == 'i686-pc-windows-msvc' with: node-version: 20 @@ -146,7 +146,7 @@ jobs: if: ${{ !matrix.settings.docker }} shell: bash - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: bindings-${{ matrix.settings.target }} path: packages/secrets/src/keyring/${{ env.APP_NAME }}.*.node @@ -229,9 +229,9 @@ jobs: - "20" runs-on: ${{ matrix.settings.host }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} check-latest: true @@ -239,12 +239,12 @@ jobs: - name: Install dependencies run: npm ci --ignore-scripts - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: bindings-${{ matrix.settings.target }} path: packages/secrets/src/keyring/ - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 if: ${{ matrix.settings.platform }} with: platforms: ${{ matrix.settings.platform }} diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 206794b77b..8d08046c1c 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ github.event.workflow_run.head_repository.full_name }} ref: ${{ github.event.workflow_run.head_branch }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index c46005d17a..6acaccc7f2 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,7 +11,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: # General rules applied to both, issues and pull requests (PRs) start-date: "2022-07-30T00:00:00Z" diff --git a/.github/workflows/zowe-cli.yml b/.github/workflows/zowe-cli.yml index 1885e9fedb..b56cceb963 100644 --- a/.github/workflows/zowe-cli.yml +++ b/.github/workflows/zowe-cli.yml @@ -53,10 +53,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} check-latest: true @@ -105,7 +105,7 @@ jobs: - name: Archive Binary if: github.event.inputs.test-type == 'binary' || github.event_name == 'push' id: upload-binary - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: zowe-${{ matrix.os }}.tgz path: zowe.tgz @@ -147,14 +147,14 @@ jobs: - name: Archive Results if: ${{ always() && steps.build.outcome == 'success' }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.os }}-${{ matrix.node-version }}-results path: __tests__/__results__/ - name: Upload Results to Codecov if: ${{ always() && steps.build.outcome == 'success' }} - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: env_vars: OS,NODE @@ -165,7 +165,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 persist-credentials: false @@ -173,7 +173,7 @@ jobs: # Use Node 20. Currently the latest. - name: Use Node.js 20 - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20' From 3ae40398a1ddf887aeee63cd4d341b075e5dfc9a Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Fri, 2 Feb 2024 14:49:48 +0000 Subject: [PATCH 70/92] Add overwrite to workflow Signed-off-by: Andrew W. Harn --- .github/workflows/zowe-cli.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/zowe-cli.yml b/.github/workflows/zowe-cli.yml index b56cceb963..d17983562a 100644 --- a/.github/workflows/zowe-cli.yml +++ b/.github/workflows/zowe-cli.yml @@ -109,6 +109,7 @@ jobs: with: name: zowe-${{ matrix.os }}.tgz path: zowe.tgz + overwrite: true - name: Setup Binary in PATH if: github.event.inputs.test-type == 'binary' || github.event_name == 'push' From e1689e0ab4b87f200788028602245fc92bacf36d Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Fri, 2 Feb 2024 16:02:38 +0000 Subject: [PATCH 71/92] Fix CodeCov Signed-off-by: Andrew W. Harn --- .github/workflows/zowe-cli.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/zowe-cli.yml b/.github/workflows/zowe-cli.yml index d17983562a..6d9873e550 100644 --- a/.github/workflows/zowe-cli.yml +++ b/.github/workflows/zowe-cli.yml @@ -158,6 +158,7 @@ jobs: uses: codecov/codecov-action@v4 with: env_vars: OS,NODE + token: ${{ secrets.CODECOV_TOKEN }} release: if: github.event_name == 'push' && github.ref_protected From d762d02edc8b7a1270dc9b62a6b1f07b70b97137 Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Fri, 2 Feb 2024 19:46:02 +0000 Subject: [PATCH 72/92] Use maintained label action Signed-off-by: Andrew W. Harn --- .github/workflows/auto-comment.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/auto-comment.yml b/.github/workflows/auto-comment.yml index 1d707b5af8..952eeffd9a 100644 --- a/.github/workflows/auto-comment.yml +++ b/.github/workflows/auto-comment.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v4 - name: Process Label Action - uses: hramos/respond-to-issue-based-on-label@v2 + uses: dessant/label-actions@v4 with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - configuration-path: '.github/label-actions.yml' + github-token: ${{ secrets.GITHUB_TOKEN }} + config-path: '.github/label-actions.yml' From b457ae41ab11d8277dcf15b692ea07fed97a04bb Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Fri, 2 Feb 2024 20:25:00 +0000 Subject: [PATCH 73/92] Use GH CLI for release publish Signed-off-by: Andrew W. Harn --- .github/workflows/rust-cli-publish.yml | 48 ++++++-------------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/.github/workflows/rust-cli-publish.yml b/.github/workflows/rust-cli-publish.yml index 65901b6431..0c63f13a0c 100644 --- a/.github/workflows/rust-cli-publish.yml +++ b/.github/workflows/rust-cli-publish.yml @@ -28,19 +28,15 @@ jobs: - name: Create Release id: create_release - uses: ncipollo/release-action@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag: native-v${{ steps.get-version.outputs.ZOWEX_VERSION }} - name: Native Client Release ${{ steps.get-version.outputs.ZOWEX_VERSION }} - body: | - Native Zowe CLI client which communicates with a "daemon" version of Zowe CLI. - draft: false - prerelease: false - makeLatest: false - - - uses: actions/upload-artifact@v3 + run: | + gh release create \ + -n "Native Zowe CLI client which communicates with a 'daemon' version of Zowe CLI." \ + -t "Native Client Release ${{ steps.get-version.outputs.ZOWEX_VERSION }}" \ + native-v${{ steps.get-version.outputs.ZOWEX_VERSION }} + + - uses: actions/upload-artifact@v4 with: name: repo path: | @@ -79,17 +75,9 @@ jobs: - name: Upload Release Asset id: upload-release-asset - uses: ncipollo/release-action@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag: native-v${{ needs.release.outputs.ZOWEX_VERSION }} - name: Native Client Release ${{ needs.release.outputs.ZOWEX_VERSION }} - allowUpdates: true - artifacts: target/x86_64-unknown-linux-gnu/release/zowe-linux.tgz - artifactContentType: application/octet-stream - removeArtifacts: false - replacesArtifacts: false + run: gh release upload native-v${{ needs.release.outputs.ZOWEX_VERSION }} target/x86_64-unknown-linux-gnu/release/zowe-linux.tgz build-macos: @@ -126,17 +114,9 @@ jobs: - name: Upload Release Asset id: upload-release-asset - uses: ncipollo/release-action@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag: native-v${{ needs.release.outputs.ZOWEX_VERSION }} - name: Native Client Release ${{ needs.release.outputs.ZOWEX_VERSION }} - allowUpdates: true - artifacts: target/release/zowe-macos.tgz - artifactContentType: application/octet-stream - removeArtifacts: false - replacesArtifacts: false + run: gh release upload native-v${{ needs.release.outputs.ZOWEX_VERSION }} target/release/zowe-macos.tgz build-windows: @@ -168,14 +148,6 @@ jobs: - name: Upload Release Asset id: upload-release-asset - uses: ncipollo/release-action@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag: native-v${{ needs.release.outputs.ZOWEX_VERSION }} - name: Native Client Release ${{ needs.release.outputs.ZOWEX_VERSION }} - allowUpdates: true - artifacts: target/release/zowe-windows.tgz - artifactContentType: application/octet-stream - removeArtifacts: false - replacesArtifacts: false + run: gh release upload native-v${{ needs.release.outputs.ZOWEX_VERSION }} target/release/zowe-windows.tgz From 9fd1213f364cd7a1ce9710612c904659f1150303 Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Fri, 2 Feb 2024 20:27:24 +0000 Subject: [PATCH 74/92] Fix missed artifact steps Signed-off-by: Andrew W. Harn --- .github/workflows/rust-cli-publish.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust-cli-publish.yml b/.github/workflows/rust-cli-publish.yml index 0c63f13a0c..5d001c3fa6 100644 --- a/.github/workflows/rust-cli-publish.yml +++ b/.github/workflows/rust-cli-publish.yml @@ -55,7 +55,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: repo @@ -94,7 +94,7 @@ jobs: with: targets: aarch64-apple-darwin - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: repo @@ -131,7 +131,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: repo From a5c0423b9b0b2630fb70b6a836ad7318c1de62c1 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 7 Feb 2024 10:41:05 -0500 Subject: [PATCH 75/92] fix: check if config layer is valid before updating schema Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 9806b6fdd2..e6bcab3ddd 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1331,6 +1331,9 @@ export class ProfileInfo { const layerPath = cachedType != null ? cachedType[0].substring(0, cachedType[0].lastIndexOf(":")) : this.getTeamConfig().layerActive().path; const layerToUpdate = this.getTeamConfig().mLayers.find((l) => l.path === layerPath); + if (layerToUpdate == null) { + return; + } const cacheKey = `${layerPath}:${profileType}`; const sameSchemaExists = versionChanged ? false : From 83c5bc7d0931f04e1dc74321150fed767f05e1ee Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Wed, 7 Feb 2024 11:41:01 -0500 Subject: [PATCH 76/92] test: updateSchemaAtLayer does nothing if layer path not found Signed-off-by: Trae Yelovich --- .../__tests__/ProfileInfo.TeamConfig.unit.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 428326ccca..3150324307 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1416,6 +1416,17 @@ describe("TeamConfig ProfileInfo tests", () => { }; }; + it("does nothing if there are no layers that match the built layer path", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + (profInfo as any).mProfileSchemaCache = new Map(); + (profInfo as any).mProfileSchemaCache.set("/some/nonexistent/layer/path:someUnregisteredProfType"); + const writeFileSync = jest.spyOn(jsonfile, "writeFileSync"); + writeFileSync.mockReset(); + (profInfo as any).updateSchemaAtLayer("someUnregisteredProfType", {} as any); + expect(writeFileSync).not.toHaveBeenCalled(); + }); + // case 1: schema is the same as the cached one; do not write to disk it("does not write schema to disk if it hasn't changed", async () => { const blockMocks = getBlockMocks(); From ed08ed2638ba51054c3390d73311a1aed55e0a71 Mon Sep 17 00:00:00 2001 From: zowe-robot Date: Thu, 8 Feb 2024 14:56:49 +0000 Subject: [PATCH 77/92] Bump version to 7.23.1 [ci skip] Signed-off-by: zowe-robot --- .../__packages__/cli-test-utils/package.json | 4 +- lerna.json | 2 +- npm-shrinkwrap.json | 206 +++++++++--------- packages/cli/CHANGELOG.md | 2 +- packages/cli/package.json | 26 +-- packages/core/package.json | 6 +- packages/imperative/package.json | 2 +- packages/provisioning/package.json | 8 +- packages/workflows/package.json | 10 +- packages/zosconsole/package.json | 8 +- packages/zosfiles/package.json | 10 +- packages/zosjobs/package.json | 10 +- packages/zoslogs/package.json | 8 +- packages/zosmf/package.json | 8 +- packages/zostso/package.json | 10 +- packages/zosuss/package.json | 6 +- 16 files changed, 163 insertions(+), 163 deletions(-) diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index bd6afe0b2c..70f144d9b9 100644 --- a/__tests__/__packages__/cli-test-utils/package.json +++ b/__tests__/__packages__/cli-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli-test-utils", - "version": "7.23.0", + "version": "7.23.1", "description": "Test utilities package for Zowe CLI plug-ins", "author": "Zowe", "license": "EPL-2.0", @@ -43,7 +43,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.0" + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" diff --git a/lerna.json b/lerna.json index 3de5537bce..32b73c17ea 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "7.23.0", + "version": "7.23.1", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 3190874ea2..1d824762f5 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -51,7 +51,7 @@ }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", @@ -62,7 +62,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.0" + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" @@ -24604,21 +24604,21 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "7.23.0", + "version": "7.23.1", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/provisioning-for-zowe-sdk": "7.23.0", - "@zowe/zos-console-for-zowe-sdk": "7.23.0", - "@zowe/zos-files-for-zowe-sdk": "7.23.0", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.0", - "@zowe/zos-logs-for-zowe-sdk": "7.23.0", - "@zowe/zos-tso-for-zowe-sdk": "7.23.0", - "@zowe/zos-uss-for-zowe-sdk": "7.23.0", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.0", - "@zowe/zosmf-for-zowe-sdk": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/provisioning-for-zowe-sdk": "7.23.1", + "@zowe/zos-console-for-zowe-sdk": "7.23.1", + "@zowe/zos-files-for-zowe-sdk": "7.23.1", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.1", + "@zowe/zos-logs-for-zowe-sdk": "7.23.1", + "@zowe/zos-tso-for-zowe-sdk": "7.23.1", + "@zowe/zos-uss-for-zowe-sdk": "7.23.1", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.1", + "@zowe/zosmf-for-zowe-sdk": "7.23.1", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -24633,7 +24633,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.0", + "@zowe/cli-test-utils": "7.23.1", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" @@ -24666,15 +24666,15 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "dependencies": { "comment-json": "4.1.1", "string-width": "4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" @@ -24682,7 +24682,7 @@ }, "packages/imperative": { "name": "@zowe/imperative", - "version": "5.22.0", + "version": "5.22.1", "license": "EPL-2.0", "dependencies": { "@types/yargs": "13.0.4", @@ -25019,16 +25019,16 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "dependencies": { "js-yaml": "4.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25050,15 +25050,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.0" + "@zowe/zos-files-for-zowe-sdk": "7.23.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25067,12 +25067,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25081,17 +25081,17 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "dependencies": { "get-stream": "6.0.1", "minimatch": "5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/zos-uss-for-zowe-sdk": "7.23.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/zos-uss-for-zowe-sdk": "7.23.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25119,15 +25119,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.0" + "@zowe/zos-files-for-zowe-sdk": "7.23.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25136,12 +25136,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25150,12 +25150,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25164,15 +25164,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.23.0" + "@zowe/zosmf-for-zowe-sdk": "7.23.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25181,15 +25181,15 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "license": "EPL-2.0", "dependencies": { "ssh2": "1.15.0" }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/imperative": "^5.2.0" @@ -31839,19 +31839,19 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/provisioning-for-zowe-sdk": "7.23.0", + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/provisioning-for-zowe-sdk": "7.23.1", "@zowe/secrets-for-zowe-sdk": "7.18.6", - "@zowe/zos-console-for-zowe-sdk": "7.23.0", - "@zowe/zos-files-for-zowe-sdk": "7.23.0", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.0", - "@zowe/zos-logs-for-zowe-sdk": "7.23.0", - "@zowe/zos-tso-for-zowe-sdk": "7.23.0", - "@zowe/zos-uss-for-zowe-sdk": "7.23.0", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.0", - "@zowe/zosmf-for-zowe-sdk": "7.23.0", + "@zowe/zos-console-for-zowe-sdk": "7.23.1", + "@zowe/zos-files-for-zowe-sdk": "7.23.1", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.1", + "@zowe/zos-logs-for-zowe-sdk": "7.23.1", + "@zowe/zos-tso-for-zowe-sdk": "7.23.1", + "@zowe/zos-uss-for-zowe-sdk": "7.23.1", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.1", + "@zowe/zosmf-for-zowe-sdk": "7.23.1", "comment-json": "^4.1.1", "find-process": "1.4.7", "get-stream": "6.0.1", @@ -31885,7 +31885,7 @@ "requires": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.0", + "@zowe/imperative": "5.22.1", "find-up": "^5.0.0", "js-yaml": "^4.0.0", "rimraf": "^3.0.2", @@ -31905,8 +31905,8 @@ "@zowe/core-for-zowe-sdk": { "version": "file:packages/core", "requires": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/imperative": "5.22.0", + "@zowe/cli-test-utils": "7.23.1", + "@zowe/imperative": "5.22.1", "comment-json": "4.1.1", "string-width": "4.2.3" } @@ -32160,9 +32160,9 @@ "version": "file:packages/provisioning", "requires": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", "js-yaml": "4.1.0" } }, @@ -32176,18 +32176,18 @@ "@zowe/zos-console-for-zowe-sdk": { "version": "file:packages/zosconsole", "requires": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" } }, "@zowe/zos-files-for-zowe-sdk": { "version": "file:packages/zosfiles", "requires": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/zos-uss-for-zowe-sdk": "7.23.0", + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/zos-uss-for-zowe-sdk": "7.23.1", "get-stream": "6.0.1", "minimatch": "5.0.1" }, @@ -32213,53 +32213,53 @@ "@zowe/zos-jobs-for-zowe-sdk": { "version": "file:packages/zosjobs", "requires": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/zos-files-for-zowe-sdk": "7.23.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/zos-files-for-zowe-sdk": "7.23.1" } }, "@zowe/zos-logs-for-zowe-sdk": { "version": "file:packages/zoslogs", "requires": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" } }, "@zowe/zos-tso-for-zowe-sdk": { "version": "file:packages/zostso", "requires": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/zosmf-for-zowe-sdk": "7.23.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/zosmf-for-zowe-sdk": "7.23.1" } }, "@zowe/zos-uss-for-zowe-sdk": { "version": "file:packages/zosuss", "requires": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.0", - "@zowe/imperative": "5.22.0", + "@zowe/cli-test-utils": "7.23.1", + "@zowe/imperative": "5.22.1", "ssh2": "1.15.0" } }, "@zowe/zos-workflows-for-zowe-sdk": { "version": "file:packages/workflows", "requires": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/zos-files-for-zowe-sdk": "7.23.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/zos-files-for-zowe-sdk": "7.23.1" } }, "@zowe/zosmf-for-zowe-sdk": { "version": "file:packages/zosmf", "requires": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" } }, "abbrev": { diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 8d4e86d8ab..c1d32def3a 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Zowe CLI package will be documented in this file. -## Recent Changes +## `7.23.1` - Enhancement: Adding `--binary` and `--encoding` options to `zosfiles edit` to zowe V2 diff --git a/packages/cli/package.json b/packages/cli/package.json index cb75cb3314..c4868e6e7e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", "license": "EPL-2.0", @@ -58,17 +58,17 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/provisioning-for-zowe-sdk": "7.23.0", - "@zowe/zos-console-for-zowe-sdk": "7.23.0", - "@zowe/zos-files-for-zowe-sdk": "7.23.0", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.0", - "@zowe/zos-logs-for-zowe-sdk": "7.23.0", - "@zowe/zos-tso-for-zowe-sdk": "7.23.0", - "@zowe/zos-uss-for-zowe-sdk": "7.23.0", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.0", - "@zowe/zosmf-for-zowe-sdk": "7.23.0", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/provisioning-for-zowe-sdk": "7.23.1", + "@zowe/zos-console-for-zowe-sdk": "7.23.1", + "@zowe/zos-files-for-zowe-sdk": "7.23.1", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.1", + "@zowe/zos-logs-for-zowe-sdk": "7.23.1", + "@zowe/zos-tso-for-zowe-sdk": "7.23.1", + "@zowe/zos-uss-for-zowe-sdk": "7.23.1", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.1", + "@zowe/zosmf-for-zowe-sdk": "7.23.1", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -79,7 +79,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.0", + "@zowe/cli-test-utils": "7.23.1", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" diff --git a/packages/core/package.json b/packages/core/package.json index c544c291ea..1573e6b834 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Core libraries shared by Zowe SDK packages", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ "string-width": "4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" diff --git a/packages/imperative/package.json b/packages/imperative/package.json index 1fe9586e77..85db749f63 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "5.22.0", + "version": "5.22.1", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index 4c6a8e9ebf..7a7c4f2523 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with the z/OS provisioning APIs", "author": "Zowe", "license": "EPL-2.0", @@ -49,9 +49,9 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/workflows/package.json b/packages/workflows/package.json index 8f5777ce17..d4fdee3f53 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.0" + "@zowe/zos-files-for-zowe-sdk": "7.23.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index 94c2bfe221..71cc0d9dad 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with the z/OS console", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index 05dd84e3ce..b2a393e2d1 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -50,10 +50,10 @@ "minimatch": "5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0", - "@zowe/zos-uss-for-zowe-sdk": "7.23.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1", + "@zowe/zos-uss-for-zowe-sdk": "7.23.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index a2c4449814..867c9769ba 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,12 +46,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.0" + "@zowe/zos-files-for-zowe-sdk": "7.23.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index f4f84d7ec9..f082129b6b 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with the z/OS logs", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index cf870b56fa..03008dab66 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with the z/OS Management Facility", "author": "Zowe", "license": "EPL-2.0", @@ -44,9 +44,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zostso/package.json b/packages/zostso/package.json index 46b187a41c..c6d61eaa9c 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with TSO on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.23.0" + "@zowe/zosmf-for-zowe-sdk": "7.23.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.0", - "@zowe/core-for-zowe-sdk": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index a8d8c4d6e5..d2af39e664 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.23.0", + "version": "7.23.1", "description": "Zowe SDK to interact with USS on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.0", - "@zowe/imperative": "5.22.0" + "@zowe/cli-test-utils": "7.23.1", + "@zowe/imperative": "5.22.1" }, "peerDependencies": { "@zowe/imperative": "^5.2.0" From 71c88d82d2647274795e73e07d1889db3ac50e0c Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Fri, 9 Feb 2024 14:43:08 -0500 Subject: [PATCH 78/92] fix: ignore command-based props during schema comparison Signed-off-by: Trae Yelovich --- packages/imperative/CHANGELOG.md | 5 ++- .../ProfileInfo.TeamConfig.unit.test.ts | 9 +++-- .../imperative/src/config/src/ProfileInfo.ts | 34 ++++++++++++++++--- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index b1aac3a280..d34ddf8fe8 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- BugFix: Resolved issue in `ProfileInfo` where schema comparisons fail, specifically when comparing the cached schema against a command-based schema during registration. + ## `5.22.0` - BugFix: Updated `mustache` and `jsonschema` dependencies for technical currency. @@ -69,7 +73,6 @@ All notable changes to the Imperative package will be documented in this file. - BugFix: Handle logic for if a null command handler is provided - ## `5.14.1` - BugFix: Fixed a logic error in the `config list` command that caused unwanted behavior when a positional and `--locations` were both passed in. diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 3150324307..d51937c64e 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -1420,7 +1420,7 @@ describe("TeamConfig ProfileInfo tests", () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); (profInfo as any).mProfileSchemaCache = new Map(); - (profInfo as any).mProfileSchemaCache.set("/some/nonexistent/layer/path:someUnregisteredProfType"); + (profInfo as any).mProfileSchemaCache.set("/some/nonexistent/layer/path:someUnregisteredProfType", {}); const writeFileSync = jest.spyOn(jsonfile, "writeFileSync"); writeFileSync.mockReset(); (profInfo as any).updateSchemaAtLayer("someUnregisteredProfType", {} as any); @@ -1432,6 +1432,8 @@ describe("TeamConfig ProfileInfo tests", () => { const blockMocks = getBlockMocks(); const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); + jest.spyOn(Map.prototype, "has").mockReturnValue(true); + jest.spyOn(lodash, "isEqual").mockReturnValue(true); const dummySchema = profInfo.getSchemaForType("dummy"); blockMocks.buildSchema.mockReturnValueOnce({} as any); writeFileSyncMock.mockClear(); @@ -1571,9 +1573,10 @@ describe("TeamConfig ProfileInfo tests", () => { }); it("warns the user when old, unversioned schema is different from new, unversioned schema", () => { - jest.spyOn(ProfileInfo.prototype, "getSchemaForType").mockReturnValue({ title: "Mock Schema", otherKey: "otherVal" } as any); + jest.spyOn(ProfileInfo.prototype, "getSchemaForType") + .mockReturnValue({ title: "Mock Schema", properties: { otherKey: "someValue" } } as any); expectAddToSchemaTester( - { schema: { title: "Mock Schema", someKey: "someValue" } as any, previousVersion: "none" }, + { schema: { title: "Mock Schema", properties: { someKey: "someValue" } } as any, previousVersion: "none" }, { extendersJson: { profileTypes: { diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index e6bcab3ddd..8021873d79 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -36,7 +36,7 @@ import { IConfigOpts } from "./doc/IConfigOpts"; // for old-school profile operations import { AbstractProfileManager } from "../../profiles/src/abstract/AbstractProfileManager"; import { CliProfileManager, ICommandProfileProperty, ICommandArguments } from "../../cmd"; -import { IProfileLoaded, IProfileSchema, ProfileIO } from "../../profiles"; +import { IProfileLoaded, IProfileProperty, IProfileSchema, ProfileIO } from "../../profiles"; // for imperative operations import { EnvironmentalVariableSettings } from "../../imperative/src/env/EnvironmentalVariableSettings"; @@ -1336,8 +1336,11 @@ export class ProfileInfo { } const cacheKey = `${layerPath}:${profileType}`; - const sameSchemaExists = versionChanged ? false : - this.mProfileSchemaCache.has(cacheKey) && lodash.isEqual(this.mProfileSchemaCache.get(cacheKey), schema); + const transformedSchemaProps = this.omitCmdPropsFromSchema(schema.properties); + const transformedCacheProps = this.mProfileSchemaCache.has(cacheKey) ? + this.omitCmdPropsFromSchema(this.mProfileSchemaCache.get(cacheKey)) : {}; + + const sameSchemaExists = this.mProfileSchemaCache.has(cacheKey) && lodash.isEqual(transformedSchemaProps, transformedCacheProps); // Update the cache with the newest schema for this profile type this.mProfileSchemaCache.set(cacheKey, schema); @@ -1348,11 +1351,29 @@ export class ProfileInfo { const schemaPath = url.fileURLToPath(schemaUri); // if profile type schema has changed or if it doesn't exist on-disk, rebuild schema and write to disk - if (!sameSchemaExists && fs.existsSync(schemaPath)) { + if (versionChanged || !sameSchemaExists && fs.existsSync(schemaPath)) { jsonfile.writeFileSync(schemaPath, this.buildSchema([], layerToUpdate), { spaces: 4 }); } } + /** + * This helper function removes all command-related properties from the given schema properties object and returns it. + * This is so we can easily compare schemas from disk with those that are registered with type ICommandProfileSchema. + * It's also been added to avoid a breaking change (as we currently allow ICommandProfileSchema objects to be registered). + * @param obj The properties object from the schema + * @returns The properties object, but with all of the command-related properties removed + */ + private omitCmdPropsFromSchema(obj: Record): Record { + const result = lodash.omit(obj, ["optionDefinition", "optionDefinitions", "includeInTemplate"]); + Object.keys(result).forEach((key) => { + if (lodash.isObject(result[key])) { + result[key] = this.omitCmdPropsFromSchema(result[key]); + } + }); + + return result; + } + /** * Adds a profile type to the schema, and tracks its contribution in extenders.json. * @@ -1427,9 +1448,12 @@ export class ProfileInfo { }; } + const schemaProps = this.omitCmdPropsFromSchema(typeInfo.schema.properties); + const cachedSchemaProps = this.omitCmdPropsFromSchema(this.getSchemaForType(profileType)?.properties || {}); + // If the old schema doesn't have a tracked version and its different from the one passed into this function, warn the user if (this.mExtendersJson.profileTypes[profileType].version == null && - !lodash.isEqual(typeInfo.schema, this.getSchemaForType(profileType))) { + !lodash.isEqual(schemaProps, cachedSchemaProps)) { return { success: false, info: `Both the old and new schemas are unversioned for ${profileType}, but the schemas are different. `.concat( From e896d7adf1acdbf887cdc8f4fd5ec56b22918821 Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Mon, 12 Feb 2024 21:27:30 +0000 Subject: [PATCH 79/92] Fix technical currency Signed-off-by: Andrew W. Harn --- npm-shrinkwrap.json | 67 ++++++++++++++++++++++++-------- packages/cli/CHANGELOG.md | 4 ++ packages/imperative/CHANGELOG.md | 4 ++ 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1d824762f5..d07efa5384 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -14338,10 +14338,22 @@ "node": ">=12.0.0" } }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, "node_modules/irregular-plurals": { "version": "3.5.0", @@ -17125,6 +17137,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -22554,15 +22571,15 @@ } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.3.tgz", + "integrity": "sha512-vfuYK48HXCTFD03G/1/zkIls3Ebr2YNa4qU9gHDZdblHLiqhJrJGkY3+0Nx0JpN9qBhJbVObc1CNciT1bIZJxw==", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -36681,10 +36698,21 @@ "wrap-ansi": "^7.0.0" } }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + } + } }, "irregular-plurals": { "version": "3.5.0", @@ -38844,6 +38872,11 @@ "argparse": "^2.0.1" } }, + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -42996,11 +43029,11 @@ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" }, "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.3.tgz", + "integrity": "sha512-vfuYK48HXCTFD03G/1/zkIls3Ebr2YNa4qU9gHDZdblHLiqhJrJGkY3+0Nx0JpN9qBhJbVObc1CNciT1bIZJxw==", "requires": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" } }, diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index c1d32def3a..d0bea115fc 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Zowe CLI package will be documented in this file. +## Recent Changes + +- BugFix: Resolved technical currency by updating `socks` transitive dependency + ## `7.23.1` - Enhancement: Adding `--binary` and `--encoding` options to `zosfiles edit` to zowe V2 diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index b1aac3a280..1c2aa9743b 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- BugFix: Resolved technical currency by updating `socks` transitive dependency + ## `5.22.0` - BugFix: Updated `mustache` and `jsonschema` dependencies for technical currency. From 5e8ae95cef821dd969d264a2b008feabd0467da3 Mon Sep 17 00:00:00 2001 From: zowe-robot Date: Mon, 12 Feb 2024 23:00:49 +0000 Subject: [PATCH 80/92] Bump version to 7.23.2 [ci skip] Signed-off-by: zowe-robot --- .../__packages__/cli-test-utils/package.json | 4 +- lerna.json | 2 +- npm-shrinkwrap.json | 206 +++++++++--------- packages/cli/CHANGELOG.md | 2 +- packages/cli/package.json | 26 +-- packages/core/package.json | 6 +- packages/imperative/CHANGELOG.md | 2 +- packages/imperative/package.json | 2 +- packages/provisioning/package.json | 8 +- packages/workflows/package.json | 10 +- packages/zosconsole/package.json | 8 +- packages/zosfiles/package.json | 10 +- packages/zosjobs/package.json | 10 +- packages/zoslogs/package.json | 8 +- packages/zosmf/package.json | 8 +- packages/zostso/package.json | 10 +- packages/zosuss/package.json | 6 +- 17 files changed, 164 insertions(+), 164 deletions(-) diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index 70f144d9b9..c34d22dddd 100644 --- a/__tests__/__packages__/cli-test-utils/package.json +++ b/__tests__/__packages__/cli-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli-test-utils", - "version": "7.23.1", + "version": "7.23.2", "description": "Test utilities package for Zowe CLI plug-ins", "author": "Zowe", "license": "EPL-2.0", @@ -43,7 +43,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.1" + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" diff --git a/lerna.json b/lerna.json index 32b73c17ea..1344cd3f1d 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "7.23.1", + "version": "7.23.2", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index d07efa5384..139003fba3 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -51,7 +51,7 @@ }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", @@ -62,7 +62,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.1" + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" @@ -24621,21 +24621,21 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "7.23.1", + "version": "7.23.2", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/provisioning-for-zowe-sdk": "7.23.1", - "@zowe/zos-console-for-zowe-sdk": "7.23.1", - "@zowe/zos-files-for-zowe-sdk": "7.23.1", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.1", - "@zowe/zos-logs-for-zowe-sdk": "7.23.1", - "@zowe/zos-tso-for-zowe-sdk": "7.23.1", - "@zowe/zos-uss-for-zowe-sdk": "7.23.1", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.1", - "@zowe/zosmf-for-zowe-sdk": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/provisioning-for-zowe-sdk": "7.23.2", + "@zowe/zos-console-for-zowe-sdk": "7.23.2", + "@zowe/zos-files-for-zowe-sdk": "7.23.2", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.2", + "@zowe/zos-logs-for-zowe-sdk": "7.23.2", + "@zowe/zos-tso-for-zowe-sdk": "7.23.2", + "@zowe/zos-uss-for-zowe-sdk": "7.23.2", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.2", + "@zowe/zosmf-for-zowe-sdk": "7.23.2", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -24650,7 +24650,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.1", + "@zowe/cli-test-utils": "7.23.2", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" @@ -24683,15 +24683,15 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "dependencies": { "comment-json": "4.1.1", "string-width": "4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" @@ -24699,7 +24699,7 @@ }, "packages/imperative": { "name": "@zowe/imperative", - "version": "5.22.1", + "version": "5.22.2", "license": "EPL-2.0", "dependencies": { "@types/yargs": "13.0.4", @@ -25036,16 +25036,16 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "dependencies": { "js-yaml": "4.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25067,15 +25067,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.1" + "@zowe/zos-files-for-zowe-sdk": "7.23.2" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25084,12 +25084,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25098,17 +25098,17 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "dependencies": { "get-stream": "6.0.1", "minimatch": "5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/zos-uss-for-zowe-sdk": "7.23.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/zos-uss-for-zowe-sdk": "7.23.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25136,15 +25136,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.1" + "@zowe/zos-files-for-zowe-sdk": "7.23.2" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25153,12 +25153,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25167,12 +25167,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25181,15 +25181,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.23.1" + "@zowe/zosmf-for-zowe-sdk": "7.23.2" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25198,15 +25198,15 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "license": "EPL-2.0", "dependencies": { "ssh2": "1.15.0" }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/imperative": "^5.2.0" @@ -31856,19 +31856,19 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/provisioning-for-zowe-sdk": "7.23.1", + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/provisioning-for-zowe-sdk": "7.23.2", "@zowe/secrets-for-zowe-sdk": "7.18.6", - "@zowe/zos-console-for-zowe-sdk": "7.23.1", - "@zowe/zos-files-for-zowe-sdk": "7.23.1", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.1", - "@zowe/zos-logs-for-zowe-sdk": "7.23.1", - "@zowe/zos-tso-for-zowe-sdk": "7.23.1", - "@zowe/zos-uss-for-zowe-sdk": "7.23.1", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.1", - "@zowe/zosmf-for-zowe-sdk": "7.23.1", + "@zowe/zos-console-for-zowe-sdk": "7.23.2", + "@zowe/zos-files-for-zowe-sdk": "7.23.2", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.2", + "@zowe/zos-logs-for-zowe-sdk": "7.23.2", + "@zowe/zos-tso-for-zowe-sdk": "7.23.2", + "@zowe/zos-uss-for-zowe-sdk": "7.23.2", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.2", + "@zowe/zosmf-for-zowe-sdk": "7.23.2", "comment-json": "^4.1.1", "find-process": "1.4.7", "get-stream": "6.0.1", @@ -31902,7 +31902,7 @@ "requires": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.1", + "@zowe/imperative": "5.22.2", "find-up": "^5.0.0", "js-yaml": "^4.0.0", "rimraf": "^3.0.2", @@ -31922,8 +31922,8 @@ "@zowe/core-for-zowe-sdk": { "version": "file:packages/core", "requires": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/imperative": "5.22.1", + "@zowe/cli-test-utils": "7.23.2", + "@zowe/imperative": "5.22.2", "comment-json": "4.1.1", "string-width": "4.2.3" } @@ -32177,9 +32177,9 @@ "version": "file:packages/provisioning", "requires": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", "js-yaml": "4.1.0" } }, @@ -32193,18 +32193,18 @@ "@zowe/zos-console-for-zowe-sdk": { "version": "file:packages/zosconsole", "requires": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" } }, "@zowe/zos-files-for-zowe-sdk": { "version": "file:packages/zosfiles", "requires": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/zos-uss-for-zowe-sdk": "7.23.1", + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/zos-uss-for-zowe-sdk": "7.23.2", "get-stream": "6.0.1", "minimatch": "5.0.1" }, @@ -32230,53 +32230,53 @@ "@zowe/zos-jobs-for-zowe-sdk": { "version": "file:packages/zosjobs", "requires": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/zos-files-for-zowe-sdk": "7.23.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/zos-files-for-zowe-sdk": "7.23.2" } }, "@zowe/zos-logs-for-zowe-sdk": { "version": "file:packages/zoslogs", "requires": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" } }, "@zowe/zos-tso-for-zowe-sdk": { "version": "file:packages/zostso", "requires": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/zosmf-for-zowe-sdk": "7.23.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/zosmf-for-zowe-sdk": "7.23.2" } }, "@zowe/zos-uss-for-zowe-sdk": { "version": "file:packages/zosuss", "requires": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.1", - "@zowe/imperative": "5.22.1", + "@zowe/cli-test-utils": "7.23.2", + "@zowe/imperative": "5.22.2", "ssh2": "1.15.0" } }, "@zowe/zos-workflows-for-zowe-sdk": { "version": "file:packages/workflows", "requires": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/zos-files-for-zowe-sdk": "7.23.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/zos-files-for-zowe-sdk": "7.23.2" } }, "@zowe/zosmf-for-zowe-sdk": { "version": "file:packages/zosmf", "requires": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" } }, "abbrev": { diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index d0bea115fc..55ba8ed0a2 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Zowe CLI package will be documented in this file. -## Recent Changes +## `7.23.2` - BugFix: Resolved technical currency by updating `socks` transitive dependency diff --git a/packages/cli/package.json b/packages/cli/package.json index c4868e6e7e..82d6903b63 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", "license": "EPL-2.0", @@ -58,17 +58,17 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/provisioning-for-zowe-sdk": "7.23.1", - "@zowe/zos-console-for-zowe-sdk": "7.23.1", - "@zowe/zos-files-for-zowe-sdk": "7.23.1", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.1", - "@zowe/zos-logs-for-zowe-sdk": "7.23.1", - "@zowe/zos-tso-for-zowe-sdk": "7.23.1", - "@zowe/zos-uss-for-zowe-sdk": "7.23.1", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.1", - "@zowe/zosmf-for-zowe-sdk": "7.23.1", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/provisioning-for-zowe-sdk": "7.23.2", + "@zowe/zos-console-for-zowe-sdk": "7.23.2", + "@zowe/zos-files-for-zowe-sdk": "7.23.2", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.2", + "@zowe/zos-logs-for-zowe-sdk": "7.23.2", + "@zowe/zos-tso-for-zowe-sdk": "7.23.2", + "@zowe/zos-uss-for-zowe-sdk": "7.23.2", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.2", + "@zowe/zosmf-for-zowe-sdk": "7.23.2", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -79,7 +79,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.1", + "@zowe/cli-test-utils": "7.23.2", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" diff --git a/packages/core/package.json b/packages/core/package.json index 1573e6b834..50da6bc262 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Core libraries shared by Zowe SDK packages", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ "string-width": "4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 1c2aa9743b..9fbb5c4f64 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Imperative package will be documented in this file. -## Recent Changes +## `5.22.2` - BugFix: Resolved technical currency by updating `socks` transitive dependency diff --git a/packages/imperative/package.json b/packages/imperative/package.json index 85db749f63..c989c80329 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "5.22.1", + "version": "5.22.2", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index 7a7c4f2523..5f807ea3f3 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with the z/OS provisioning APIs", "author": "Zowe", "license": "EPL-2.0", @@ -49,9 +49,9 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/workflows/package.json b/packages/workflows/package.json index d4fdee3f53..7cc15b5dd1 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.1" + "@zowe/zos-files-for-zowe-sdk": "7.23.2" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index 71cc0d9dad..509b25e88e 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with the z/OS console", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index b2a393e2d1..b79839a844 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -50,10 +50,10 @@ "minimatch": "5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1", - "@zowe/zos-uss-for-zowe-sdk": "7.23.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2", + "@zowe/zos-uss-for-zowe-sdk": "7.23.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index 867c9769ba..a7c0616028 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,12 +46,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.1" + "@zowe/zos-files-for-zowe-sdk": "7.23.2" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index f082129b6b..f4b6aa6b7a 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with the z/OS logs", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index 03008dab66..f39f3f80bf 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with the z/OS Management Facility", "author": "Zowe", "license": "EPL-2.0", @@ -44,9 +44,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zostso/package.json b/packages/zostso/package.json index c6d61eaa9c..c12c45c85c 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with TSO on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.23.1" + "@zowe/zosmf-for-zowe-sdk": "7.23.2" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.1", - "@zowe/core-for-zowe-sdk": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index d2af39e664..bba4026adb 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.23.1", + "version": "7.23.2", "description": "Zowe SDK to interact with USS on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.1", - "@zowe/imperative": "5.22.1" + "@zowe/cli-test-utils": "7.23.2", + "@zowe/imperative": "5.22.2" }, "peerDependencies": { "@zowe/imperative": "^5.2.0" From 7ff571b580775c497f118d7c949dbf105cd29331 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 13 Feb 2024 09:53:05 -0500 Subject: [PATCH 81/92] refactor: move cmd props into constant array Signed-off-by: Trae Yelovich --- packages/imperative/src/config/src/ProfileInfo.ts | 3 ++- packages/imperative/src/constants/src/Constants.ts | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 8021873d79..66120830fe 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -57,6 +57,7 @@ import { ConfigUtils } from "./ConfigUtils"; import { ConfigBuilder } from "./ConfigBuilder"; import { IAddProfTypeResult, IExtenderTypeInfo, IExtendersJsonOpts } from "./doc/IExtenderOpts"; import { IConfigLayer } from ".."; +import { Constants } from "../../constants"; /** * This class provides functions to retrieve profile-related information. @@ -1364,7 +1365,7 @@ export class ProfileInfo { * @returns The properties object, but with all of the command-related properties removed */ private omitCmdPropsFromSchema(obj: Record): Record { - const result = lodash.omit(obj, ["optionDefinition", "optionDefinitions", "includeInTemplate"]); + const result: Record = lodash.omit(obj, Constants.COMMAND_PROF_TYPE_PROPS); Object.keys(result).forEach((key) => { if (lodash.isObject(result[key])) { result[key] = this.omitCmdPropsFromSchema(result[key]); diff --git a/packages/imperative/src/constants/src/Constants.ts b/packages/imperative/src/constants/src/Constants.ts index 85befd0080..cdd1d527f2 100644 --- a/packages/imperative/src/constants/src/Constants.ts +++ b/packages/imperative/src/constants/src/Constants.ts @@ -120,4 +120,10 @@ export class Constants { * Auto Init constants */ public static readonly AUTO_INIT_ACTION = "auto-init"; + + /** + * ICommandProfileTypeConfiguration properties + * (used to omit from schemas registered via ProfileInfo) + */ + public static readonly COMMAND_PROF_TYPE_PROPS = ["optionDefinition", "optionDefinitions", "includeInTemplate"]; } From 79f5e8c3f356d4144bb6365acf4346c82a5da9c4 Mon Sep 17 00:00:00 2001 From: zowe-robot Date: Tue, 13 Feb 2024 16:40:08 +0000 Subject: [PATCH 82/92] Bump version to 7.23.3 [ci skip] Signed-off-by: zowe-robot --- .../__packages__/cli-test-utils/package.json | 4 +- lerna.json | 2 +- npm-shrinkwrap.json | 206 +++++++++--------- packages/cli/package.json | 26 +-- packages/core/package.json | 6 +- packages/imperative/CHANGELOG.md | 2 +- packages/imperative/package.json | 2 +- packages/provisioning/package.json | 8 +- packages/workflows/package.json | 10 +- packages/zosconsole/package.json | 8 +- packages/zosfiles/package.json | 10 +- packages/zosjobs/package.json | 10 +- packages/zoslogs/package.json | 8 +- packages/zosmf/package.json | 8 +- packages/zostso/package.json | 10 +- packages/zosuss/package.json | 6 +- 16 files changed, 163 insertions(+), 163 deletions(-) diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index c34d22dddd..c39989e91c 100644 --- a/__tests__/__packages__/cli-test-utils/package.json +++ b/__tests__/__packages__/cli-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli-test-utils", - "version": "7.23.2", + "version": "7.23.3", "description": "Test utilities package for Zowe CLI plug-ins", "author": "Zowe", "license": "EPL-2.0", @@ -43,7 +43,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.2" + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" diff --git a/lerna.json b/lerna.json index 1344cd3f1d..12ad0df840 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "7.23.2", + "version": "7.23.3", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 139003fba3..ecba761f0c 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -51,7 +51,7 @@ }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", @@ -62,7 +62,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.2" + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" @@ -24621,21 +24621,21 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "7.23.2", + "version": "7.23.3", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/provisioning-for-zowe-sdk": "7.23.2", - "@zowe/zos-console-for-zowe-sdk": "7.23.2", - "@zowe/zos-files-for-zowe-sdk": "7.23.2", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.2", - "@zowe/zos-logs-for-zowe-sdk": "7.23.2", - "@zowe/zos-tso-for-zowe-sdk": "7.23.2", - "@zowe/zos-uss-for-zowe-sdk": "7.23.2", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.2", - "@zowe/zosmf-for-zowe-sdk": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/provisioning-for-zowe-sdk": "7.23.3", + "@zowe/zos-console-for-zowe-sdk": "7.23.3", + "@zowe/zos-files-for-zowe-sdk": "7.23.3", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.3", + "@zowe/zos-logs-for-zowe-sdk": "7.23.3", + "@zowe/zos-tso-for-zowe-sdk": "7.23.3", + "@zowe/zos-uss-for-zowe-sdk": "7.23.3", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.3", + "@zowe/zosmf-for-zowe-sdk": "7.23.3", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -24650,7 +24650,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.2", + "@zowe/cli-test-utils": "7.23.3", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" @@ -24683,15 +24683,15 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "dependencies": { "comment-json": "4.1.1", "string-width": "4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" @@ -24699,7 +24699,7 @@ }, "packages/imperative": { "name": "@zowe/imperative", - "version": "5.22.2", + "version": "5.22.3", "license": "EPL-2.0", "dependencies": { "@types/yargs": "13.0.4", @@ -25036,16 +25036,16 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "dependencies": { "js-yaml": "4.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25067,15 +25067,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.2" + "@zowe/zos-files-for-zowe-sdk": "7.23.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25084,12 +25084,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25098,17 +25098,17 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "dependencies": { "get-stream": "6.0.1", "minimatch": "5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/zos-uss-for-zowe-sdk": "7.23.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/zos-uss-for-zowe-sdk": "7.23.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25136,15 +25136,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.2" + "@zowe/zos-files-for-zowe-sdk": "7.23.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25153,12 +25153,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25167,12 +25167,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25181,15 +25181,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.23.2" + "@zowe/zosmf-for-zowe-sdk": "7.23.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", @@ -25198,15 +25198,15 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "license": "EPL-2.0", "dependencies": { "ssh2": "1.15.0" }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/imperative": "^5.2.0" @@ -31856,19 +31856,19 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/provisioning-for-zowe-sdk": "7.23.2", + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/provisioning-for-zowe-sdk": "7.23.3", "@zowe/secrets-for-zowe-sdk": "7.18.6", - "@zowe/zos-console-for-zowe-sdk": "7.23.2", - "@zowe/zos-files-for-zowe-sdk": "7.23.2", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.2", - "@zowe/zos-logs-for-zowe-sdk": "7.23.2", - "@zowe/zos-tso-for-zowe-sdk": "7.23.2", - "@zowe/zos-uss-for-zowe-sdk": "7.23.2", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.2", - "@zowe/zosmf-for-zowe-sdk": "7.23.2", + "@zowe/zos-console-for-zowe-sdk": "7.23.3", + "@zowe/zos-files-for-zowe-sdk": "7.23.3", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.3", + "@zowe/zos-logs-for-zowe-sdk": "7.23.3", + "@zowe/zos-tso-for-zowe-sdk": "7.23.3", + "@zowe/zos-uss-for-zowe-sdk": "7.23.3", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.3", + "@zowe/zosmf-for-zowe-sdk": "7.23.3", "comment-json": "^4.1.1", "find-process": "1.4.7", "get-stream": "6.0.1", @@ -31902,7 +31902,7 @@ "requires": { "@types/js-yaml": "^4.0.0", "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.22.2", + "@zowe/imperative": "5.22.3", "find-up": "^5.0.0", "js-yaml": "^4.0.0", "rimraf": "^3.0.2", @@ -31922,8 +31922,8 @@ "@zowe/core-for-zowe-sdk": { "version": "file:packages/core", "requires": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/imperative": "5.22.2", + "@zowe/cli-test-utils": "7.23.3", + "@zowe/imperative": "5.22.3", "comment-json": "4.1.1", "string-width": "4.2.3" } @@ -32177,9 +32177,9 @@ "version": "file:packages/provisioning", "requires": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", "js-yaml": "4.1.0" } }, @@ -32193,18 +32193,18 @@ "@zowe/zos-console-for-zowe-sdk": { "version": "file:packages/zosconsole", "requires": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" } }, "@zowe/zos-files-for-zowe-sdk": { "version": "file:packages/zosfiles", "requires": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/zos-uss-for-zowe-sdk": "7.23.2", + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/zos-uss-for-zowe-sdk": "7.23.3", "get-stream": "6.0.1", "minimatch": "5.0.1" }, @@ -32230,53 +32230,53 @@ "@zowe/zos-jobs-for-zowe-sdk": { "version": "file:packages/zosjobs", "requires": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/zos-files-for-zowe-sdk": "7.23.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/zos-files-for-zowe-sdk": "7.23.3" } }, "@zowe/zos-logs-for-zowe-sdk": { "version": "file:packages/zoslogs", "requires": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" } }, "@zowe/zos-tso-for-zowe-sdk": { "version": "file:packages/zostso", "requires": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/zosmf-for-zowe-sdk": "7.23.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/zosmf-for-zowe-sdk": "7.23.3" } }, "@zowe/zos-uss-for-zowe-sdk": { "version": "file:packages/zosuss", "requires": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.2", - "@zowe/imperative": "5.22.2", + "@zowe/cli-test-utils": "7.23.3", + "@zowe/imperative": "5.22.3", "ssh2": "1.15.0" } }, "@zowe/zos-workflows-for-zowe-sdk": { "version": "file:packages/workflows", "requires": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/zos-files-for-zowe-sdk": "7.23.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/zos-files-for-zowe-sdk": "7.23.3" } }, "@zowe/zosmf-for-zowe-sdk": { "version": "file:packages/zosmf", "requires": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" } }, "abbrev": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 82d6903b63..0faea6dd27 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", "license": "EPL-2.0", @@ -58,17 +58,17 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/provisioning-for-zowe-sdk": "7.23.2", - "@zowe/zos-console-for-zowe-sdk": "7.23.2", - "@zowe/zos-files-for-zowe-sdk": "7.23.2", - "@zowe/zos-jobs-for-zowe-sdk": "7.23.2", - "@zowe/zos-logs-for-zowe-sdk": "7.23.2", - "@zowe/zos-tso-for-zowe-sdk": "7.23.2", - "@zowe/zos-uss-for-zowe-sdk": "7.23.2", - "@zowe/zos-workflows-for-zowe-sdk": "7.23.2", - "@zowe/zosmf-for-zowe-sdk": "7.23.2", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/provisioning-for-zowe-sdk": "7.23.3", + "@zowe/zos-console-for-zowe-sdk": "7.23.3", + "@zowe/zos-files-for-zowe-sdk": "7.23.3", + "@zowe/zos-jobs-for-zowe-sdk": "7.23.3", + "@zowe/zos-logs-for-zowe-sdk": "7.23.3", + "@zowe/zos-tso-for-zowe-sdk": "7.23.3", + "@zowe/zos-uss-for-zowe-sdk": "7.23.3", + "@zowe/zos-workflows-for-zowe-sdk": "7.23.3", + "@zowe/zosmf-for-zowe-sdk": "7.23.3", "find-process": "1.4.7", "get-stream": "6.0.1", "lodash": "4.17.21", @@ -79,7 +79,7 @@ "@types/diff": "^5.0.2", "@types/lodash": "^4.14.175", "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.23.2", + "@zowe/cli-test-utils": "7.23.3", "comment-json": "^4.1.1", "strip-ansi": "^6.0.1", "which": "^2.0.2" diff --git a/packages/core/package.json b/packages/core/package.json index 50da6bc262..1e9960132e 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Core libraries shared by Zowe SDK packages", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ "string-width": "4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/imperative": "^5.0.0" diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index dadb05ac1e..3993056153 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Imperative package will be documented in this file. -## Recent Changes +## `5.22.3` - BugFix: Resolved issue in `ProfileInfo` where schema comparisons fail, specifically when comparing the cached schema against a command-based schema during registration. diff --git a/packages/imperative/package.json b/packages/imperative/package.json index c989c80329..092a4036be 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "5.22.2", + "version": "5.22.3", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index 5f807ea3f3..a0adb976ca 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with the z/OS provisioning APIs", "author": "Zowe", "license": "EPL-2.0", @@ -49,9 +49,9 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/workflows/package.json b/packages/workflows/package.json index 7cc15b5dd1..0ed3eb51e0 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.2" + "@zowe/zos-files-for-zowe-sdk": "7.23.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index 509b25e88e..3360046856 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with the z/OS console", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index b79839a844..5a1bddc72a 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -50,10 +50,10 @@ "minimatch": "5.0.1" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2", - "@zowe/zos-uss-for-zowe-sdk": "7.23.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3", + "@zowe/zos-uss-for-zowe-sdk": "7.23.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index a7c0616028..a174d1f295 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,12 +46,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.23.2" + "@zowe/zos-files-for-zowe-sdk": "7.23.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index f4b6aa6b7a..6d784dd31d 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with the z/OS logs", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index f39f3f80bf..b22e49d757 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with the z/OS Management Facility", "author": "Zowe", "license": "EPL-2.0", @@ -44,9 +44,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zostso/package.json b/packages/zostso/package.json index c12c45c85c..d3d8c084a1 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with TSO on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.23.2" + "@zowe/zosmf-for-zowe-sdk": "7.23.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.23.2", - "@zowe/core-for-zowe-sdk": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/core-for-zowe-sdk": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^7.0.0", diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index bba4026adb..04cd27c34c 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.23.2", + "version": "7.23.3", "description": "Zowe SDK to interact with USS on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ }, "devDependencies": { "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.23.2", - "@zowe/imperative": "5.22.2" + "@zowe/cli-test-utils": "7.23.3", + "@zowe/imperative": "5.22.3" }, "peerDependencies": { "@zowe/imperative": "^5.2.0" From 52ea42826ead3866109f5615c5c78a4ad6f9b01b Mon Sep 17 00:00:00 2001 From: "Andrew W. Harn" Date: Thu, 15 Feb 2024 20:42:17 +0000 Subject: [PATCH 83/92] Add missing yields and other fixes Signed-off-by: Andrew W. Harn --- packages/cli/CHANGELOG.md | 4 + packages/imperative/CHANGELOG.md | 4 + .../lib/sample-plugin/cmd/bar/bar.handler.js | 1 + .../lib/sample-plugin/cmd/foo/foo.handler.js | 1 + .../lib/sample-plugin/healthCheck.handler.js | 2 +- .../healthCheck.handler.js | 1 + .../healthCheck.handler.js | 1 + .../lib/sample-plugin/cmd/bar/bar.handler.js | 1 + .../lib/sample-plugin/cmd/foo/foo.handler.js | 1 + .../lib/sample-plugin/healthCheck.handler.js | 2 +- .../lib/sample-plugin/cmd/bar/bar.handler.js | 1 + .../lib/sample-plugin/cmd/foo/foo.handler.js | 1 + .../lib/sample-plugin/healthCheck.handler.js | 2 +- .../lib/sample-plugin/cmd/bar/bar.handler.js | 1 + .../lib/sample-plugin/cmd/foo/foo.handler.js | 1 + .../globgroup/globcmd1/globcmd1.handler.js | 1 + .../globgroup/globcmd2/globcmd2.handler.js | 1 + .../lib/sample-plugin/healthCheck.handler.js | 1 + .../imperative-apis/imperativeApis.handler.js | 1 + .../imperativeConfig.handler.js | 1 + .../imperativeLogging.handler.js | 1 + .../lib/sample-plugin/healthCheck.handler.js | 2 +- .../lib/sample-plugin/cmd/bar/bar.handler.js | 1 + .../lib/sample-plugin/cmd/foo/foo.handler.js | 1 + .../lib/sample-plugin/healthCheck.handler.js | 2 +- .../lifeCycle/class_good_lifeCycle.js | 2 + .../overrides/CredentialManager.override.js | 4 +- .../lib/sample-plugin/cmd/bar/bar.handler.js | 1 + .../lib/sample-plugin/cmd/foo/foo.handler.js | 1 + .../lib/sample-plugin/healthCheck.handler.js | 2 +- .../src/imperative/src/Imperative.ts | 374 +++++++++--------- .../convert-profiles.handler.ts | 2 +- .../src/abstract/AbstractCredentialManager.ts | 4 +- packages/imperative/web-diff/index.html | 3 +- packages/imperative/web-help/dist/index.html | 2 +- .../zosfiles/src/methods/upload/Upload.ts | 2 +- packages/zosuss/src/Shell.ts | 1 - 37 files changed, 231 insertions(+), 203 deletions(-) diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 55ba8ed0a2..0ff2eec0b4 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Zowe CLI package will be documented in this file. +## Recent Changes + +- BugFix: Fixed race condition in `config convert-profiles` command that may fail to delete secure values for old profiles + ## `7.23.2` - BugFix: Resolved technical currency by updating `socks` transitive dependency diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 3993056153..8f48f00fb6 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- BugFix: Fixed race condition in `config convert-profiles` command that may fail to delete secure values for old profiles + ## `5.22.3` - BugFix: Resolved issue in `ProfileInfo` where schema comparisons fail, specifically when comparing the cached schema against a command-based schema during registration. diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/cmd/bar/bar.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/cmd/bar/bar.handler.js index ce5d45ad93..f699259a0d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/cmd/bar/bar.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/cmd/bar/bar.handler.js @@ -15,6 +15,7 @@ class BarHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("@TODO Complete this command: bar"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/cmd/foo/foo.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/cmd/foo/foo.handler.js index ca9a85c2ae..6b63091553 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/cmd/foo/foo.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/cmd/foo/foo.handler.js @@ -12,6 +12,7 @@ class FooHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("Invoked sample-plugin foo handler"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/healthCheck.handler.js index 9254a82bef..5c482dba54 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/lib/sample-plugin/healthCheck.handler.js @@ -12,7 +12,7 @@ class HealthCheckHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { console.log("Invoked health check handler"); - params.response.build(); + yield params.response.build(); }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_in_plugin/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_in_plugin/healthCheck.handler.js index 4e98338f1b..38a280876d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_in_plugin/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_in_plugin/healthCheck.handler.js @@ -26,6 +26,7 @@ class HealthCheckHandler { const impFileLogger = imperative_cli_1.Logger.getImperativeLogger(); impFileLogger.debug("Invoked health check handler"); params.response.console.log("You would report problems identified by healthCheck."); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_with_cli/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_with_cli/healthCheck.handler.js index 4e98338f1b..38a280876d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_with_cli/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_with_cli/healthCheck.handler.js @@ -26,6 +26,7 @@ class HealthCheckHandler { const impFileLogger = imperative_cli_1.Logger.getImperativeLogger(); impFileLogger.debug("Invoked health check handler"); params.response.console.log("You would report problems identified by healthCheck."); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/cmd/bar/bar.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/cmd/bar/bar.handler.js index ce5d45ad93..f699259a0d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/cmd/bar/bar.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/cmd/bar/bar.handler.js @@ -15,6 +15,7 @@ class BarHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("@TODO Complete this command: bar"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/cmd/foo/foo.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/cmd/foo/foo.handler.js index ca9a85c2ae..6b63091553 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/cmd/foo/foo.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/cmd/foo/foo.handler.js @@ -12,6 +12,7 @@ class FooHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("Invoked sample-plugin foo handler"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/healthCheck.handler.js index 9254a82bef..5c482dba54 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/lib/sample-plugin/healthCheck.handler.js @@ -12,7 +12,7 @@ class HealthCheckHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { console.log("Invoked health check handler"); - params.response.build(); + yield params.response.build(); }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/cmd/bar/bar.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/cmd/bar/bar.handler.js index ce5d45ad93..f699259a0d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/cmd/bar/bar.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/cmd/bar/bar.handler.js @@ -15,6 +15,7 @@ class BarHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("@TODO Complete this command: bar"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/cmd/foo/foo.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/cmd/foo/foo.handler.js index ca9a85c2ae..6b63091553 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/cmd/foo/foo.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/cmd/foo/foo.handler.js @@ -12,6 +12,7 @@ class FooHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("Invoked sample-plugin foo handler"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/healthCheck.handler.js index 9254a82bef..5c482dba54 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/lib/sample-plugin/healthCheck.handler.js @@ -12,7 +12,7 @@ class HealthCheckHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { console.log("Invoked health check handler"); - params.response.build(); + yield params.response.build(); }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/bar/bar.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/bar/bar.handler.js index 59718d22de..340c1efcc7 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/bar/bar.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/bar/bar.handler.js @@ -18,6 +18,7 @@ class BarHandler { // const impFileLogger = imperative_cli_1.Logger.getImperativeLogger(); // impFileLogger.debug("Invoked normal-plugin-3 bar handler"); params.response.console.log("You have executed the Bar command!"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/foo/foo.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/foo/foo.handler.js index b5a3ca2d8e..32459f2b30 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/foo/foo.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/foo/foo.handler.js @@ -18,6 +18,7 @@ class FooHandler { profile.size + " and duration = " + profile.duration; // impFileLogger.debug(successMsg); params.response.console.log(successMsg); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/globgroup/globcmd1/globcmd1.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/globgroup/globcmd1/globcmd1.handler.js index c1a4cc8a1a..8bb47e215d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/globgroup/globcmd1/globcmd1.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/globgroup/globcmd1/globcmd1.handler.js @@ -18,6 +18,7 @@ class GlobCmd1Handler { const impFileLogger = imperative_cli_1.Logger.getImperativeLogger(); impFileLogger.debug("Invoked sample-plugin globcmd1 handler"); params.response.console.log("You have executed the globcmd1 command. It's definition was processed by globs."); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/globgroup/globcmd2/globcmd2.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/globgroup/globcmd2/globcmd2.handler.js index 1f40f53f53..fb74e880bb 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/globgroup/globcmd2/globcmd2.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/globgroup/globcmd2/globcmd2.handler.js @@ -18,6 +18,7 @@ class GlobCmd2Handler { const impFileLogger = imperative_cli_1.Logger.getImperativeLogger(); impFileLogger.debug("Invoked sample-plugin globcmd2 handler"); params.response.console.log("You have executed the globcmd2 command. It's definition was processed by globs."); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/healthCheck.handler.js index 414a67deca..10da25d79b 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/healthCheck.handler.js @@ -15,6 +15,7 @@ class HealthCheckHandler { const impFileLogger = imperative_cli_1.Logger.getImperativeLogger(); impFileLogger.debug("Invoked health check handler"); params.response.console.log("You would report problems identified by healthCheck."); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-apis/imperativeApis.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-apis/imperativeApis.handler.js index 73bd714d73..1df6d5ebcc 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-apis/imperativeApis.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-apis/imperativeApis.handler.js @@ -35,6 +35,7 @@ class ImperativeApisHandler { } else { throw new T.ImperativeError({msg: "Imperative APIs appLogger is not accessible from the test plugin"}); } + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-config/imperativeConfig.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-config/imperativeConfig.handler.js index c8a7428cd3..c56271021a 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-config/imperativeConfig.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-config/imperativeConfig.handler.js @@ -54,6 +54,7 @@ class ImperativeConfigHandler { } else { throw new T.ImperativeError({msg: "Imperative configuration does not contain the expected profiles"}); } + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-logging/imperativeLogging.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-logging/imperativeLogging.handler.js index e3d7f9c9d9..8ae0fe9225 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-logging/imperativeLogging.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-logging/imperativeLogging.handler.js @@ -33,6 +33,7 @@ class ImperativeLoggingHandler { params.response.console.log(`${params.arguments.test}: Messages logged successfully to the following locations`); params.response.console.log(path.join(config.defaultHome, "imperative", "logs", "imperative.log")); params.response.console.log(path.join(config.defaultHome, config.name, "logs", config.name + ".log")); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/healthCheck.handler.js index 9254a82bef..5c482dba54 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/healthCheck.handler.js @@ -12,7 +12,7 @@ class HealthCheckHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { console.log("Invoked health check handler"); - params.response.build(); + yield params.response.build(); }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/cmd/bar/bar.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/cmd/bar/bar.handler.js index ce5d45ad93..f699259a0d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/cmd/bar/bar.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/cmd/bar/bar.handler.js @@ -15,6 +15,7 @@ class BarHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("@TODO Complete this command: bar"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/cmd/foo/foo.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/cmd/foo/foo.handler.js index ca9a85c2ae..6b63091553 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/cmd/foo/foo.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/cmd/foo/foo.handler.js @@ -12,6 +12,7 @@ class FooHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("Invoked sample-plugin foo handler"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/healthCheck.handler.js index 9254a82bef..5c482dba54 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/healthCheck.handler.js @@ -12,7 +12,7 @@ class HealthCheckHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { console.log("Invoked health check handler"); - params.response.build(); + yield params.response.build(); }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/lifeCycle/class_good_lifeCycle.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/lifeCycle/class_good_lifeCycle.js index c349da6c3e..996a24d4bb 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/lifeCycle/class_good_lifeCycle.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/lifeCycle/class_good_lifeCycle.js @@ -18,12 +18,14 @@ class PluginLifeCycle extends imperative_1.AbstractPluginLifeCycle { return __awaiter(this, void 0, void 0, function* () { imperative_1.CredentialManagerOverride.recordCredMgrInConfig(credMgrDisplayName); imperative_1.Logger.getImperativeLogger().debug("The plugin did a post-install action"); + yield undefined; }); } async preUninstall() { return __awaiter(this, void 0, void 0, function* () { imperative_1.CredentialManagerOverride.recordDefaultCredMgrInConfig(credMgrDisplayName); imperative_1.Logger.getImperativeLogger().debug("The plugin did a pre-uninstall action"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/overrides/CredentialManager.override.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/overrides/CredentialManager.override.js index 2303e1c668..f4a29aeb51 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/overrides/CredentialManager.override.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/overrides/CredentialManager.override.js @@ -29,6 +29,7 @@ module.exports = class CredentialManagerOverrides extends imperative_1.AbstractC this.consoleLog.info("CredentialManager in sample-plugin is deleting:\n" + ` service = ${this.service}\n` + ` account = ${account}`); + yield undefined; }); } loadCredentials(account) { @@ -42,7 +43,7 @@ module.exports = class CredentialManagerOverrides extends imperative_1.AbstractC failNotFound: true }; const loadResultString = JSON.stringify(loadedProfResult, null, 2); - return Buffer.from(loadResultString).toString("base64"); + yield Buffer.from(loadResultString).toString("base64"); }); } saveCredentials(account, credentials) { @@ -51,6 +52,7 @@ module.exports = class CredentialManagerOverrides extends imperative_1.AbstractC ` service = ${this.service}\n` + ` account = ${account}\n` + ` credentials = ${credentials.length * Math.random()}`); + yield undefined; }); } }; diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/cmd/bar/bar.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/cmd/bar/bar.handler.js index ce5d45ad93..f699259a0d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/cmd/bar/bar.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/cmd/bar/bar.handler.js @@ -15,6 +15,7 @@ class BarHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("@TODO Complete this command: bar"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/cmd/foo/foo.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/cmd/foo/foo.handler.js index ca9a85c2ae..6b63091553 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/cmd/foo/foo.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/cmd/foo/foo.handler.js @@ -12,6 +12,7 @@ class FooHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { params.response.console.log("Invoked sample-plugin foo handler"); + yield undefined; }); } } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/healthCheck.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/healthCheck.handler.js index 9254a82bef..5c482dba54 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/healthCheck.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/lib/sample-plugin/healthCheck.handler.js @@ -12,7 +12,7 @@ class HealthCheckHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { console.log("Invoked health check handler"); - params.response.build(); + yield params.response.build(); }); } } diff --git a/packages/imperative/src/imperative/src/Imperative.ts b/packages/imperative/src/imperative/src/Imperative.ts index 8f6c53e201..4eafe5ee27 100644 --- a/packages/imperative/src/imperative/src/Imperative.ts +++ b/packages/imperative/src/imperative/src/Imperative.ts @@ -24,7 +24,6 @@ import { IImperativeApi } from "./api/doc/IImperativeApi"; import { Constants } from "../../constants/src/Constants"; import { TextUtils } from "../../utilities/src/TextUtils"; import { ImperativeConfig } from "../../utilities/src/ImperativeConfig"; -import { ImperativeReject } from "../../interfaces/src/types/ImperativeReject"; import { LoggingConfigurer } from "./LoggingConfigurer"; import { ImperativeError } from "../../error"; import { PluginManagementFacility } from "./plugins/PluginManagementFacility"; @@ -123,219 +122,216 @@ export class Imperative { * * @returns {Promise} A promise indicating that we are done here. */ - public static init(config?: IImperativeConfig): Promise { - // eslint-disable-next-line no-async-promise-executor - return new Promise(async (initializationComplete: () => void, initializationFailed: ImperativeReject) => { + public static async init(config?: IImperativeConfig): Promise { + try { + + /** + * Config Logger Manager to enable log messages in memory prior to logger init. + */ + Logger.setLogInMemory(true); + + /** + * Identify caller's location on the system + */ + ImperativeConfig.instance.callerLocation = process.mainModule.filename; + + /** + * Load callers configuration, validate, and save + */ + config = ConfigurationLoader.load(config, ImperativeConfig.instance.callerPackageJson, + ImperativeConfig.instance.getCallerFile + ); + ConfigurationValidator.validate(config); + ImperativeConfig.instance.loadedConfig = config; + + /** + * Get the command name from the package bin. + * If no command name exists, we will instead use the file name invoked + * and log a debug warning. + */ + if (ImperativeConfig.instance.findPackageBinName() != null) { + this.mRootCommandName = ImperativeConfig.instance.findPackageBinName(); + } else { + this.mRootCommandName = ImperativeConfig.instance.callerLocation; + this.log.debug("WARNING: No \"bin\" configuration was found in your package.json," + + " or your package.json could not be found. " + + "Defaulting command name to filepath instead."); + } + ImperativeConfig.instance.rootCommandName = this.mRootCommandName; + + let delayedEnvFileSetupError = undefined; try { + EnvFileUtils.setEnvironmentForApp(ImperativeConfig.instance.rootCommandName, true, ImperativeConfig.instance.envVariablePrefix); + } catch (err) { + delayedEnvFileSetupError = err; + } - /** - * Config Logger Manager to enable log messages in memory prior to logger init. - */ - Logger.setLogInMemory(true); - - /** - * Identify caller's location on the system - */ - ImperativeConfig.instance.callerLocation = process.mainModule.filename; - - /** - * Load callers configuration, validate, and save - */ - config = ConfigurationLoader.load(config, ImperativeConfig.instance.callerPackageJson, - ImperativeConfig.instance.getCallerFile - ); - ConfigurationValidator.validate(config); - ImperativeConfig.instance.loadedConfig = config; - - /** - * Get the command name from the package bin. - * If no command name exists, we will instead use the file name invoked - * and log a debug warning. - */ - if (ImperativeConfig.instance.findPackageBinName() != null) { - this.mRootCommandName = ImperativeConfig.instance.findPackageBinName(); - } else { - this.mRootCommandName = ImperativeConfig.instance.callerLocation; - this.log.debug("WARNING: No \"bin\" configuration was found in your package.json," + - " or your package.json could not be found. " + - "Defaulting command name to filepath instead."); - } - ImperativeConfig.instance.rootCommandName = this.mRootCommandName; + // Initialize our settings file + this.initAppSettings(); - let delayedEnvFileSetupError = undefined; - try { - EnvFileUtils.setEnvironmentForApp(ImperativeConfig.instance.rootCommandName, true, ImperativeConfig.instance.envVariablePrefix); - } catch (err) { - delayedEnvFileSetupError = err; - } + // If config group is enabled add config commands + if (config.allowConfigGroup) { + const ConfigManagementFacility = require("./config/ConfigManagementFacility"); // Delayed load req for init help text to work + ConfigManagementFacility.ConfigManagementFacility.instance.init(); + } - // Initialize our settings file - this.initAppSettings(); + let delayedConfigLoadError = undefined; - // If config group is enabled add config commands - if (config.allowConfigGroup) { - const ConfigManagementFacility = require("./config/ConfigManagementFacility"); // Delayed load req for init help text to work - ConfigManagementFacility.ConfigManagementFacility.instance.init(); - } + // Load the base config, save any error from config load + const configAppName = ImperativeConfig.instance.findPackageBinName() ? this.mRootCommandName : config.name; - let delayedConfigLoadError = undefined; + try { + ImperativeConfig.instance.config = await Config.load(configAppName, + { homeDir: ImperativeConfig.instance.cliHome } + ); + } catch (err) { + delayedConfigLoadError = err; + } - // Load the base config, save any error from config load - const configAppName = ImperativeConfig.instance.findPackageBinName() ? this.mRootCommandName : config.name; + // If plugins are allowed, enable core plugins commands + if (config.allowPlugins) { + PluginManagementFacility.instance.init(); - try { - ImperativeConfig.instance.config = await Config.load(configAppName, - { homeDir: ImperativeConfig.instance.cliHome } - ); - } catch (err) { - delayedConfigLoadError = err; - } + // load the configuration of every installed plugin for later processing + PluginManagementFacility.instance.loadAllPluginCfgProps(); - // If plugins are allowed, enable core plugins commands - if (config.allowPlugins) { - PluginManagementFacility.instance.init(); + // Override the config object with things loaded from plugins + Object.assign( + ImperativeConfig.instance.loadedConfig.overrides, + PluginManagementFacility.instance.pluginOverrides + ); + } - // load the configuration of every installed plugin for later processing - PluginManagementFacility.instance.loadAllPluginCfgProps(); + /** + * Once we have a complete representation of the config object, we should be able to + * use that and populate all required categories and expose them on our API object + * so that an app using imperative can write to the imperative log, its own log, or + * even a plug-in log. + * + * Any other initialization added to this routine should occur after logging has been initialized. + */ + this.initLogging(); + + /** + * If there was an error trying to load the user's environment variable configuration, tell them about it now. + * Do not stop the process from running. + */ + if (delayedEnvFileSetupError) { + const appLogger = Logger.getAppLogger(); + appLogger.logError(delayedEnvFileSetupError); + new Console().error(delayedEnvFileSetupError); + } - // Override the config object with things loaded from plugins - Object.assign( - ImperativeConfig.instance.loadedConfig.overrides, - PluginManagementFacility.instance.pluginOverrides + /** + * If there was an error trying to load the user's configuration, tell them about it now. + */ + if (delayedConfigLoadError) { + if (config.daemonMode) { + ImperativeConfig.instance.config = await Config.load(configAppName, + { + homeDir: ImperativeConfig.instance.cliHome, + noLoad: true + } ); + const imperativeLogger = Logger.getImperativeLogger(); + imperativeLogger.logError(delayedConfigLoadError); + } else { + throw delayedConfigLoadError; } + } - /** - * Once we have a complete representation of the config object, we should be able to - * use that and populate all required categories and expose them on our API object - * so that an app using imperative can write to the imperative log, its own log, or - * even a plug-in log. - * - * Any other initialization added to this routine should occur after logging has been initialized. - */ - this.initLogging(); - - /** - * If there was an error trying to load the user's environment variable configuration, tell them about it now. - * Do not stop the process from running. - */ - if (delayedEnvFileSetupError) { - const appLogger = Logger.getAppLogger(); - appLogger.logError(delayedEnvFileSetupError); - new Console().error(delayedEnvFileSetupError); - } - - /** - * If there was an error trying to load the user's configuration, tell them about it now. - */ - if (delayedConfigLoadError) { - if (config.daemonMode) { - ImperativeConfig.instance.config = await Config.load(configAppName, - { - homeDir: ImperativeConfig.instance.cliHome, - noLoad: true - } - ); - const imperativeLogger = Logger.getImperativeLogger(); - imperativeLogger.logError(delayedConfigLoadError); - } else { - throw delayedConfigLoadError; - } - } - - /** - * Now we should apply any overrides to default Imperative functionality. This is where CLI - * developers are able to really start customizing Imperative and how it operates internally. - * For the "config convert-profiles" command, we skip loading the CredentialManager override - * because we need to be able to uninstall the plugin that provides it. - */ - // eslint-disable-next-line @typescript-eslint/no-magic-numbers - if (!(process.argv.length > 3 && process.argv[2] === "config" && process.argv[3].startsWith("convert"))) { - await OverridesLoader.load(ImperativeConfig.instance.loadedConfig, - ImperativeConfig.instance.callerPackageJson); - } + /** + * Now we should apply any overrides to default Imperative functionality. This is where CLI + * developers are able to really start customizing Imperative and how it operates internally. + * For the "config convert-profiles" command, we skip loading the CredentialManager override + * because we need to be able to uninstall the plugin that provides it. + */ + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + if (!(process.argv.length > 3 && process.argv[2] === "config" && process.argv[3].startsWith("convert"))) { + await OverridesLoader.load(ImperativeConfig.instance.loadedConfig, + ImperativeConfig.instance.callerPackageJson); + } - /** - * Build API object - */ - this.mApi = this.constructApiObject(); + /** + * Build API object + */ + this.mApi = this.constructApiObject(); - /** - * Build the help generator factory - requires the root command name and the loaded configuration document - */ - this.mHelpGeneratorFactory = new ImperativeHelpGeneratorFactory(this.rootCommandName, ImperativeConfig.instance.loadedConfig); + /** + * Build the help generator factory - requires the root command name and the loaded configuration document + */ + this.mHelpGeneratorFactory = new ImperativeHelpGeneratorFactory(this.rootCommandName, ImperativeConfig.instance.loadedConfig); - // resolve command module globs, forming the root of the CLI command tree - this.log.info(`Loaded and validated config for '${config.name}'. Config details at trace level of logging.`); - this.log.trace(`The config object for '${config.name}' is:\n` + - JSON.stringify(config, null, 2) - ); - const resolvedHostCliCmdTree: ICommandDefinition = this.getResolvedCmdTree(config); + // resolve command module globs, forming the root of the CLI command tree + this.log.info(`Loaded and validated config for '${config.name}'. Config details at trace level of logging.`); + this.log.trace(`The config object for '${config.name}' is:\n` + + JSON.stringify(config, null, 2) + ); + const resolvedHostCliCmdTree: ICommandDefinition = this.getResolvedCmdTree(config); - // If plugins are allowed, add plugins' commands and profiles to the CLI command tree - if (config.allowPlugins) { - PluginManagementFacility.instance.addAllPluginsToHostCli(resolvedHostCliCmdTree); - this.log.info("Plugins added to the CLI command tree."); - } + // If plugins are allowed, add plugins' commands and profiles to the CLI command tree + if (config.allowPlugins) { + PluginManagementFacility.instance.addAllPluginsToHostCli(resolvedHostCliCmdTree); + this.log.info("Plugins added to the CLI command tree."); + } - // final preparation of the command tree - const preparedHostCliCmdTree = this.getPreparedCmdTree(resolvedHostCliCmdTree, config.baseProfile); + // final preparation of the command tree + const preparedHostCliCmdTree = this.getPreparedCmdTree(resolvedHostCliCmdTree, config.baseProfile); - /** - * Only initialize the old-school profile environment - * if we are not in team-config mode. - */ - if (ImperativeConfig.instance.config.exists === false) { - await this.initProfiles(config); - } + /** + * Only initialize the old-school profile environment + * if we are not in team-config mode. + */ + if (ImperativeConfig.instance.config.exists === false) { + await this.initProfiles(config); + } - /** - * Define all known commands - */ - this.log.info("Inherited traits applied to CLI command tree children. " + - "Cmd tree details at trace level of logging." - ); - this.log.trace("The CLI command tree before being defined to yargs: " + - JSON.stringify(preparedHostCliCmdTree, null, 2) - ); - this.defineCommands(preparedHostCliCmdTree); + /** + * Define all known commands + */ + this.log.info("Inherited traits applied to CLI command tree children. " + + "Cmd tree details at trace level of logging." + ); + this.log.trace("The CLI command tree before being defined to yargs: " + + JSON.stringify(preparedHostCliCmdTree, null, 2) + ); + this.defineCommands(preparedHostCliCmdTree); - /** - * Notify caller initialization is complete - */ - initializationComplete(); + /** + * Notify caller initialization is complete + */ + return Promise.resolve(); - } catch (error) { - const imperativeLogger = Logger.getImperativeLogger(); - if (error?.suppressDump) { - imperativeLogger.fatal(error.message); // Error generated by a bad config is printed - } else { - imperativeLogger.fatal(require("util").inspect(error)); - const os = require("os"); - imperativeLogger.fatal("Diagnostic information:\n" + - "Platform: '%s', Architecture: '%s', Process.argv: '%s'\n" + - "Node versions: '%s'" + - "Environmental variables: '%s'", - os.platform(), os.arch(), process.argv.join(" "), - JSON.stringify(process.versions, null, 2), - JSON.stringify(process.env, null, 2)); - Logger.writeInMemoryMessages(Imperative.DEFAULT_DEBUG_FILE); - if (error.report) { - const {writeFileSync} = require("fs"); - writeFileSync(Imperative.DEFAULT_DEBUG_FILE, error.report); - } - if (!(error instanceof ImperativeError)) { - const oldError = error; - error = new ImperativeError({ // eslint-disable-line no-ex-assign - msg: "Unexpected Error Encountered", - causeErrors: error - }); - error.stack = "\n" + oldError.stack; - } + } catch (error) { + const imperativeLogger = Logger.getImperativeLogger(); + if (error?.suppressDump) { + imperativeLogger.fatal(error.message); // Error generated by a bad config is printed + } else { + imperativeLogger.fatal(require("util").inspect(error)); + const os = require("os"); + imperativeLogger.fatal("Diagnostic information:\n" + + "Platform: '%s', Architecture: '%s', Process.argv: '%s'\n" + + "Node versions: '%s'" + + "Environmental variables: '%s'", + os.platform(), os.arch(), process.argv.join(" "), + JSON.stringify(process.versions, null, 2), + JSON.stringify(process.env, null, 2)); + Logger.writeInMemoryMessages(Imperative.DEFAULT_DEBUG_FILE); + if (error.report) { + const {writeFileSync} = require("fs"); + writeFileSync(Imperative.DEFAULT_DEBUG_FILE, error.report); + } + if (!(error instanceof ImperativeError)) { + const oldError = error; + error = new ImperativeError({ // eslint-disable-line no-ex-assign + msg: "Unexpected Error Encountered", + causeErrors: error + }); + error.stack = "\n" + oldError.stack; } - initializationFailed(error); } - }); + return Promise.reject(error); + } } /** diff --git a/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.handler.ts b/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.handler.ts index 43c7113c2c..966ff24249 100644 --- a/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.handler.ts @@ -173,7 +173,7 @@ export default class ConvertProfilesHandler implements ICommandHandler { const accounts = await this.findOldSecureProps(service, params); for (const account of accounts) { if (!account.includes("secure_config_props")) { - const success = this.deleteOldSecureProps(service, account, params); + const success = await this.deleteOldSecureProps(service, account, params); params.response.console.log(`Deleting secure value for "${service}/${account}"... ${success ? "done" : "failed"}`); } } diff --git a/packages/imperative/src/security/src/abstract/AbstractCredentialManager.ts b/packages/imperative/src/security/src/abstract/AbstractCredentialManager.ts index bbf6dd2b59..a01ec4af0b 100644 --- a/packages/imperative/src/security/src/abstract/AbstractCredentialManager.ts +++ b/packages/imperative/src/security/src/abstract/AbstractCredentialManager.ts @@ -143,11 +143,11 @@ export abstract class AbstractCredentialManager { } /** - * @returns {string[]} - List of possible solutions for credential manager errors. + * @returns {string[] | undefined} - List of possible solutions for credential manager errors. * Override this in your CredentialManager to supply more detailed error messages. */ protected get possibleSolutions(): string[] | undefined { - return; + return undefined; } /** diff --git a/packages/imperative/web-diff/index.html b/packages/imperative/web-diff/index.html index f273c4082f..5d6c26c86d 100644 --- a/packages/imperative/web-diff/index.html +++ b/packages/imperative/web-diff/index.html @@ -11,9 +11,10 @@ */ --> - + + Web Diff
- +