391 lines
14 KiB
PowerShell
391 lines
14 KiB
PowerShell
|
function New-AlkamiManifest {
|
|||
|
<#
|
|||
|
.SYNOPSIS
|
|||
|
Create a new AlkamiManifest.xml (v 1.0) in a specified location for a known type.
|
|||
|
|
|||
|
.PARAMETER Type
|
|||
|
The type of manifest to be created
|
|||
|
|
|||
|
.PARAMETER Destination
|
|||
|
The target folder location where the manifest is going to be created. Defaults to the current folder.
|
|||
|
|
|||
|
.PARAMETER ProjectLocation
|
|||
|
The location of the project file to use for manifest creation. Defaults to looking in the current folder.
|
|||
|
|
|||
|
.PARAMETER FileType
|
|||
|
Create files in xml or json format
|
|||
|
|
|||
|
.PARAMETER Force
|
|||
|
Used to overwrite existing files
|
|||
|
#>
|
|||
|
[CmdletBinding()]
|
|||
|
Param(
|
|||
|
[Parameter(Position = 0, Mandatory = $true)]
|
|||
|
[ValidateNotNullOrEmpty()]
|
|||
|
[ValidateSet('Widget', 'Service', 'Migration', 'Theme', 'WebApplication', 'WebExtension', 'Repository', 'Provider', 'WebSite', 'LegacyUtility', 'Hotfix', 'ApiComponent')]
|
|||
|
[String]$Type,
|
|||
|
|
|||
|
[Parameter(Position = 1, Mandatory = $false)]
|
|||
|
[Alias('Path', 'Folder', 'Target')]
|
|||
|
[String]$Destination,
|
|||
|
|
|||
|
[Parameter(Position = 2, Mandatory = $false)]
|
|||
|
[String]$ProjectLocation,
|
|||
|
|
|||
|
[Parameter(Position = 3, Mandatory = $false)]
|
|||
|
[ValidateSet('Xml', 'Json')]
|
|||
|
[string]$FileType = 'Xml',
|
|||
|
|
|||
|
[Switch]$Force
|
|||
|
)
|
|||
|
process {
|
|||
|
$logLead = (Get-LogLeadName)
|
|||
|
|
|||
|
$widgetType = 'Widget'
|
|||
|
$serviceType = 'Service'
|
|||
|
$migrationType = 'Migration'
|
|||
|
$themeType = 'Theme'
|
|||
|
$webApplicationType = 'WebApplication'
|
|||
|
$webExtensionType = 'WebExtension'
|
|||
|
$repositoryType = 'Repository'
|
|||
|
$providerType = 'Provider'
|
|||
|
$websiteType = 'WebSite'
|
|||
|
$legacyUtilityType = 'LegacyUtility'
|
|||
|
$hotfixType = 'Hotfix'
|
|||
|
$apiComponentType = 'ApiComponent'
|
|||
|
|
|||
|
# Get the current folder so we can put/look for things in the working folder if not specified
|
|||
|
$CurrentWorkingFolder = (Get-Location).Path
|
|||
|
|
|||
|
# The base name is like C:\git\Alkami.Services.Permissions\ <- I want "Alkami.Services.Permissions"
|
|||
|
# The base name can also be derived from the csproj name later
|
|||
|
# So if the folder is C:\git\perms with an Alkami.Services.Permissions.csproj we can absorb that as the basename later
|
|||
|
# The reason for a basename is when we start supporting node or ruby, etc, they don't have an assemblyInfo
|
|||
|
$baseName = (Split-Path $CurrentWorkingFolder -Leaf)
|
|||
|
|
|||
|
if ([string]::IsNullOrWhiteSpace($Destination)) {
|
|||
|
$Destination = $CurrentWorkingFolder
|
|||
|
}
|
|||
|
|
|||
|
# Target path is where we store the final file at
|
|||
|
# Easier to work with non-relative paths. This gives us a full path.
|
|||
|
$targetPath = (Resolve-Path $Destination).Path
|
|||
|
|
|||
|
# Determine where we want to drop the file when we're done
|
|||
|
# Ensure that our target path ends in the manifest filename
|
|||
|
$defaultFilename = "AlkamiManifest.$($FileType.ToLower())"
|
|||
|
|
|||
|
$targetItemIsContainer = (Get-Item $targetPath).PSIsContainer
|
|||
|
|
|||
|
if (!$targetItemIsContainer -and ((Split-Path $targetPath -Leaf) -ne $defaultFilename)) {
|
|||
|
Write-Warning "$logLead : The specified filename is not the expected filename. Matching to required filename."
|
|||
|
$targetPath = (Join-Path (Split-Path $targetPath -Parent) $defaultFilename)
|
|||
|
}
|
|||
|
|
|||
|
# if the target path is a container (is not a file)
|
|||
|
# append the filename
|
|||
|
if ($targetItemIsContainer) {
|
|||
|
$targetPath = (Join-Path $targetPath $defaultFilename)
|
|||
|
}
|
|||
|
|
|||
|
# Target path is now a file that we want to target
|
|||
|
if (!$Force -and (Test-Path $targetPath)) {
|
|||
|
Write-Warning "$logLead : There's already a file at $targetPath - Did you want to Test-AlkamiManifest this file instead? Use -Force to overwrite the existing file."
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
Write-Verbose "$logLead : Getting CSProj"
|
|||
|
if ([string]::IsNullOrWhiteSpace($ProjectLocation)) {
|
|||
|
$ProjectLocation = $CurrentWorkingFolder
|
|||
|
}
|
|||
|
|
|||
|
if (!(Test-Path $ProjectLocation)) {
|
|||
|
Write-Warning "$logLead : Project location does not exist, looking in current folder for a csproj"
|
|||
|
$ProjectLocation = $CurrentWorkingFolder
|
|||
|
}
|
|||
|
|
|||
|
# If it's a folder, look in the folder
|
|||
|
if ((Get-Item $ProjectLocation).PSIsContainer) {
|
|||
|
$csprojFile = ((Get-ChildItem (Join-Path $ProjectLocation "*.csproj") -Recurse) | Sort-Object -Unique | Select-Object -First 1)
|
|||
|
} else {
|
|||
|
# Test path did exist, it wasn't a folder, use that
|
|||
|
$csprojFile = (Get-Item $ProjectLocation)
|
|||
|
}
|
|||
|
|
|||
|
# This could be a node project, or just an empty folder with no content yet
|
|||
|
if ($null -ne $csprojFile) {
|
|||
|
$baseName = (Get-Item $csprojFile).BaseName
|
|||
|
}
|
|||
|
|
|||
|
$assemblyName = $baseName
|
|||
|
$rootNamespace = $baseName
|
|||
|
$creatorCode = ""
|
|||
|
$areaName = ""
|
|||
|
$framework = "framework"
|
|||
|
$splitRoots = @()
|
|||
|
|
|||
|
# If we have a csproj file then let's collect information from it
|
|||
|
if ((![string]::IsNullOrWhiteSpace($csprojFile)) -and (Test-Path $csprojFile)) {
|
|||
|
$xml = [xml](Get-Content $csprojFile.FullName)
|
|||
|
|
|||
|
$rootNamespaces = @($xml.Project.PropertyGroup.RootNamespace)
|
|||
|
if (![string]::IsNullOrWhiteSpace($rootNamespaces[0])) {
|
|||
|
$rootNamespace = $rootNamespaces[0]
|
|||
|
}
|
|||
|
|
|||
|
$assemblyNames = @($xml.Project.PropertyGroup.AssemblyName)
|
|||
|
if (![string]::IsNullOrWhiteSpace($assemblyNames[0])) {
|
|||
|
$assemblyName = $assemblyNames[0]
|
|||
|
}
|
|||
|
|
|||
|
$targetFrameworks = @($xml.Project.PropertyGroup.TargetFramework)
|
|||
|
if (![string]::IsNullOrWhiteSpace($targetFrameworks[0])) {
|
|||
|
$targetFramework = $targetFrameworks[0]
|
|||
|
}
|
|||
|
|
|||
|
if ($targetFramework -match "core") {
|
|||
|
$framework = "dotnetcore"
|
|||
|
} else {
|
|||
|
$framework = "framework"
|
|||
|
}
|
|||
|
|
|||
|
$splitRoots = $rootNamespace.Split('.')
|
|||
|
$creatorCode = $splitRoots[0]
|
|||
|
} else {
|
|||
|
# Refactor when we have node project examples to emit something more generic
|
|||
|
Write-Warning "$logLead : There is no csproj file at [$ProjectLocation|$csprojFile]. Please run this from within a project code folder, or supply a valid ProjectLocation"
|
|||
|
}
|
|||
|
|
|||
|
if ([string]::IsNullOrWhiteSpace($assemblyName) -and ![string]::IsNullOrWhiteSpace($rootNamespace)) {
|
|||
|
$assemblyName = $rootNamespace
|
|||
|
}
|
|||
|
|
|||
|
if ([string]::IsNullOrWhiteSpace($rootNamespace) -and ![string]::IsNullOrWhiteSpace($assemblyName)) {
|
|||
|
$rootNamespace = $assemblyName
|
|||
|
}
|
|||
|
|
|||
|
$sectionManifest = ""
|
|||
|
|
|||
|
if ($Type -eq $hotfixType) {
|
|||
|
Write-Verbose "Building Hotfix Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<hotfixManifest>
|
|||
|
<fixedInOrbVersion>REPLACEME</fixedInOrbVersion>
|
|||
|
<serverTier>REPLACESERVERTIER</serverTier>
|
|||
|
</hotfixManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if($Type -eq $apiComponentType){
|
|||
|
Write-Verbose "Building ApiComponent Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<apiComponentsManifest>
|
|||
|
<targetApp>REPLACEME</targetApp>
|
|||
|
</apiComponentsManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $widgetType) {
|
|||
|
Write-Verbose "Building Widget Section"
|
|||
|
|
|||
|
if (!!$splitRoots) {
|
|||
|
# Widget area names are always the last part of the project name
|
|||
|
# Alkami.Client.Widgets.Lending = Lending
|
|||
|
$areaName = $splitRoots[-1]
|
|||
|
|
|||
|
# In the case of SDK they are actually:
|
|||
|
# BCU.Client.Widgets.Lending = BCULending
|
|||
|
$areaName = $splitRoots[0] + $splitRoots[-1]
|
|||
|
}
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<widgetManifest>
|
|||
|
<widgetName>This is a displayable widget name for the UI</widgetName>
|
|||
|
<widgetDescription>This is a displayable widget description for the UI</widgetDescription>
|
|||
|
<widgetInstall>Client</widgetInstall>
|
|||
|
<areaName>$areaName</areaName>
|
|||
|
<assemblyInfo>$rootNamespace</assemblyInfo>
|
|||
|
<displaySettings>Desktop</displaySettings>
|
|||
|
<iconName></iconName>
|
|||
|
</widgetManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $serviceType) {
|
|||
|
Write-Verbose "$logLead : Building Service Section"
|
|||
|
|
|||
|
$jsonServiceManifestChunk = @"
|
|||
|
<migrations>
|
|||
|
<assembly target="master|TENANT|tde" online="true|FALSE" role="my_service_role">$assemblyName.Migrations</assembly>
|
|||
|
<package id="$assemblyName.Migrations" version="1.0" />
|
|||
|
</migrations>
|
|||
|
<db_role>my_service_role</db_role>
|
|||
|
<!--
|
|||
|
<provider>
|
|||
|
<providerName>my_provider_name</providerName>
|
|||
|
<providerType>my_provider_type</providerType>
|
|||
|
</provider>
|
|||
|
-->
|
|||
|
"@
|
|||
|
$xmlServiceManifestChunk = @"
|
|||
|
<migrations>
|
|||
|
<!--<assembly target="master|TENANT|tde" online="true|FALSE" role="my_service_role">$assemblyName.Migrations</assembly> -->
|
|||
|
<!--<package id="$assemblyName.Migrations" version="1.0" />-->
|
|||
|
</migrations>
|
|||
|
<!-- <db_role>my_service_role</db_role> -->
|
|||
|
"@
|
|||
|
|
|||
|
$useChunk = $xmlServiceManifestChunk
|
|||
|
if ($FileType -eq 'Json') {
|
|||
|
$useChunk = $jsonServiceManifestChunk
|
|||
|
}
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<serviceManifest>
|
|||
|
<runtime>$framework</runtime>
|
|||
|
<entryPoint>$assemblyName</entryPoint>
|
|||
|
<!-- Populating the migrations or db_role values will assume the microservice needs connectivity to a tenant database. -->$useChunk
|
|||
|
</serviceManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $legacyUtilityType) {
|
|||
|
Write-Verbose "Building LegacyUtility Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<legacyUtilityManifest>
|
|||
|
<!-- If legacy projects use Alkami.Ioc from AppDev/Common or the Alkami.Common nuget package, then needsShared should be set to true. -->
|
|||
|
<needsShared>true</needsShared>
|
|||
|
</legacyUtilityManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $migrationType) {
|
|||
|
Write-Verbose "Building Migration Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<migrationManifest>
|
|||
|
<runnerType>FluentMigrator|Fluent</runnerType>
|
|||
|
<roleName>REPLACEME</roleName>
|
|||
|
<!-- The assemblyName of the file in this current package (only the migration dll name "My.Service.Migrations.dll" is required) -->
|
|||
|
<!-- The assemblyName can be array-ified by repeating <assemblyName> tags as many as you need, one entry per -->
|
|||
|
<assemblyName>$assemblyName</assemblyName>
|
|||
|
</migrationManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $themeType) {
|
|||
|
Write-Verbose "Building Theme Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<themeManifest>
|
|||
|
<themeName></themeName>
|
|||
|
<defaultOverrideForUrlSignature></defaultOverrideForUrlSignature>
|
|||
|
</themeManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $webApplicationType) {
|
|||
|
Write-Verbose "Building Web Application Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<webApplicationManifest>
|
|||
|
<appInstall></appInstall>
|
|||
|
<appName>$areaName</appName>
|
|||
|
<!-- most apps do not need needsShared set to true. Ask SDK/Vanguard for more details. -->
|
|||
|
<needsShared>false</needsShared>
|
|||
|
</webApplicationManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $webExtensionType) {
|
|||
|
Write-Verbose "Building Web Extension Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<webExtensionManifest>
|
|||
|
<appInstall>Client</appInstall>
|
|||
|
</webExtensionManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $repositoryType) {
|
|||
|
Write-Verbose "Building Repository Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<repositoryManifest>
|
|||
|
<appInstall>Client</appInstall>
|
|||
|
</repositoryManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $websiteType) {
|
|||
|
Write-Verbose "Building WebSite Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<websiteManifest>
|
|||
|
<websiteName>$baseName</websiteName>
|
|||
|
<url></url>
|
|||
|
</websiteManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
if ($Type -eq $providerType) {
|
|||
|
Write-Verbose "Building Provider Section"
|
|||
|
|
|||
|
$sectionManifest = @"
|
|||
|
<!-- This is a legacy project. Providers are no longer supported as new submissions for Alkami SDK projects. -->
|
|||
|
<providerManifest>
|
|||
|
<!-- appInstall requires some combination of the default provided values. Use pipes or commas to separate service names. -->
|
|||
|
<appInstall>BankService|Bank|SchedulerService|CoreService|Core|NotificationService|SecurityManagementService|SecurityManagement|Security|Radium|Nag|NagConfigurationService|NagConfig|NagConfiguration|All</appInstall>
|
|||
|
<assemblyInfo>$rootNamespace</assemblyInfo>
|
|||
|
<providerType></providerType>
|
|||
|
<providerName></providerName>
|
|||
|
<pluginType>Connector</pluginType>
|
|||
|
</providerManifest>
|
|||
|
"@
|
|||
|
}
|
|||
|
|
|||
|
Write-Verbose "Building Manifest"
|
|||
|
|
|||
|
$sdkSection = @"
|
|||
|
<!-- SDK clients should add their BankIdentifier(s) in this list. No quotes or brackets - {} - are required. Dashes are encouraged. -->
|
|||
|
<bankIdentifiers>
|
|||
|
<bankIdentifier name="MyFIName">DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF</bankIdentifier>
|
|||
|
</bankIdentifiers>
|
|||
|
"@
|
|||
|
|
|||
|
# Special case for SDK clients to get extra help
|
|||
|
if ($creatorCode -eq "Alkami") {
|
|||
|
$sdkSection = ""
|
|||
|
}
|
|||
|
|
|||
|
$manifestPayload = @"
|
|||
|
<?xml version="1.0"?>
|
|||
|
<packageManifest>
|
|||
|
<version>1.0</version>
|
|||
|
<general>
|
|||
|
<creatorCode>$creatorCode</creatorCode>
|
|||
|
<element>$assemblyName</element>
|
|||
|
<componentType>$Type</componentType>$sdkSection
|
|||
|
<!--
|
|||
|
<releaseManagement>
|
|||
|
<alwaysDeploy>false</alwaysDeploy>
|
|||
|
</releaseManagement>
|
|||
|
-->
|
|||
|
</general>
|
|||
|
$sectionManifest
|
|||
|
</packageManifest>
|
|||
|
"@
|
|||
|
|
|||
|
Write-Host "$logLead : Creating a new manifest file for a $FileType [$Type] at [$targetPath]"
|
|||
|
|
|||
|
if ($FileType -eq 'Json') {
|
|||
|
$manifestPayload = ([xml]$manifestPayload | ConvertFrom-Xml).PackageManifest | Format-Json
|
|||
|
}
|
|||
|
|
|||
|
Set-Content -Path $targetPath -Value $manifestPayload;
|
|||
|
}
|
|||
|
}
|