@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.
Files changed (204) hide show
  1. package/.agents/skills/chillsharp-current-user-preferences/SKILL.md +70 -0
  2. package/.agents/skills/chillsharp-ui-template/SKILL.md +18 -0
  3. package/README.md +103 -0
  4. package/chill-sharp-ui-core.d.ts.map +1 -0
  5. package/doc/AIAssistedDevelopment/README.md +185 -0
  6. package/doc/AttachmentModel/README.md +173 -0
  7. package/doc/AuthenticationModel/README.md +213 -0
  8. package/doc/AuthenticationModel/how-to-integreate-auth-minimal-api.md +293 -0
  9. package/doc/ChillSharpClient.md +464 -0
  10. package/doc/ClientGeneration/README.md +172 -0
  11. package/doc/ComplianceGuide/README.md +178 -0
  12. package/doc/Configuration/README.md +94 -0
  13. package/doc/CurrentUserPreferences.md +114 -0
  14. package/doc/DateTimePolicy/README.md +154 -0
  15. package/doc/DateTimeSerialization.md +423 -0
  16. package/doc/Endpoints.md +260 -0
  17. package/doc/HowTo/01-simple-blog-sqlite.md +153 -0
  18. package/doc/HowTo/02-blog-schema-labels.md +140 -0
  19. package/doc/HowTo/03-authentication.md +218 -0
  20. package/doc/HowTo/04-blog-posts-one-to-many.md +194 -0
  21. package/doc/HowTo/05-docker-env-variables.md +274 -0
  22. package/doc/HowTo/06-chunk-transactions-autocomplete.md +196 -0
  23. package/doc/Mcp/ChatGPT.md +291 -0
  24. package/doc/Mcp/README.md +799 -0
  25. package/doc/MenuGuide/README.md +49 -0
  26. package/doc/ModelPreparation.md +255 -0
  27. package/doc/PermissionModel/README.md +277 -0
  28. package/doc/README.md +228 -0
  29. package/doc/ReferenceExistence.md +130 -0
  30. package/doc/RegisterContext.md +217 -0
  31. package/doc/UiCore/CRUD.md +170 -0
  32. package/doc/UiCore/README.md +13 -0
  33. package/doc/ValidationModel/README.md +117 -0
  34. package/doc/it/AIAssistedDevelopment/README.md +185 -0
  35. package/doc/it/AttachmentModel/README.md +173 -0
  36. package/doc/it/AuthenticationModel/README.md +171 -0
  37. package/doc/it/AuthenticationModel/how-to-integreate-auth-minimal-api.md +292 -0
  38. package/doc/it/ChillSharpClient.md +464 -0
  39. package/doc/it/ClientGeneration/README.md +152 -0
  40. package/doc/it/ComplianceGuide/README.md +178 -0
  41. package/doc/it/Configuration/README.md +94 -0
  42. package/doc/it/CurrentUserPreferences.md +114 -0
  43. package/doc/it/DateTimePolicy/README.md +154 -0
  44. package/doc/it/DateTimeSerialization.md +423 -0
  45. package/doc/it/Endpoints.md +260 -0
  46. package/doc/it/HowTo/01-simple-blog-sqlite.md +152 -0
  47. package/doc/it/HowTo/02-blog-schema-labels.md +139 -0
  48. package/doc/it/HowTo/03-authentication.md +221 -0
  49. package/doc/it/HowTo/04-blog-posts-one-to-many.md +193 -0
  50. package/doc/it/HowTo/05-docker-env-variables.md +268 -0
  51. package/doc/it/HowTo/06-chunk-transactions-autocomplete.md +196 -0
  52. package/doc/it/Mcp/ChatGPT.md +291 -0
  53. package/doc/it/Mcp/README.md +799 -0
  54. package/doc/it/MenuGuide/README.md +49 -0
  55. package/doc/it/ModelPreparation.md +254 -0
  56. package/doc/it/PermissionModel/README.md +190 -0
  57. package/doc/it/README.md +172 -0
  58. package/doc/it/ReferenceExistence.md +130 -0
  59. package/doc/it/RegisterContext.md +218 -0
  60. package/doc/it/UiCore/CRUD.md +170 -0
  61. package/doc/it/UiCore/README.md +13 -0
  62. package/doc/it/ValidationModel/README.md +117 -0
  63. package/fesm2022/chill-sharp-ui-core.mjs +16725 -0
  64. package/fesm2022/chill-sharp-ui-core.mjs.map +1 -0
  65. package/index.d.ts +6 -0
  66. package/lib/chill-sharp-ui-root.component.d.ts +6 -0
  67. package/lib/chill-sharp-ui-root.component.d.ts.map +1 -0
  68. package/lib/chill-sharp-ui.routes.d.ts +3 -0
  69. package/lib/chill-sharp-ui.routes.d.ts.map +1 -0
  70. package/lib/chill.config.d.ts +5 -0
  71. package/lib/chill.config.d.ts.map +1 -0
  72. package/lib/layouts/auth-shell.component.d.ts +8 -0
  73. package/lib/layouts/auth-shell.component.d.ts.map +1 -0
  74. package/lib/layouts/workspace-page.component.d.ts +49 -0
  75. package/lib/layouts/workspace-page.component.d.ts.map +1 -0
  76. package/lib/lib/chill-form.component.d.ts +151 -0
  77. package/lib/lib/chill-form.component.d.ts.map +1 -0
  78. package/lib/lib/chill-i18n-button-label.component.d.ts +27 -0
  79. package/lib/lib/chill-i18n-button-label.component.d.ts.map +1 -0
  80. package/lib/lib/chill-i18n-label.component.d.ts +30 -0
  81. package/lib/lib/chill-i18n-label.component.d.ts.map +1 -0
  82. package/lib/lib/chill-json-input.component.d.ts +31 -0
  83. package/lib/lib/chill-json-input.component.d.ts.map +1 -0
  84. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts +12 -0
  85. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts.map +1 -0
  86. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts +17 -0
  87. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts.map +1 -0
  88. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts +45 -0
  89. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts.map +1 -0
  90. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts +19 -0
  91. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts.map +1 -0
  92. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts +12 -0
  93. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts.map +1 -0
  94. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts +13 -0
  95. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts.map +1 -0
  96. package/lib/lib/chill-polymorphic-input.component.d.ts +452 -0
  97. package/lib/lib/chill-polymorphic-input.component.d.ts.map +1 -0
  98. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts +7 -0
  99. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts.map +1 -0
  100. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts +7 -0
  101. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts.map +1 -0
  102. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts +7 -0
  103. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts.map +1 -0
  104. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts +8 -0
  105. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts.map +1 -0
  106. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts +7 -0
  107. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts.map +1 -0
  108. package/lib/lib/chill-polymorphic-output.component.d.ts +75 -0
  109. package/lib/lib/chill-polymorphic-output.component.d.ts.map +1 -0
  110. package/lib/lib/chill-table.component.d.ts +434 -0
  111. package/lib/lib/chill-table.component.d.ts.map +1 -0
  112. package/lib/lib/chill-text-editor-dialog.component.d.ts +14 -0
  113. package/lib/lib/chill-text-editor-dialog.component.d.ts.map +1 -0
  114. package/lib/lib/crud-configuration.utils.d.ts +4 -0
  115. package/lib/lib/crud-configuration.utils.d.ts.map +1 -0
  116. package/lib/lib/culture-name-options.d.ts +3 -0
  117. package/lib/lib/culture-name-options.d.ts.map +1 -0
  118. package/lib/lib/date-format-options.d.ts +3 -0
  119. package/lib/lib/date-format-options.d.ts.map +1 -0
  120. package/lib/lib/iana-time-zone-options.d.ts +3 -0
  121. package/lib/lib/iana-time-zone-options.d.ts.map +1 -0
  122. package/lib/lib/notice-transition.directive.d.ts +17 -0
  123. package/lib/lib/notice-transition.directive.d.ts.map +1 -0
  124. package/lib/lib/schema-property-dialog.component.d.ts +74 -0
  125. package/lib/lib/schema-property-dialog.component.d.ts.map +1 -0
  126. package/lib/models/chill-auth.models.d.ts +176 -0
  127. package/lib/models/chill-auth.models.d.ts.map +1 -0
  128. package/lib/models/chill-menu.models.d.ts +12 -0
  129. package/lib/models/chill-menu.models.d.ts.map +1 -0
  130. package/lib/models/chill-schema.models.d.ts +141 -0
  131. package/lib/models/chill-schema.models.d.ts.map +1 -0
  132. package/lib/models/workspace-dialog.models.d.ts +16 -0
  133. package/lib/models/workspace-dialog.models.d.ts.map +1 -0
  134. package/lib/models/workspace-task.models.d.ts +36 -0
  135. package/lib/models/workspace-task.models.d.ts.map +1 -0
  136. package/lib/pages/confirm-reset-page.component.d.ts +21 -0
  137. package/lib/pages/confirm-reset-page.component.d.ts.map +1 -0
  138. package/lib/pages/crud/attachment-upload-dialog.component.d.ts +24 -0
  139. package/lib/pages/crud/attachment-upload-dialog.component.d.ts.map +1 -0
  140. package/lib/pages/crud/crud-page.component.d.ts +244 -0
  141. package/lib/pages/crud/crud-page.component.d.ts.map +1 -0
  142. package/lib/pages/login-page.component.d.ts +21 -0
  143. package/lib/pages/login-page.component.d.ts.map +1 -0
  144. package/lib/pages/permissions/auth-role-dialog.component.d.ts +29 -0
  145. package/lib/pages/permissions/auth-role-dialog.component.d.ts.map +1 -0
  146. package/lib/pages/permissions/auth-search-select.component.d.ts +28 -0
  147. package/lib/pages/permissions/auth-search-select.component.d.ts.map +1 -0
  148. package/lib/pages/permissions/auth-user-dialog.component.d.ts +35 -0
  149. package/lib/pages/permissions/auth-user-dialog.component.d.ts.map +1 -0
  150. package/lib/pages/permissions/permission-editor.component.d.ts +55 -0
  151. package/lib/pages/permissions/permission-editor.component.d.ts.map +1 -0
  152. package/lib/pages/permissions/permissions-page.component.d.ts +38 -0
  153. package/lib/pages/permissions/permissions-page.component.d.ts.map +1 -0
  154. package/lib/pages/permissions/role-permission.component.d.ts +43 -0
  155. package/lib/pages/permissions/role-permission.component.d.ts.map +1 -0
  156. package/lib/pages/permissions/user-permission.component.d.ts +43 -0
  157. package/lib/pages/permissions/user-permission.component.d.ts.map +1 -0
  158. package/lib/pages/register-page.component.d.ts +24 -0
  159. package/lib/pages/register-page.component.d.ts.map +1 -0
  160. package/lib/pages/reset-password-page.component.d.ts +18 -0
  161. package/lib/pages/reset-password-page.component.d.ts.map +1 -0
  162. package/lib/provide-chill-sharp-ui-core.d.ts +8 -0
  163. package/lib/provide-chill-sharp-ui-core.d.ts.map +1 -0
  164. package/lib/services/chill.service.d.ts +249 -0
  165. package/lib/services/chill.service.d.ts.map +1 -0
  166. package/lib/services/workspace-dialog.service.d.ts +22 -0
  167. package/lib/services/workspace-dialog.service.d.ts.map +1 -0
  168. package/lib/services/workspace-layout.service.d.ts +13 -0
  169. package/lib/services/workspace-layout.service.d.ts.map +1 -0
  170. package/lib/services/workspace-task-registry.service.d.ts +35 -0
  171. package/lib/services/workspace-task-registry.service.d.ts.map +1 -0
  172. package/lib/services/workspace-toolbar.service.d.ts +23 -0
  173. package/lib/services/workspace-toolbar.service.d.ts.map +1 -0
  174. package/lib/services/workspace.service.d.ts +114 -0
  175. package/lib/services/workspace.service.d.ts.map +1 -0
  176. package/lib/storage-keys.d.ts +5 -0
  177. package/lib/storage-keys.d.ts.map +1 -0
  178. package/lib/tasks/crud-task/crud-task.component.d.ts +33 -0
  179. package/lib/tasks/crud-task/crud-task.component.d.ts.map +1 -0
  180. package/lib/tasks/goto-url-task/goto-url-task.component.d.ts +31 -0
  181. package/lib/tasks/goto-url-task/goto-url-task.component.d.ts.map +1 -0
  182. package/lib/workspace/confirm-message-dialog.component.d.ts +16 -0
  183. package/lib/workspace/confirm-message-dialog.component.d.ts.map +1 -0
  184. package/lib/workspace/entity-options-dialog.component.d.ts +29 -0
  185. package/lib/workspace/entity-options-dialog.component.d.ts.map +1 -0
  186. package/lib/workspace/external-task-api.d.ts +2 -0
  187. package/lib/workspace/external-task-api.d.ts.map +1 -0
  188. package/lib/workspace/user-profile-dialog.component.d.ts +30 -0
  189. package/lib/workspace/user-profile-dialog.component.d.ts.map +1 -0
  190. package/lib/workspace/workspace-dialog-host.component.d.ts +26 -0
  191. package/lib/workspace/workspace-dialog-host.component.d.ts.map +1 -0
  192. package/lib/workspace/workspace-menu-item-dialog.component.d.ts +61 -0
  193. package/lib/workspace/workspace-menu-item-dialog.component.d.ts.map +1 -0
  194. package/lib/workspace/workspace-menu.component.d.ts +104 -0
  195. package/lib/workspace/workspace-menu.component.d.ts.map +1 -0
  196. package/lib/workspace/workspace-taskbar.component.d.ts +14 -0
  197. package/lib/workspace/workspace-taskbar.component.d.ts.map +1 -0
  198. package/package.json +54 -0
  199. package/public-api.d.ts +56 -0
  200. package/public-api.d.ts.map +1 -0
  201. package/service-worker/chill-sharp-service-worker.js +166 -0
  202. package/styles/core-theme.scss +1268 -0
  203. package/template-customization/upgrade.ps1.template +342 -0
  204. 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'