clispark 1.18.0 → 1.19.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clispark",
3
- "version": "1.18.0",
3
+ "version": "1.19.1",
4
4
  "description": "Interactive scaffolding tool for new CLI projects",
5
5
  "keywords": [
6
6
  "cli",
@@ -56,11 +56,14 @@
56
56
  "@types/node": "^22.10.5",
57
57
  "eslint": "^10.7.0",
58
58
  "jiti": "^2.7.0",
59
- "shx": "^0.3.4",
59
+ "shx": "^0.4.0",
60
60
  "tsup": "^8.3.5",
61
61
  "tsx": "^4.19.2",
62
62
  "typescript": "^5.7.2",
63
63
  "typescript-eslint": "^8.63.0",
64
64
  "vitest": "^4.1.10"
65
+ },
66
+ "overrides": {
67
+ "esbuild": "^0.28.1"
65
68
  }
66
69
  }
@@ -0,0 +1,26 @@
1
+ # Architecture
2
+
3
+ This project is a PowerShell module (`.psd1`/`.psm1`), not a single script — cmdlets get proper
4
+ tab-completion, pipeline support, and discoverability via `Get-Command`.
5
+
6
+ ## Auto-registration
7
+
8
+ Every `.ps1` file in `Public/` becomes an exported cmdlet automatically — no manual registration
9
+ step. The filename must match the function name inside it (e.g. `Get-Hello.ps1` defines
10
+ `function Get-Hello`).
11
+
12
+ ## Auto-logging and error handling
13
+
14
+ `Module.psm1` wraps every `Public/` function with a **function-proxy-wrapper** at import time:
15
+ logging (`started`/`completed`/`failed`) and error handling are added automatically, using
16
+ PowerShell's own `System.Management.Automation.ProxyCommand` API — the same mechanism PowerShell's
17
+ own module-remoting proxies use, so pipeline input and all parameter attributes are preserved
18
+ exactly. Cmdlet authors never write their own try/catch or logging calls.
19
+
20
+ ## Testing
21
+
22
+ [Pester](https://pester.dev/) — one `.Tests.ps1` file per cmdlet in `tests/`.
23
+
24
+ ## Logging
25
+
26
+ [PSFramework](https://psframework.org/) — see `Logging/Initialize-Logging.ps1`.
@@ -0,0 +1,27 @@
1
+ # Logging/Initialize-Logging.ps1 — PSFramework setup, loaded by Module.psm1 before any cmdlet
2
+ # is wrapped. Mirrors the Node/.NET templates' logging principles: redaction, retention, DEBUG
3
+ # streaming, a visible log path on both success and failure.
4
+
5
+ Import-Module PSFramework -ErrorAction Stop
6
+
7
+ $logDirectory = Join-Path ([Environment]::GetFolderPath('LocalApplicationData')) 'clispark-generated' 'Logs'
8
+ if (-not (Test-Path $logDirectory)) {
9
+ New-Item -ItemType Directory -Path $logDirectory -Force | Out-Null
10
+ }
11
+
12
+ Set-PSFLoggingProvider -Name 'logfile' -InstanceName 'default' -FilePath (Join-Path $logDirectory 'log-%date%.csv') -Enabled $true
13
+
14
+ if ($env:DEBUG) {
15
+ Set-PSFLoggingProvider -Name 'console' -InstanceName 'default' -Enabled $true
16
+ }
17
+
18
+ # Retention: remove log files older than 14 days, best-effort (matches the Node/.NET templates'
19
+ # LOG_RETENTION_DAYS convention — same default, same "never block the command on a sweep failure").
20
+ try {
21
+ $cutoff = (Get-Date).AddDays(-14)
22
+ Get-ChildItem -Path $logDirectory -Filter 'log-*.csv' -ErrorAction SilentlyContinue |
23
+ Where-Object { $_.LastWriteTime -lt $cutoff } |
24
+ Remove-Item -ErrorAction SilentlyContinue
25
+ } catch {
26
+ # Best-effort — a failed sweep must never block the command itself.
27
+ }
@@ -0,0 +1,15 @@
1
+ @{
2
+ RootModule = 'Module.psm1'
3
+ ModuleVersion = '0.1.0'
4
+ GUID = '00000000-0000-0000-0000-000000000000'
5
+ Author = 'Unknown'
6
+ Description = 'Scaffolded by clispark.'
7
+ PowerShellVersion = '7.4'
8
+ FunctionsToExport = '*'
9
+ RequiredModules = @('PSFramework', 'Pester', 'Microsoft.PowerShell.PSResourceGet')
10
+ PrivateData = @{
11
+ PSData = @{
12
+ Tags = @()
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,70 @@
1
+ # Module.psm1 — loads every cmdlet in Public/ and wraps it with automatic logging and
2
+ # error handling. Cmdlet authors never write their own try/catch or logging calls.
3
+
4
+ . (Join-Path $PSScriptRoot 'Logging' 'Initialize-Logging.ps1')
5
+
6
+ $publicFiles = Get-ChildItem -Path (Join-Path $PSScriptRoot 'Public') -Filter '*.ps1'
7
+ $publicFuncNames = $publicFiles.BaseName
8
+
9
+ foreach ($file in $publicFiles) {
10
+ . $file.FullName
11
+ $funcName = $file.BaseName
12
+
13
+ # Rename the real implementation FIRST, then build the proxy metadata against the RENAMED
14
+ # command — the generated begin-block re-resolves the wrapped command by name at call time,
15
+ # so building metadata from the original name before renaming would make the wrapper recurse
16
+ # into itself once installed under that same name (verified for real during the design spec).
17
+ $renamedName = "__orig_$funcName"
18
+ Rename-Item "Function:\$funcName" $renamedName
19
+ $renamedCmd = Get-Command $renamedName -CommandType Function
20
+ $metadata = [System.Management.Automation.CommandMetadata]::new($renamedCmd)
21
+
22
+ $paramBlock = [System.Management.Automation.ProxyCommand]::GetParamBlock($metadata)
23
+ $beginBlock = [System.Management.Automation.ProxyCommand]::GetBegin($metadata)
24
+ $processBlock = [System.Management.Automation.ProxyCommand]::GetProcess($metadata)
25
+ $endBlock = [System.Management.Automation.ProxyCommand]::GetEnd($metadata)
26
+ $cmdletBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($metadata)
27
+
28
+ $wrapperDef = @"
29
+ function $funcName {
30
+ $cmdletBinding
31
+ param(
32
+ $paramBlock
33
+ )
34
+ begin {
35
+ Write-PSFMessage -Level Verbose -Message "started: $funcName"
36
+ `$__sw = [System.Diagnostics.Stopwatch]::StartNew()
37
+ try {
38
+ $beginBlock
39
+ } catch {
40
+ Write-PSFMessage -Level Error -Message "failed: $funcName" -ErrorRecord `$_
41
+ throw
42
+ }
43
+ }
44
+ process {
45
+ try {
46
+ $processBlock
47
+ } catch {
48
+ Write-PSFMessage -Level Error -Message "failed: $funcName" -ErrorRecord `$_
49
+ throw
50
+ }
51
+ }
52
+ end {
53
+ try {
54
+ $endBlock
55
+ Write-PSFMessage -Level Verbose -Message "completed: $funcName (`$(`$__sw.ElapsedMilliseconds)ms)"
56
+ } catch {
57
+ Write-PSFMessage -Level Error -Message "failed: $funcName" -ErrorRecord `$_
58
+ throw
59
+ }
60
+ }
61
+ }
62
+ "@
63
+
64
+ Invoke-Expression $wrapperDef
65
+ }
66
+
67
+ # Export only the real Public/ function names — never `-Function *`, which would also export
68
+ # the renamed __orig_* internals and trigger PowerShell's "unapproved verb" warning on import
69
+ # (verified for real during the design spec).
70
+ Export-ModuleMember -Function $publicFuncNames
File without changes
@@ -0,0 +1,10 @@
1
+ function Get-Hello {
2
+ [CmdletBinding()]
3
+ param(
4
+ [Parameter(Position = 0)]
5
+ [string]$Name = 'World'
6
+ )
7
+ process {
8
+ Write-Output "Hello, $Name!"
9
+ }
10
+ }
@@ -0,0 +1,26 @@
1
+ # {{projectName}}
2
+
3
+ A PowerShell module scaffolded by [clispark](https://www.npmjs.com/package/clispark).
4
+
5
+ ## Usage
6
+
7
+ ```powershell
8
+ Import-Module ./Module.psd1
9
+ Get-Hello -Name 'World'
10
+ ```
11
+
12
+ ## Adding a new cmdlet
13
+
14
+ Run `clispark add` from this directory, or drop a new `.ps1` file into `Public/` following the
15
+ existing `Get-Hello.ps1` pattern — every function found there is automatically wrapped with
16
+ logging and error handling on module import, no manual try/catch needed.
17
+
18
+ ## Testing
19
+
20
+ ```powershell
21
+ Invoke-Pester ./tests
22
+ ```
23
+
24
+ ## Architecture
25
+
26
+ See [ARCHITECTURE.md](./ARCHITECTURE.md).
@@ -0,0 +1,2 @@
1
+ Logs/
2
+ *.log
@@ -0,0 +1,9 @@
1
+ Describe 'Get-Hello' {
2
+ It 'greets the given name' {
3
+ Get-Hello -Name 'Pester' | Should -Be 'Hello, Pester!'
4
+ }
5
+
6
+ It 'defaults to World when no name is given' {
7
+ Get-Hello | Should -Be 'Hello, World!'
8
+ }
9
+ }