@chill-sharp/ui-core 1.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/chillsharp-current-user-preferences/SKILL.md +70 -0
- package/.agents/skills/chillsharp-ui-template/SKILL.md +18 -0
- package/README.md +103 -0
- package/chill-sharp-ui-core.d.ts.map +1 -0
- package/doc/AIAssistedDevelopment/README.md +185 -0
- package/doc/AttachmentModel/README.md +173 -0
- package/doc/AuthenticationModel/README.md +213 -0
- package/doc/AuthenticationModel/how-to-integreate-auth-minimal-api.md +293 -0
- package/doc/ChillSharpClient.md +464 -0
- package/doc/ClientGeneration/README.md +172 -0
- package/doc/ComplianceGuide/README.md +178 -0
- package/doc/Configuration/README.md +94 -0
- package/doc/CurrentUserPreferences.md +114 -0
- package/doc/DateTimePolicy/README.md +154 -0
- package/doc/DateTimeSerialization.md +423 -0
- package/doc/Endpoints.md +260 -0
- package/doc/HowTo/01-simple-blog-sqlite.md +153 -0
- package/doc/HowTo/02-blog-schema-labels.md +140 -0
- package/doc/HowTo/03-authentication.md +218 -0
- package/doc/HowTo/04-blog-posts-one-to-many.md +194 -0
- package/doc/HowTo/05-docker-env-variables.md +274 -0
- package/doc/HowTo/06-chunk-transactions-autocomplete.md +196 -0
- package/doc/Mcp/ChatGPT.md +291 -0
- package/doc/Mcp/README.md +799 -0
- package/doc/MenuGuide/README.md +49 -0
- package/doc/ModelPreparation.md +255 -0
- package/doc/PermissionModel/README.md +277 -0
- package/doc/README.md +228 -0
- package/doc/ReferenceExistence.md +130 -0
- package/doc/RegisterContext.md +217 -0
- package/doc/UiCore/CRUD.md +170 -0
- package/doc/UiCore/README.md +13 -0
- package/doc/ValidationModel/README.md +117 -0
- package/doc/it/AIAssistedDevelopment/README.md +185 -0
- package/doc/it/AttachmentModel/README.md +173 -0
- package/doc/it/AuthenticationModel/README.md +171 -0
- package/doc/it/AuthenticationModel/how-to-integreate-auth-minimal-api.md +292 -0
- package/doc/it/ChillSharpClient.md +464 -0
- package/doc/it/ClientGeneration/README.md +152 -0
- package/doc/it/ComplianceGuide/README.md +178 -0
- package/doc/it/Configuration/README.md +94 -0
- package/doc/it/CurrentUserPreferences.md +114 -0
- package/doc/it/DateTimePolicy/README.md +154 -0
- package/doc/it/DateTimeSerialization.md +423 -0
- package/doc/it/Endpoints.md +260 -0
- package/doc/it/HowTo/01-simple-blog-sqlite.md +152 -0
- package/doc/it/HowTo/02-blog-schema-labels.md +139 -0
- package/doc/it/HowTo/03-authentication.md +221 -0
- package/doc/it/HowTo/04-blog-posts-one-to-many.md +193 -0
- package/doc/it/HowTo/05-docker-env-variables.md +268 -0
- package/doc/it/HowTo/06-chunk-transactions-autocomplete.md +196 -0
- package/doc/it/Mcp/ChatGPT.md +291 -0
- package/doc/it/Mcp/README.md +799 -0
- package/doc/it/MenuGuide/README.md +49 -0
- package/doc/it/ModelPreparation.md +254 -0
- package/doc/it/PermissionModel/README.md +190 -0
- package/doc/it/README.md +172 -0
- package/doc/it/ReferenceExistence.md +130 -0
- package/doc/it/RegisterContext.md +218 -0
- package/doc/it/UiCore/CRUD.md +170 -0
- package/doc/it/UiCore/README.md +13 -0
- package/doc/it/ValidationModel/README.md +117 -0
- package/fesm2022/chill-sharp-ui-core.mjs +16725 -0
- package/fesm2022/chill-sharp-ui-core.mjs.map +1 -0
- package/index.d.ts +6 -0
- package/lib/chill-sharp-ui-root.component.d.ts +6 -0
- package/lib/chill-sharp-ui-root.component.d.ts.map +1 -0
- package/lib/chill-sharp-ui.routes.d.ts +3 -0
- package/lib/chill-sharp-ui.routes.d.ts.map +1 -0
- package/lib/chill.config.d.ts +5 -0
- package/lib/chill.config.d.ts.map +1 -0
- package/lib/layouts/auth-shell.component.d.ts +8 -0
- package/lib/layouts/auth-shell.component.d.ts.map +1 -0
- package/lib/layouts/workspace-page.component.d.ts +49 -0
- package/lib/layouts/workspace-page.component.d.ts.map +1 -0
- package/lib/lib/chill-form.component.d.ts +151 -0
- package/lib/lib/chill-form.component.d.ts.map +1 -0
- package/lib/lib/chill-i18n-button-label.component.d.ts +27 -0
- package/lib/lib/chill-i18n-button-label.component.d.ts.map +1 -0
- package/lib/lib/chill-i18n-label.component.d.ts +30 -0
- package/lib/lib/chill-i18n-label.component.d.ts.map +1 -0
- package/lib/lib/chill-json-input.component.d.ts +31 -0
- package/lib/lib/chill-json-input.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts +12 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts +17 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts +45 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts +19 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts +12 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts +13 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input.component.d.ts +452 -0
- package/lib/lib/chill-polymorphic-input.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts +8 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output.component.d.ts +75 -0
- package/lib/lib/chill-polymorphic-output.component.d.ts.map +1 -0
- package/lib/lib/chill-table.component.d.ts +434 -0
- package/lib/lib/chill-table.component.d.ts.map +1 -0
- package/lib/lib/chill-text-editor-dialog.component.d.ts +14 -0
- package/lib/lib/chill-text-editor-dialog.component.d.ts.map +1 -0
- package/lib/lib/crud-configuration.utils.d.ts +4 -0
- package/lib/lib/crud-configuration.utils.d.ts.map +1 -0
- package/lib/lib/culture-name-options.d.ts +3 -0
- package/lib/lib/culture-name-options.d.ts.map +1 -0
- package/lib/lib/date-format-options.d.ts +3 -0
- package/lib/lib/date-format-options.d.ts.map +1 -0
- package/lib/lib/iana-time-zone-options.d.ts +3 -0
- package/lib/lib/iana-time-zone-options.d.ts.map +1 -0
- package/lib/lib/notice-transition.directive.d.ts +17 -0
- package/lib/lib/notice-transition.directive.d.ts.map +1 -0
- package/lib/lib/schema-property-dialog.component.d.ts +74 -0
- package/lib/lib/schema-property-dialog.component.d.ts.map +1 -0
- package/lib/models/chill-auth.models.d.ts +176 -0
- package/lib/models/chill-auth.models.d.ts.map +1 -0
- package/lib/models/chill-menu.models.d.ts +12 -0
- package/lib/models/chill-menu.models.d.ts.map +1 -0
- package/lib/models/chill-schema.models.d.ts +141 -0
- package/lib/models/chill-schema.models.d.ts.map +1 -0
- package/lib/models/workspace-dialog.models.d.ts +16 -0
- package/lib/models/workspace-dialog.models.d.ts.map +1 -0
- package/lib/models/workspace-task.models.d.ts +36 -0
- package/lib/models/workspace-task.models.d.ts.map +1 -0
- package/lib/pages/confirm-reset-page.component.d.ts +21 -0
- package/lib/pages/confirm-reset-page.component.d.ts.map +1 -0
- package/lib/pages/crud/attachment-upload-dialog.component.d.ts +24 -0
- package/lib/pages/crud/attachment-upload-dialog.component.d.ts.map +1 -0
- package/lib/pages/crud/crud-page.component.d.ts +244 -0
- package/lib/pages/crud/crud-page.component.d.ts.map +1 -0
- package/lib/pages/login-page.component.d.ts +21 -0
- package/lib/pages/login-page.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-role-dialog.component.d.ts +29 -0
- package/lib/pages/permissions/auth-role-dialog.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-search-select.component.d.ts +28 -0
- package/lib/pages/permissions/auth-search-select.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-user-dialog.component.d.ts +35 -0
- package/lib/pages/permissions/auth-user-dialog.component.d.ts.map +1 -0
- package/lib/pages/permissions/permission-editor.component.d.ts +55 -0
- package/lib/pages/permissions/permission-editor.component.d.ts.map +1 -0
- package/lib/pages/permissions/permissions-page.component.d.ts +38 -0
- package/lib/pages/permissions/permissions-page.component.d.ts.map +1 -0
- package/lib/pages/permissions/role-permission.component.d.ts +43 -0
- package/lib/pages/permissions/role-permission.component.d.ts.map +1 -0
- package/lib/pages/permissions/user-permission.component.d.ts +43 -0
- package/lib/pages/permissions/user-permission.component.d.ts.map +1 -0
- package/lib/pages/register-page.component.d.ts +24 -0
- package/lib/pages/register-page.component.d.ts.map +1 -0
- package/lib/pages/reset-password-page.component.d.ts +18 -0
- package/lib/pages/reset-password-page.component.d.ts.map +1 -0
- package/lib/provide-chill-sharp-ui-core.d.ts +8 -0
- package/lib/provide-chill-sharp-ui-core.d.ts.map +1 -0
- package/lib/services/chill.service.d.ts +249 -0
- package/lib/services/chill.service.d.ts.map +1 -0
- package/lib/services/workspace-dialog.service.d.ts +22 -0
- package/lib/services/workspace-dialog.service.d.ts.map +1 -0
- package/lib/services/workspace-layout.service.d.ts +13 -0
- package/lib/services/workspace-layout.service.d.ts.map +1 -0
- package/lib/services/workspace-task-registry.service.d.ts +35 -0
- package/lib/services/workspace-task-registry.service.d.ts.map +1 -0
- package/lib/services/workspace-toolbar.service.d.ts +23 -0
- package/lib/services/workspace-toolbar.service.d.ts.map +1 -0
- package/lib/services/workspace.service.d.ts +114 -0
- package/lib/services/workspace.service.d.ts.map +1 -0
- package/lib/storage-keys.d.ts +5 -0
- package/lib/storage-keys.d.ts.map +1 -0
- package/lib/tasks/crud-task/crud-task.component.d.ts +33 -0
- package/lib/tasks/crud-task/crud-task.component.d.ts.map +1 -0
- package/lib/tasks/goto-url-task/goto-url-task.component.d.ts +31 -0
- package/lib/tasks/goto-url-task/goto-url-task.component.d.ts.map +1 -0
- package/lib/workspace/confirm-message-dialog.component.d.ts +16 -0
- package/lib/workspace/confirm-message-dialog.component.d.ts.map +1 -0
- package/lib/workspace/entity-options-dialog.component.d.ts +29 -0
- package/lib/workspace/entity-options-dialog.component.d.ts.map +1 -0
- package/lib/workspace/external-task-api.d.ts +2 -0
- package/lib/workspace/external-task-api.d.ts.map +1 -0
- package/lib/workspace/user-profile-dialog.component.d.ts +30 -0
- package/lib/workspace/user-profile-dialog.component.d.ts.map +1 -0
- package/lib/workspace/workspace-dialog-host.component.d.ts +26 -0
- package/lib/workspace/workspace-dialog-host.component.d.ts.map +1 -0
- package/lib/workspace/workspace-menu-item-dialog.component.d.ts +61 -0
- package/lib/workspace/workspace-menu-item-dialog.component.d.ts.map +1 -0
- package/lib/workspace/workspace-menu.component.d.ts +104 -0
- package/lib/workspace/workspace-menu.component.d.ts.map +1 -0
- package/lib/workspace/workspace-taskbar.component.d.ts +14 -0
- package/lib/workspace/workspace-taskbar.component.d.ts.map +1 -0
- package/package.json +54 -0
- package/public-api.d.ts +56 -0
- package/public-api.d.ts.map +1 -0
- package/service-worker/chill-sharp-service-worker.js +166 -0
- package/styles/core-theme.scss +1268 -0
- package/template-customization/upgrade.ps1.template +342 -0
- package/template-customization/upgrade.sh.template +271 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
[CmdletBinding()]
|
|
2
|
+
param(
|
|
3
|
+
[string]$SharedFolder = 'C:\source\npm-shared',
|
|
4
|
+
[switch]$SkipConfirmation
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = 'Stop'
|
|
8
|
+
Set-StrictMode -Version Latest
|
|
9
|
+
|
|
10
|
+
$UpgradeScriptVersion = 3
|
|
11
|
+
$scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
12
|
+
$packageJsonPath = Join-Path $scriptDirectory 'package.json'
|
|
13
|
+
$packagesFolder = Join-Path $scriptDirectory 'packages'
|
|
14
|
+
|
|
15
|
+
function Resolve-ConfirmedFolderPath {
|
|
16
|
+
param(
|
|
17
|
+
[Parameter(Mandatory = $true)]
|
|
18
|
+
[string]$InitialPath,
|
|
19
|
+
|
|
20
|
+
[Parameter(Mandatory = $true)]
|
|
21
|
+
[string]$Label,
|
|
22
|
+
|
|
23
|
+
[switch]$SkipPrompt
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
$selectedPath = $InitialPath
|
|
27
|
+
|
|
28
|
+
if (-not $SkipPrompt) {
|
|
29
|
+
Write-Host "$Label shared folder suggestion: $InitialPath"
|
|
30
|
+
$enteredPath = [string](Read-Host 'Press Enter to confirm, or type a different path')
|
|
31
|
+
if (-not [string]::IsNullOrWhiteSpace($enteredPath)) {
|
|
32
|
+
$selectedPath = $enteredPath
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
$confirmation = [string](Read-Host "Continue with '$selectedPath'? [Y/n]")
|
|
36
|
+
if (-not [string]::IsNullOrWhiteSpace($confirmation) -and $confirmation -notmatch '^(?i:y|yes)$') {
|
|
37
|
+
Write-Host 'Upgrade cancelled.'
|
|
38
|
+
exit 0
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (-not (Test-Path -LiteralPath $selectedPath)) {
|
|
43
|
+
throw "$Label shared folder '$selectedPath' was not found."
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return [System.IO.Path]::GetFullPath($selectedPath)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function Get-LatestArchive {
|
|
50
|
+
param(
|
|
51
|
+
[Parameter(Mandatory = $true)]
|
|
52
|
+
[string]$FolderPath,
|
|
53
|
+
|
|
54
|
+
[Parameter(Mandatory = $true)]
|
|
55
|
+
[string]$ArchivePrefix
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
$pattern = '^' + [System.Text.RegularExpressions.Regex]::Escape($ArchivePrefix) + '-(?<Version>\d+\.\d+\.\d+(?:[-+][0-9A-Za-z\.-]+)?)\.tgz$'
|
|
59
|
+
|
|
60
|
+
$candidates = foreach ($file in Get-ChildItem -LiteralPath $FolderPath -Filter "$ArchivePrefix-*.tgz" -File -ErrorAction Stop) {
|
|
61
|
+
if ($file.Name -notmatch $pattern) {
|
|
62
|
+
continue
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
[pscustomobject]@{
|
|
66
|
+
File = $file
|
|
67
|
+
VersionText = $matches.Version
|
|
68
|
+
Version = [System.Management.Automation.SemanticVersion]::Parse($matches.Version)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
$latestArchive = $candidates | Sort-Object Version -Descending | Select-Object -First 1
|
|
73
|
+
if ($null -eq $latestArchive) {
|
|
74
|
+
throw "Could not find a '$ArchivePrefix-<version>.tgz' archive in '$FolderPath'."
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return $latestArchive
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function Test-CommandAvailable {
|
|
81
|
+
param(
|
|
82
|
+
[Parameter(Mandatory = $true)]
|
|
83
|
+
[string]$CommandName
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return $null -ne (Get-Command $CommandName -ErrorAction SilentlyContinue)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function Update-UpgradeScriptIfNewer {
|
|
90
|
+
param(
|
|
91
|
+
[Parameter(Mandatory = $true)]
|
|
92
|
+
[string]$ArchivePath,
|
|
93
|
+
|
|
94
|
+
[Parameter(Mandatory = $true)]
|
|
95
|
+
[string]$ScriptPath
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
$temporaryScriptPath = [System.IO.Path]::GetTempFileName()
|
|
99
|
+
Add-Type -AssemblyName System.Formats.Tar
|
|
100
|
+
$fileStream = [System.IO.File]::OpenRead($ArchivePath)
|
|
101
|
+
$gzipStream = [System.IO.Compression.GZipStream]::new($fileStream, [System.IO.Compression.CompressionMode]::Decompress)
|
|
102
|
+
$tarReader = [System.Formats.Tar.TarReader]::new($gzipStream)
|
|
103
|
+
try {
|
|
104
|
+
$entry = $null
|
|
105
|
+
while ($null -ne ($entry = $tarReader.GetNextEntry($false))) {
|
|
106
|
+
if ($entry.Name -ne 'package/template-customization/upgrade.ps1.template') {
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
$outputStream = [System.IO.File]::Open($temporaryScriptPath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
|
|
111
|
+
try {
|
|
112
|
+
$entry.DataStream.CopyTo($outputStream)
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
$outputStream.Dispose()
|
|
116
|
+
}
|
|
117
|
+
$packagedContents = Get-Content -LiteralPath $temporaryScriptPath -Raw
|
|
118
|
+
$versionMatch = [System.Text.RegularExpressions.Regex]::Match(
|
|
119
|
+
$packagedContents,
|
|
120
|
+
'(?m)^\s*\$UpgradeScriptVersion\s*=\s*(?<Version>\d+)\s*$')
|
|
121
|
+
if (-not $versionMatch.Success) {
|
|
122
|
+
throw "The packaged upgrade script does not define a valid `$UpgradeScriptVersion."
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
$packagedVersion = [int]$versionMatch.Groups['Version'].Value
|
|
126
|
+
if ($packagedVersion -le $UpgradeScriptVersion) {
|
|
127
|
+
return $false
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
Copy-Item -LiteralPath $temporaryScriptPath -Destination $ScriptPath -Force
|
|
131
|
+
Write-Host "Updated upgrade.ps1 from internal version $UpgradeScriptVersion to $packagedVersion. Rerun the script to continue the package upgrade."
|
|
132
|
+
return $true
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return $false
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
$tarReader.Dispose()
|
|
139
|
+
$gzipStream.Dispose()
|
|
140
|
+
$fileStream.Dispose()
|
|
141
|
+
if (Test-Path -LiteralPath $temporaryScriptPath) {
|
|
142
|
+
Remove-Item -LiteralPath $temporaryScriptPath -Force
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function Extract-ChillSharpUiTemplateSkills {
|
|
148
|
+
param(
|
|
149
|
+
[Parameter(Mandatory = $true)]
|
|
150
|
+
[string]$ArchivePath,
|
|
151
|
+
|
|
152
|
+
[Parameter(Mandatory = $true)]
|
|
153
|
+
[string]$TargetFolder
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
$agentsDir = Join-Path $TargetFolder '.agents'
|
|
157
|
+
$skillsTargetDir = Join-Path $agentsDir 'skills'
|
|
158
|
+
if (Test-Path -LiteralPath $skillsTargetDir) {
|
|
159
|
+
Remove-Item -LiteralPath $skillsTargetDir -Recurse -Force | Out-Null
|
|
160
|
+
}
|
|
161
|
+
New-Item -ItemType Directory -Path $skillsTargetDir -Force | Out-Null
|
|
162
|
+
$skillsTargetRoot = [System.IO.Path]::GetFullPath($skillsTargetDir)
|
|
163
|
+
|
|
164
|
+
Add-Type -AssemblyName System.Formats.Tar
|
|
165
|
+
$fileStream = [System.IO.File]::OpenRead($ArchivePath)
|
|
166
|
+
$gzipStream = [System.IO.Compression.GZipStream]::new($fileStream, [System.IO.Compression.CompressionMode]::Decompress)
|
|
167
|
+
$tarReader = [System.Formats.Tar.TarReader]::new($gzipStream)
|
|
168
|
+
try {
|
|
169
|
+
$entry = $null
|
|
170
|
+
$entryPrefix = 'package/.agents/skills/'
|
|
171
|
+
while ($null -ne ($entry = $tarReader.GetNextEntry($false))) {
|
|
172
|
+
if (-not $entry.Name.StartsWith($entryPrefix, [System.StringComparison]::Ordinal)) {
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
$relativePath = $entry.Name.Substring($entryPrefix.Length)
|
|
177
|
+
if ([string]::IsNullOrWhiteSpace($relativePath) -or $entry.EntryType -eq [System.Formats.Tar.TarEntryType]::Directory) {
|
|
178
|
+
continue
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
$destinationPath = [System.IO.Path]::GetFullPath((Join-Path $skillsTargetRoot ($relativePath -replace '/', [System.IO.Path]::DirectorySeparatorChar)))
|
|
182
|
+
if (-not $destinationPath.StartsWith($skillsTargetRoot + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase)) {
|
|
183
|
+
throw "Refusing to extract skill outside '$skillsTargetRoot'."
|
|
184
|
+
}
|
|
185
|
+
$destinationDirectory = Split-Path -Parent $destinationPath
|
|
186
|
+
New-Item -ItemType Directory -Path $destinationDirectory -Force | Out-Null
|
|
187
|
+
$outputStream = [System.IO.File]::Open($destinationPath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
|
|
188
|
+
try {
|
|
189
|
+
$entry.DataStream.CopyTo($outputStream)
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
$outputStream.Dispose()
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
$tarReader.Dispose()
|
|
198
|
+
$gzipStream.Dispose()
|
|
199
|
+
$fileStream.Dispose()
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function Extract-ChillSharpUiTemplateDocumentation {
|
|
204
|
+
param(
|
|
205
|
+
[Parameter(Mandatory = $true)]
|
|
206
|
+
[string]$ArchivePath,
|
|
207
|
+
|
|
208
|
+
[Parameter(Mandatory = $true)]
|
|
209
|
+
[string]$TargetFolder
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
$documentationTargetDir = Join-Path $TargetFolder 'doc'
|
|
213
|
+
if (Test-Path -LiteralPath $documentationTargetDir) {
|
|
214
|
+
Remove-Item -LiteralPath $documentationTargetDir -Recurse -Force | Out-Null
|
|
215
|
+
}
|
|
216
|
+
New-Item -ItemType Directory -Path $documentationTargetDir | Out-Null
|
|
217
|
+
$documentationTargetRoot = [System.IO.Path]::GetFullPath($documentationTargetDir)
|
|
218
|
+
|
|
219
|
+
Add-Type -AssemblyName System.Formats.Tar
|
|
220
|
+
$fileStream = [System.IO.File]::OpenRead($ArchivePath)
|
|
221
|
+
$gzipStream = [System.IO.Compression.GZipStream]::new($fileStream, [System.IO.Compression.CompressionMode]::Decompress)
|
|
222
|
+
$tarReader = [System.Formats.Tar.TarReader]::new($gzipStream)
|
|
223
|
+
try {
|
|
224
|
+
$entry = $null
|
|
225
|
+
$entryPrefix = 'package/doc/'
|
|
226
|
+
while ($null -ne ($entry = $tarReader.GetNextEntry($false))) {
|
|
227
|
+
if (-not $entry.Name.StartsWith($entryPrefix, [System.StringComparison]::Ordinal)) {
|
|
228
|
+
continue
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
$relativePath = $entry.Name.Substring($entryPrefix.Length)
|
|
232
|
+
if ([string]::IsNullOrWhiteSpace($relativePath)) {
|
|
233
|
+
continue
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
$destinationPath = [System.IO.Path]::GetFullPath((Join-Path $documentationTargetRoot ($relativePath -replace '/', [System.IO.Path]::DirectorySeparatorChar)))
|
|
237
|
+
if (-not $destinationPath.StartsWith($documentationTargetRoot + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase)) {
|
|
238
|
+
throw "Refusing to extract documentation outside '$documentationTargetRoot'."
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if ($entry.EntryType -eq [System.Formats.Tar.TarEntryType]::Directory) {
|
|
242
|
+
New-Item -ItemType Directory -Path $destinationPath -Force | Out-Null
|
|
243
|
+
continue
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
$destinationDirectory = Split-Path -Parent $destinationPath
|
|
247
|
+
New-Item -ItemType Directory -Path $destinationDirectory -Force | Out-Null
|
|
248
|
+
$outputStream = [System.IO.File]::Open($destinationPath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
|
|
249
|
+
try {
|
|
250
|
+
$entry.DataStream.CopyTo($outputStream)
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
$outputStream.Dispose()
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
finally {
|
|
258
|
+
$tarReader.Dispose()
|
|
259
|
+
$gzipStream.Dispose()
|
|
260
|
+
$fileStream.Dispose()
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (-not (Test-Path -LiteralPath $packageJsonPath)) {
|
|
265
|
+
throw "Could not find package.json at '$packageJsonPath'."
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (-not (Test-Path -LiteralPath $packagesFolder)) {
|
|
269
|
+
New-Item -ItemType Directory -Path $packagesFolder | Out-Null
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
$resolvedSharedFolder = Resolve-ConfirmedFolderPath -InitialPath $SharedFolder -Label 'npm' -SkipPrompt:$SkipConfirmation
|
|
273
|
+
|
|
274
|
+
$latestUiCoreArchive = Get-LatestArchive -FolderPath $resolvedSharedFolder -ArchivePrefix 'chill-sharp-ui-core'
|
|
275
|
+
if (Update-UpgradeScriptIfNewer -ArchivePath $latestUiCoreArchive.File.FullName -ScriptPath $MyInvocation.MyCommand.Path) {
|
|
276
|
+
exit 0
|
|
277
|
+
}
|
|
278
|
+
Extract-ChillSharpUiTemplateSkills -ArchivePath $latestUiCoreArchive.File.FullName -TargetFolder $scriptDirectory
|
|
279
|
+
Extract-ChillSharpUiTemplateDocumentation -ArchivePath $latestUiCoreArchive.File.FullName -TargetFolder $scriptDirectory
|
|
280
|
+
|
|
281
|
+
$packageDefinitions = @(
|
|
282
|
+
[pscustomobject]@{ PackageName = '@chill-sharp/ui-core'; ArchivePrefix = 'chill-sharp-ui-core' }
|
|
283
|
+
[pscustomobject]@{ PackageName = '@chill-sharp/ng-client'; ArchivePrefix = 'chill-sharp-ng-client' }
|
|
284
|
+
[pscustomobject]@{ PackageName = '@chill-sharp/ts-client'; ArchivePrefix = 'chill-sharp-ts-client' }
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
$packageJson = Get-Content -LiteralPath $packageJsonPath -Raw | ConvertFrom-Json
|
|
288
|
+
if ($null -eq $packageJson.dependencies) {
|
|
289
|
+
throw "package.json at '$packageJsonPath' does not define a dependencies object."
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
foreach ($definition in $packageDefinitions) {
|
|
293
|
+
$latestArchive = Get-LatestArchive -FolderPath $resolvedSharedFolder -ArchivePrefix $definition.ArchivePrefix
|
|
294
|
+
$destinationArchivePath = Join-Path $packagesFolder $latestArchive.File.Name
|
|
295
|
+
|
|
296
|
+
foreach ($existingArchive in Get-ChildItem -LiteralPath $packagesFolder -Filter "$($definition.ArchivePrefix)-*.tgz" -File -ErrorAction SilentlyContinue) {
|
|
297
|
+
if (-not $existingArchive.FullName.Equals($destinationArchivePath, [System.StringComparison]::OrdinalIgnoreCase)) {
|
|
298
|
+
Remove-Item -LiteralPath $existingArchive.FullName -Force
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
Copy-Item -LiteralPath $latestArchive.File.FullName -Destination $destinationArchivePath -Force
|
|
303
|
+
$packageJson.dependencies | Add-Member -NotePropertyName $definition.PackageName -NotePropertyValue "file:./packages/$($latestArchive.File.Name)" -Force
|
|
304
|
+
|
|
305
|
+
Write-Host "Copied $($definition.PackageName) $($latestArchive.VersionText) to '$destinationArchivePath'."
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
$packageJson | ConvertTo-Json -Depth 100 | Set-Content -LiteralPath $packageJsonPath
|
|
309
|
+
|
|
310
|
+
if (Test-CommandAvailable -CommandName 'npm') {
|
|
311
|
+
$packageLockPath = Join-Path $scriptDirectory 'package-lock.json'
|
|
312
|
+
$packageLockBackupPath = "$packageLockPath.chill-sharp-upgrade.bak"
|
|
313
|
+
$hadPackageLock = Test-Path -LiteralPath $packageLockPath
|
|
314
|
+
if ($hadPackageLock) {
|
|
315
|
+
Copy-Item -LiteralPath $packageLockPath -Destination $packageLockBackupPath -Force
|
|
316
|
+
Remove-Item -LiteralPath $packageLockPath -Force
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
Write-Host 'Refreshing package-lock.json and local file dependencies with npm install --ignore-scripts...'
|
|
320
|
+
Push-Location $scriptDirectory
|
|
321
|
+
try {
|
|
322
|
+
& npm install --ignore-scripts
|
|
323
|
+
if ($LASTEXITCODE -ne 0) {
|
|
324
|
+
if ($hadPackageLock -and (Test-Path -LiteralPath $packageLockBackupPath)) {
|
|
325
|
+
Move-Item -LiteralPath $packageLockBackupPath -Destination $packageLockPath -Force
|
|
326
|
+
}
|
|
327
|
+
Write-Warning 'npm install --ignore-scripts did not complete successfully. Local archives were copied, but package-lock.json and node_modules may still need a manual refresh.'
|
|
328
|
+
}
|
|
329
|
+
elseif (Test-Path -LiteralPath $packageLockBackupPath) {
|
|
330
|
+
Remove-Item -LiteralPath $packageLockBackupPath -Force
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
finally {
|
|
334
|
+
Pop-Location
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
Write-Warning "npm was not found on PATH. Local archives were copied, but package-lock.json was not refreshed."
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
Write-Host 'UI template dependencies were upgraded from the shared npm folder.'
|
|
342
|
+
Write-Host "Extracted and updated documentation in 'doc/'."
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -Eeuo pipefail
|
|
3
|
+
|
|
4
|
+
upgrade_script_version=2
|
|
5
|
+
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
6
|
+
package_json_path="$script_dir/package.json"
|
|
7
|
+
packages_folder="$script_dir/packages"
|
|
8
|
+
shared_folder="${CHILL_NPM_SHARED_FOLDER:-$HOME/source/npm-shared}"
|
|
9
|
+
env_file="${CHILL_ENV_FILE:-$HOME/.profile}"
|
|
10
|
+
skip_confirmation=false
|
|
11
|
+
resolved_shared_folder=''
|
|
12
|
+
|
|
13
|
+
while [[ $# -gt 0 ]]; do
|
|
14
|
+
case "$1" in
|
|
15
|
+
--shared-folder|-s)
|
|
16
|
+
shared_folder="${2:-}"
|
|
17
|
+
shift 2
|
|
18
|
+
;;
|
|
19
|
+
--skip-confirmation|-y)
|
|
20
|
+
skip_confirmation=true
|
|
21
|
+
shift
|
|
22
|
+
;;
|
|
23
|
+
*)
|
|
24
|
+
printf "Error: Unknown argument '%s'.\n" "$1" >&2
|
|
25
|
+
exit 1
|
|
26
|
+
;;
|
|
27
|
+
esac
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
die() {
|
|
31
|
+
printf 'Error: %s\n' "$*" >&2
|
|
32
|
+
exit 1
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
warn() {
|
|
36
|
+
printf 'Warning: %s\n' "$*" >&2
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
require_command() {
|
|
40
|
+
command -v "$1" >/dev/null 2>&1 || die "Required command '$1' was not found."
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
normalize_path() {
|
|
44
|
+
python3 -c 'import os, sys; print(os.path.abspath(sys.argv[1]))' "$1"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
shell_quote() {
|
|
48
|
+
local value="$1"
|
|
49
|
+
printf "'%s'" "${value//\'/\'\\\'\'}"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
persist_user_env_var() {
|
|
53
|
+
local name="$1"
|
|
54
|
+
local value="$2"
|
|
55
|
+
local quoted_value temp_file
|
|
56
|
+
|
|
57
|
+
quoted_value="$(shell_quote "$value")"
|
|
58
|
+
mkdir -p -- "$(dirname -- "$env_file")"
|
|
59
|
+
touch "$env_file"
|
|
60
|
+
|
|
61
|
+
temp_file="$(mktemp)"
|
|
62
|
+
awk -v name="$name" '
|
|
63
|
+
$0 ~ "^[[:space:]]*export[[:space:]]+" name "=" { next }
|
|
64
|
+
$0 ~ "^[[:space:]]*" name "=" { next }
|
|
65
|
+
{ print }
|
|
66
|
+
' "$env_file" > "$temp_file"
|
|
67
|
+
printf 'export %s=%s\n' "$name" "$quoted_value" >> "$temp_file"
|
|
68
|
+
mv -- "$temp_file" "$env_file"
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
resolve_confirmed_shared_folder() {
|
|
72
|
+
local selected_path="$shared_folder"
|
|
73
|
+
local entered_path confirmation
|
|
74
|
+
|
|
75
|
+
if [[ "$skip_confirmation" == false ]]; then
|
|
76
|
+
printf 'npm shared folder suggestion: %s\n' "$selected_path" >&2
|
|
77
|
+
read -r -p 'Press Enter to confirm, or type a different path: ' entered_path
|
|
78
|
+
if [[ -n "${entered_path//[[:space:]]/}" ]]; then
|
|
79
|
+
selected_path="$entered_path"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
read -r -p "Continue with '$selected_path'? [Y/n]: " confirmation
|
|
83
|
+
if [[ -n "${confirmation//[[:space:]]/}" && ! "$confirmation" =~ ^[Yy]([Ee][Ss])?$ ]]; then
|
|
84
|
+
printf 'Upgrade cancelled.\n' >&2
|
|
85
|
+
exit 0
|
|
86
|
+
fi
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
selected_path="$(normalize_path "$selected_path")"
|
|
90
|
+
[[ -d "$selected_path" ]] || die "npm shared folder '$selected_path' was not found."
|
|
91
|
+
|
|
92
|
+
export CHILL_NPM_SHARED_FOLDER="$selected_path"
|
|
93
|
+
persist_user_env_var CHILL_NPM_SHARED_FOLDER "$selected_path"
|
|
94
|
+
|
|
95
|
+
resolved_shared_folder="$selected_path"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
latest_archive_line() {
|
|
99
|
+
local folder_path="$1"
|
|
100
|
+
local archive_prefix="$2"
|
|
101
|
+
|
|
102
|
+
find "$folder_path" -maxdepth 1 -type f -name "$archive_prefix-*.tgz" -printf '%f\t%p\n' |
|
|
103
|
+
sed -n "s/^$archive_prefix-\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*[-+0-9A-Za-z.]*\)\.tgz\t/\1\t/p" |
|
|
104
|
+
sort -V -r |
|
|
105
|
+
head -n 1
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
set_package_dependency() {
|
|
109
|
+
local package_name="$1"
|
|
110
|
+
local dependency_spec="$2"
|
|
111
|
+
local temp_json
|
|
112
|
+
|
|
113
|
+
jq -e '.dependencies | type == "object"' "$package_json_path" >/dev/null ||
|
|
114
|
+
die "package.json at '$package_json_path' does not define a dependencies object."
|
|
115
|
+
|
|
116
|
+
temp_json="$(mktemp)"
|
|
117
|
+
jq --arg name "$package_name" --arg spec "$dependency_spec" \
|
|
118
|
+
'.dependencies[$name] = $spec' \
|
|
119
|
+
"$package_json_path" > "$temp_json"
|
|
120
|
+
mv -- "$temp_json" "$package_json_path"
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
copy_latest_package_archive() {
|
|
124
|
+
local package_name="$1"
|
|
125
|
+
local archive_prefix="$2"
|
|
126
|
+
local latest_line package_version source_archive_path destination_archive_path
|
|
127
|
+
|
|
128
|
+
latest_line="$(latest_archive_line "$resolved_shared_folder" "$archive_prefix")"
|
|
129
|
+
[[ -n "$latest_line" ]] ||
|
|
130
|
+
die "Could not find a '$archive_prefix-<version>.tgz' archive in '$resolved_shared_folder'."
|
|
131
|
+
|
|
132
|
+
IFS=$'\t' read -r package_version source_archive_path <<<"$latest_line"
|
|
133
|
+
destination_archive_path="$packages_folder/$(basename -- "$source_archive_path")"
|
|
134
|
+
|
|
135
|
+
while IFS= read -r -d '' existing_archive; do
|
|
136
|
+
if [[ "$(normalize_path "$existing_archive")" != "$(normalize_path "$destination_archive_path")" ]]; then
|
|
137
|
+
rm -f -- "$existing_archive"
|
|
138
|
+
fi
|
|
139
|
+
done < <(find "$packages_folder" -maxdepth 1 -type f -name "$archive_prefix-*.tgz" -print0)
|
|
140
|
+
|
|
141
|
+
cp -f -- "$source_archive_path" "$destination_archive_path"
|
|
142
|
+
set_package_dependency "$package_name" "file:./packages/$(basename -- "$destination_archive_path")"
|
|
143
|
+
|
|
144
|
+
printf "Copied %s %s to '%s'.\n" "$package_name" "$package_version" "$destination_archive_path"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
update_upgrade_script_if_newer() {
|
|
148
|
+
local archive_path="$1"
|
|
149
|
+
local script_path="$2"
|
|
150
|
+
|
|
151
|
+
python3 -c '
|
|
152
|
+
import os, re, stat, sys, tarfile, tempfile
|
|
153
|
+
|
|
154
|
+
archive_path, script_path, current_version = sys.argv[1], sys.argv[2], int(sys.argv[3])
|
|
155
|
+
entry_name = "package/template-customization/upgrade.sh.template"
|
|
156
|
+
|
|
157
|
+
with tarfile.open(archive_path, "r:gz") as archive:
|
|
158
|
+
try:
|
|
159
|
+
entry = archive.getmember(entry_name)
|
|
160
|
+
except KeyError:
|
|
161
|
+
sys.exit(0)
|
|
162
|
+
contents = archive.extractfile(entry).read().decode("utf-8")
|
|
163
|
+
|
|
164
|
+
match = re.search(r"(?m)^\\s*upgrade_script_version\\s*=\\s*(\\d+)\\s*$", contents)
|
|
165
|
+
if match is None:
|
|
166
|
+
raise RuntimeError("The packaged upgrade script does not define a valid upgrade_script_version.")
|
|
167
|
+
|
|
168
|
+
packaged_version = int(match.group(1))
|
|
169
|
+
if packaged_version <= current_version:
|
|
170
|
+
sys.exit(0)
|
|
171
|
+
|
|
172
|
+
script_dir = os.path.dirname(os.path.abspath(script_path))
|
|
173
|
+
original_mode = stat.S_IMODE(os.stat(script_path).st_mode)
|
|
174
|
+
fd, temporary_script_path = tempfile.mkstemp(prefix=".upgrade-", dir=script_dir)
|
|
175
|
+
try:
|
|
176
|
+
with os.fdopen(fd, "w", encoding="utf-8", newline="") as file:
|
|
177
|
+
file.write(contents)
|
|
178
|
+
os.chmod(temporary_script_path, original_mode)
|
|
179
|
+
os.replace(temporary_script_path, script_path)
|
|
180
|
+
finally:
|
|
181
|
+
if os.path.exists(temporary_script_path):
|
|
182
|
+
os.unlink(temporary_script_path)
|
|
183
|
+
|
|
184
|
+
print(f"Updated upgrade.sh from internal version {current_version} to {packaged_version}. Rerun the script to continue the package upgrade.")
|
|
185
|
+
sys.exit(10)
|
|
186
|
+
' "$archive_path" "$script_path" "$upgrade_script_version"
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
extract_chillsharp_ui_template_skills() {
|
|
190
|
+
local archive_path="$1"
|
|
191
|
+
local target_folder="$2"
|
|
192
|
+
|
|
193
|
+
python3 -c '
|
|
194
|
+
import os, shutil, sys, tarfile
|
|
195
|
+
|
|
196
|
+
archive_path, target_folder = sys.argv[1], sys.argv[2]
|
|
197
|
+
skills_dir = os.path.join(target_folder, ".agents", "skills")
|
|
198
|
+
skills_root = os.path.abspath(skills_dir)
|
|
199
|
+
prefix = "package/.agents/skills/"
|
|
200
|
+
|
|
201
|
+
if os.path.exists(skills_dir):
|
|
202
|
+
shutil.rmtree(skills_dir)
|
|
203
|
+
os.makedirs(skills_dir, exist_ok=True)
|
|
204
|
+
|
|
205
|
+
with tarfile.open(archive_path, "r:gz") as archive:
|
|
206
|
+
for entry in archive.getmembers():
|
|
207
|
+
if not entry.isfile() or not entry.name.startswith(prefix):
|
|
208
|
+
continue
|
|
209
|
+
relative_path = entry.name[len(prefix):]
|
|
210
|
+
destination = os.path.abspath(os.path.join(skills_root, relative_path))
|
|
211
|
+
if os.path.commonpath((skills_root, destination)) != skills_root:
|
|
212
|
+
raise RuntimeError(f"Refusing to extract outside the skills folder: {entry.name}")
|
|
213
|
+
os.makedirs(os.path.dirname(destination), exist_ok=True)
|
|
214
|
+
with archive.extractfile(entry) as source, open(destination, "wb") as output:
|
|
215
|
+
shutil.copyfileobj(source, output)
|
|
216
|
+
' "$archive_path" "$target_folder"
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
require_command python3
|
|
220
|
+
require_command jq
|
|
221
|
+
|
|
222
|
+
[[ -f "$package_json_path" ]] || die "Could not find package.json at '$package_json_path'."
|
|
223
|
+
mkdir -p -- "$packages_folder"
|
|
224
|
+
|
|
225
|
+
resolve_confirmed_shared_folder
|
|
226
|
+
|
|
227
|
+
latest_ui_core_line="$(latest_archive_line "$resolved_shared_folder" 'chill-sharp-ui-core')"
|
|
228
|
+
[[ -n "$latest_ui_core_line" ]] ||
|
|
229
|
+
die "Could not find a 'chill-sharp-ui-core-<version>.tgz' archive in '$resolved_shared_folder'."
|
|
230
|
+
IFS=$'\t' read -r _latest_ui_core_version latest_ui_core_archive_path <<<"$latest_ui_core_line"
|
|
231
|
+
if update_upgrade_script_if_newer "$latest_ui_core_archive_path" "${BASH_SOURCE[0]}"; then
|
|
232
|
+
:
|
|
233
|
+
else
|
|
234
|
+
update_status=$?
|
|
235
|
+
if [[ "$update_status" -eq 10 ]]; then
|
|
236
|
+
exit 0
|
|
237
|
+
fi
|
|
238
|
+
die 'Could not update upgrade.sh from the UI core package.'
|
|
239
|
+
fi
|
|
240
|
+
extract_chillsharp_ui_template_skills "$latest_ui_core_archive_path" "$script_dir"
|
|
241
|
+
|
|
242
|
+
copy_latest_package_archive '@chill-sharp/ui-core' 'chill-sharp-ui-core'
|
|
243
|
+
copy_latest_package_archive '@chill-sharp/ng-client' 'chill-sharp-ng-client'
|
|
244
|
+
copy_latest_package_archive '@chill-sharp/ts-client' 'chill-sharp-ts-client'
|
|
245
|
+
|
|
246
|
+
printf "Saved CHILL_NPM_SHARED_FOLDER to '%s'.\n" "$env_file"
|
|
247
|
+
|
|
248
|
+
if command -v npm >/dev/null 2>&1; then
|
|
249
|
+
package_lock_path="$script_dir/package-lock.json"
|
|
250
|
+
package_lock_backup_path="$package_lock_path.chill-sharp-upgrade.bak"
|
|
251
|
+
had_package_lock=false
|
|
252
|
+
if [[ -f "$package_lock_path" ]]; then
|
|
253
|
+
cp -f -- "$package_lock_path" "$package_lock_backup_path"
|
|
254
|
+
rm -f -- "$package_lock_path"
|
|
255
|
+
had_package_lock=true
|
|
256
|
+
fi
|
|
257
|
+
|
|
258
|
+
printf 'Refreshing package-lock.json and local file dependencies with npm install --ignore-scripts...\n'
|
|
259
|
+
if ! (cd "$script_dir" && npm install --ignore-scripts); then
|
|
260
|
+
if [[ "$had_package_lock" == true && -f "$package_lock_backup_path" ]]; then
|
|
261
|
+
mv -f -- "$package_lock_backup_path" "$package_lock_path"
|
|
262
|
+
fi
|
|
263
|
+
warn 'npm install --ignore-scripts did not complete successfully. Local archives were copied, but package-lock.json and node_modules may still need a manual refresh.'
|
|
264
|
+
else
|
|
265
|
+
rm -f -- "$package_lock_backup_path"
|
|
266
|
+
fi
|
|
267
|
+
else
|
|
268
|
+
warn 'npm was not found on PATH. Local archives were copied, but package-lock.json was not refreshed.'
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
printf 'UI template dependencies were upgraded from the shared npm folder.\n'
|