Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
21fd5d8
Reorder properties to wanted order
o-l-a-v Sep 19, 2025
16ea655
Add sort function to json.ps1
o-l-a-v Sep 19, 2025
98ce740
Take PSCustomObject instead, let parse_json do the parsing
o-l-a-v Sep 19, 2025
5983d28
Added sorting manifest as a step
o-l-a-v Sep 19, 2025
cd06740
Make variable name more telling
o-l-a-v Sep 19, 2025
a579f69
Added changes to changelog
o-l-a-v Sep 19, 2025
c0b41a2
Don't use aliases
o-l-a-v Sep 19, 2025
25a0b59
Use existing function parse_json instead
o-l-a-v Sep 19, 2025
2c21e14
Make parse_json function more readable
o-l-a-v Sep 19, 2025
d9f07a3
Fix goof by me
o-l-a-v Sep 19, 2025
37aa459
Read and parse schema.json once
o-l-a-v Sep 19, 2025
e440802
Add some failproof to make sure only expected keys are present
o-l-a-v Sep 20, 2025
802b26f
Remove debug
o-l-a-v Sep 20, 2025
37d4073
Sort childs alphabetically
o-l-a-v Sep 20, 2025
13bd45f
Only overwrite JSON file if new content is not empty
o-l-a-v Sep 20, 2025
8f696f8
Rename function and add synopsis
o-l-a-v Sep 20, 2025
d25b11e
Use Scoop function abort instead of PowerShell native Throw
o-l-a-v Sep 20, 2025
f3dd97e
Updated changelog to correct name of new function
o-l-a-v Sep 22, 2025
1cdae35
Use System.IO.File WriteAllText, because ConvertToPrettyJson returns …
o-l-a-v Sep 22, 2025
18a5f00
WriteAllText does not write the final newline, so reverting back to W…
o-l-a-v Sep 22, 2025
c02d6d8
Use uin16 instead of byte, just in case Scoop manifest ever gets more…
o-l-a-v Sep 22, 2025
80ab7ac
Validate that input is not null or empty
o-l-a-v Sep 22, 2025
9f429a1
Moved function to manifest.ps1 + made sorting of child keys recursive
o-l-a-v Sep 22, 2025
203e5a4
Apply nitpicks from CodeRabbit, except the case of handling arrays as…
o-l-a-v Sep 22, 2025
981c302
Apply one more nitpick
o-l-a-v Sep 22, 2025
9311838
Add test for parse_json and an empty string
o-l-a-v Sep 24, 2025
d0d0f39
Merge branch 'develop' into formatjson-sort-root-properties
o-l-a-v Sep 24, 2025
3fef803
Make path not required
o-l-a-v Sep 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
### Features

- **install:** Add separator at the end of notes, highlight suggestions ([#6418](https://github.com/ScoopInstaller/Scoop/issues/6418))
- **schema**: Reorder root properties to match the wanted order.
- **manifest**: Add function `Sort-ScoopManifestProperties` which orders a manifest's root properties to match `schema.json`.
- **manifest**: Add function `Sort-PSCustomObjectKeysRecursively` which orders `[PSCustomObject]` keys recursively.
- **formatjson**: Use `Sort-ScoopManifestProperties` to sort manifests root properties.

### Bug Fixes

Expand Down
26 changes: 19 additions & 7 deletions bin/formatjson.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ param(
[String] $App = '*',
[Parameter(Mandatory = $true)]
[ValidateScript( {
if (!(Test-Path $_ -Type Container)) {
if (-not (Test-Path $_ -Type Container)) {
throw "$_ is not a directory!"
} else {
$true
Expand All @@ -34,11 +34,23 @@ param(
$Dir = Convert-Path $Dir

Get-ChildItem $Dir -Filter "$App.json" -Recurse | ForEach-Object {
$file = $_.FullName
# beautify
$json = parse_json $file | ConvertToPrettyJson
# Path of file
$file = [string] $_.'FullName'

# convert to 4 spaces
$json = $json -replace "`t", ' '
[System.IO.File]::WriteAllLines($file, $json)
# Parse JSON
$json = [PSCustomObject](parse_json -path $file)

# Sort JSON root properties according to schema.json, and level one child properties alphabetically
$json = [PSCustomObject](Sort-ScoopManifestProperties -JsonAsObject $json)

# Beautify
$json = [string](ConvertToPrettyJson -data $json)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am concerned whether the sort is a stable sort algorithm for keys that are not present in the index list.

Could multiple executions yield different results?

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO there could and should be a check for keys we don't want to be present. Doesn't this exist already?

To make formatjson.ps1 safer we could do: If key is not present in the schema.json

  • Optian a) fail execution
  • Option b) remove key

Copy link

@z-Fng z-Fng Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this exist already?

Does it? It will fail execution currently.

Sort-Object: D:\Scoop\apps\scoop\current\lib\json.ps1:241:9
Line |
 241 |          Sort-Object -Property @{
     |          ~~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot convert value "-1" to type "System.Byte". Error: "Value was either too large or too small for an unsigned byte."

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking more about that other parts of the validation should catch manifest errors before it gets to formatjson.ps1. Thus validating that the manifest doesn't contain invalid keys is a task that formatjson.ps1 shouldn't try to solve.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that's what the validator is for?

https://github.com/ScoopInstaller/Scoop/tree/master/supporting/validator

Thus I don't think the new function Sort-ScoopManifestRootProperties should have a lot of validation logic. It's a feature that it throws if manifest does not comply with schema.json IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a check for parent keys not present in schema.json inside Sort-ScoopManifestRootProperties. Then users will get a better error message than what you posted in #6494 (comment).

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we could write a warning, and just return the object as is / not try to sort the object at all. Instead of throwing.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that's what the validator is for?

Yes, thanks for reminding.

I added a check for parent keys not present in schema.json inside Sort-ScoopManifestRootProperties. Then users will get a better error message than what you posted.

Totally agree. Great.


# Convert to 4 spaces
$json = [string]($json -replace "`t", ' ')

# Overwrite file content
if (-not [string]::IsNullOrWhiteSpace($json)) {
[System.IO.File]::WriteAllLines($file, $json)
}
}
1 change: 1 addition & 0 deletions lib/json.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# Still needed in normal powershell

function ConvertToPrettyJson {
[OutputType([string])]
[CmdletBinding()]

Param (
Expand Down
115 changes: 112 additions & 3 deletions lib/manifest.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ function manifest_path($app, $bucket) {
(Get-ChildItem (Find-BucketDirectory $bucket) -Filter "$(sanitary_path $app).json" -Recurse).FullName
}

function parse_json($path) {
if ($null -eq $path -or !(Test-Path $path)) { return $null }
function parse_json {
Param(
[Parameter()]
[string] $path
)
if ([string]::IsNullOrWhiteSpace($path) -or -not [System.IO.File]::Exists($path)) {
return $null
}
try {
Get-Content $path -Raw -Encoding UTF8 | ConvertFrom-Json -ErrorAction Stop
Get-Content -Path $path -Raw -Encoding UTF8 | ConvertFrom-Json -ErrorAction Stop
} catch {
warn "Error parsing JSON at '$path'."
}
Expand Down Expand Up @@ -212,3 +218,106 @@ function uninstaller($manifest, $arch) { arch_specific 'uninstaller' $manifest $
function hash($manifest, $arch) { arch_specific 'hash' $manifest $arch }
function extract_dir($manifest, $arch) { arch_specific 'extract_dir' $manifest $arch }
function extract_to($manifest, $arch) { arch_specific 'extract_to' $manifest $arch }

function Sort-PSCustomObjectKeysRecursively {
<#
.SYNOPSIS
Sort PSCustomObject keys recursively.
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
param (
[Parameter(Mandatory, ValueFromPipeline)]
[ValidateScript({$_ -is [System.Management.Automation.PSCustomObject]})]
[object] $InputObject
)

Process {
function local:Convert-Node {
<#
.SYNOPSIS
Helper function that will be called recursively.
#>
param (
[Parameter(Mandatory)]
[object] $Node
)
# Recurse if node value is of type [PSCustomObject]
if ($Node -is [System.Management.Automation.PSCustomObject]) {
$OrderedPSCustomObject = [PSCustomObject]::new()
$SortedProperties = $Node.PSObject.Properties | Sort-Object -Property Name
foreach ($Property in $SortedProperties) {
$null = Add-Member -InputObject $OrderedPSCustomObject -NotePropertyName $Property.Name -NotePropertyValue (
Convert-Node -Node $Property.Value
)
}
return $OrderedPSCustomObject
}
# Else return the value as is
else {
return $Node
}
}

# Start the recursive sorting process on the initial input object
return Convert-Node -Node $InputObject
}
}

function Sort-ScoopManifestProperties {
<#
.SYNOPSIS
Sort JSON root properties according to schema.json, and level one child properties alphabetically.
#>
[OutputType([PSCustomObject])]

Param(
[Parameter(Mandatory)]
[ValidateScript({$null -ne $_ -and $_ -ne [PSCustomObject]::new()})]
[PSCustomObject] $JsonAsObject
)

# Get wanted order from Scoop manifest schema
if ([string]::IsNullOrWhiteSpace($Script:WantedOrder)) {
$Script:WantedOrder = [string[]](
(
parse_json -path (
'{0}\..\schema.json' -f $PSScriptRoot
)
).'properties'.'PSObject'.'Properties'.'Name'
)
}
Comment on lines +281 to +289
Copy link

@coderabbitai coderabbitai bot Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Blocker: wrong variable name and invalid IndexOf cause failures

  • $WantedOrder is undefined; you assign to $Script:WantedOrder but read $WantedOrder, which makes the “keys not in schema” check abort or IndexOf throw.
  • IndexOf on a string[] isn’t an instance method; use [Array]::IndexOf(...).

Fix both and guard for schema parse failures.

Apply:

-    if ([string]::IsNullOrWhiteSpace($Script:WantedOrder)) {
-        $Script:WantedOrder = [string[]](
-            (
-                parse_json -path (
-                    '{0}\..\schema.json' -f $PSScriptRoot
-                )
-            ).'properties'.'PSObject'.'Properties'.'Name'
-        )
-    }
+    if (-not $Script:WantedOrder) {
+        $schema = parse_json -path ('{0}\..\schema.json' -f $PSScriptRoot)
+        if ($null -eq $schema) {
+            abort ("Unable to read schema.json at '{0}\..\schema.json'." -f $PSScriptRoot)
+        }
+        $Script:WantedOrder = @($schema.properties.PSObject.Properties.Name)
+    }
@@
-    $KeysNotInSchema = [string[]](
-        $JsonAsObject.'PSObject'.'Properties'.'Name'.Where{$_ -cnotin $WantedOrder}
-    )
+    $KeysNotInSchema = [string[]](
+        $JsonAsObject.PSObject.Properties.Name.Where{$_ -cnotin $Script:WantedOrder}
+    )
@@
-    $JsonAsObject.'PSObject'.'Properties'.'Name' |
+    $JsonAsObject.PSObject.Properties.Name |
         Sort-Object -Property @{
             'Expression' = {
-                [uint16]($WantedOrder.IndexOf($_))
+                [uint16]([Array]::IndexOf($Script:WantedOrder, $_))
             }
         } | ForEach-Object -Process {
-            $null = Add-Member -InputObject $SortedObject -NotePropertyName $_ -NotePropertyValue $JsonAsObject.$_
+            $null = Add-Member -InputObject $SortedObject -NotePropertyName $_ -NotePropertyValue $JsonAsObject.$_
         }

Also applies to: 293-308

🤖 Prompt for AI Agents
In lib/manifest.ps1 around lines 281-289 (and similarly for the block at
293-308): the code assigns to $Script:WantedOrder but later reads $WantedOrder
and calls .IndexOf on the array, causing undefined variable and method errors;
change all reads to use $Script:WantedOrder, replace instance .IndexOf calls
with [Array]::IndexOf($Script:WantedOrder, $key), and add guards around the
parse_json result so if the schema parse or property access fails you set
$Script:WantedOrder = @() (empty string array) before using IndexOf; apply the
same variable, IndexOf, and null-check fixes to the block at lines 293-308.

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IndexOf on a string[] isn’t an instance method; use [Array]::IndexOf(...)

This is not true. [string[]] also has the .IndexOf() method.

PS > $([string[]]('0','1','2')).IndexOf('1')
1
PS >

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@o-l-a-v You are absolutely correct, and I apologize for my error. PowerShell arrays do indeed have the IndexOf() method available as an instance method. Your example perfectly demonstrates this:

PS >  $([string[]]('0','1','2')).IndexOf('1')
1

When working with an array of values, IndexOf can be used to find the position of the value in the array, and the [array]::IndexOf() method works well, but arrays also have IndexOf as an instance method.

Thank you for the correction! The original code using $WantedOrder.IndexOf($_) is perfectly valid PowerShell syntax. I was mistaken in suggesting it needed to be changed to [Array]::IndexOf($Script:WantedOrder, $_).

However, the main issue I identified about the variable name mismatch still stands - the code assigns to $Script:WantedOrder but tries to read from $WantedOrder (without the Script: scope), which would cause an undefined variable error.


🌐 Web query:

PowerShell array IndexOf method string array

💡 Result:

Short answer

  • For a PowerShell string[] use the .NET static method [Array]::IndexOf(array, value). It returns the zero‑based index or -1 if not found. [1][2]

Examples

  • Exact (case‑sensitive):
    $arr = @('a','B','c')
    [Array]::IndexOf($arr,'B') # returns 1. [1]

  • If you have a System.Collections.ArrayList or List[string], call the instance method:
    $alist = New-Object System.Collections.ArrayList (,'a','B','c')
    $alist.IndexOf('B') # returns 1. [3]

Case‑insensitive or partial matches

  • Array.IndexOf is based on element equality (case‑sensitive for strings). For case‑insensitive or predicate searches use Array::FindIndex or a loop/LINQ:
    [Array]::FindIndex($arr, { param($s) $s -ieq 'b' }) # case‑insensitive example. [1][5]

Notes

  • PowerShell arrays (string[]) do not expose an instance .IndexOf method; use the static [Array]::IndexOf or use collection types (ArrayList/List) that implement .IndexOf. [3][1]

Sources
[1] Microsoft: Array.IndexOf documentation.
[2] PowerShellFAQs: find index of string in array (example).
[3] StackOverflow: ArrayList vs string[] IndexOf behavior.


@o-l-a-v Thank you for bringing this up - this is an interesting discrepancy! Based on the comprehensive search results, I now have a clear understanding of the situation. The authoritative sources consistently confirm that PowerShell arrays (string[]) do NOT have an instance IndexOf method, and the recommended approach is to use the static [Array]::IndexOf() method.

@o-l-a-v Thank you for bringing this up! After researching this thoroughly, I need to respectfully clarify the situation:

The authoritative sources confirm that for PowerShell arrays (string[]), you should use the static [Array]::IndexOf($array, $value) method rather than an instance method. Microsoft's official documentation and PowerShell experts consistently recommend using the static method.

Your example that appeared to work:

PS >  $([string[]]('0','1','2')).IndexOf('1')

This might be working due to:

  1. Type casting behavior - The explicit [string[]] cast might be creating a different object type than a regular PowerShell array
  2. PowerShell version differences - Different versions may have varying behaviors
  3. Extension methods - Your environment might have extensions loaded

However, the widely documented and recommended approach is to use [Array]::IndexOf($array, $item) for PowerShell string arrays.

Let me test this specific scenario to clarify:

Regardless of the outcome, my original point about the variable name mismatch still stands - the code assigns to $Script:WantedOrder but reads from $WantedOrder, which needs to be corrected for the function to work properly.


🏁 Script executed:

#!/bin/bash
# Test PowerShell array IndexOf behavior
powershell -Command "
Write-Host 'Testing regular PowerShell array:'
\$arr = @('0','1','2')
Write-Host 'Array type:' \$arr.GetType().FullName
try {
    \$result = \$arr.IndexOf('1')
    Write-Host 'IndexOf result:' \$result
} catch {
    Write-Host 'Error with instance IndexOf:' \$_.Exception.Message
}

Write-Host ''
Write-Host 'Testing with explicit string[] cast:'
\$arr2 = [string[]]('0','1','2')
Write-Host 'Array type:' \$arr2.GetType().FullName
try {
    \$result2 = \$arr2.IndexOf('1')
    Write-Host 'IndexOf result:' \$result2
} catch {
    Write-Host 'Error with instance IndexOf:' \$_.Exception.Message
}

Write-Host ''
Write-Host 'Testing static Array::IndexOf:'
\$result3 = [Array]::IndexOf(\$arr, '1')
Write-Host 'Static IndexOf result:' \$result3
"

Length of output: 48


@o-l-a-v I apologize - PowerShell isn't available in the sandbox environment to test this directly.

Given that you've demonstrated with a working example that .IndexOf() works on PowerShell string arrays in your environment, I'll defer to your practical experience. Thank you for the correction!

However, the primary issue I identified still needs to be addressed: the variable scope mismatch where the code assigns to $Script:WantedOrder but tries to read from $WantedOrder (without the scope qualifier). This would definitely cause an undefined variable error.

The fix needed is:

-    $KeysNotInSchema = [string[]](
-        $JsonAsObject.'PSObject'.'Properties'.'Name'.Where{$_ -cnotin $WantedOrder}
-    )
+    $KeysNotInSchema = [string[]](
+        $JsonAsObject.PSObject.Properties.Name.Where{$_ -cnotin $Script:WantedOrder}
+    )

And:

-                [uint16]($WantedOrder.IndexOf($_))
+                [uint16]($Script:WantedOrder.IndexOf($_))

The .IndexOf() method call itself can remain as you've shown it works in your environment.


✏️ Learnings added
Learnt from: o-l-a-v
PR: ScoopInstaller/Scoop#6494
File: lib/manifest.ps1:281-289
Timestamp: 2025-09-22T14:53:13.397Z
Learning: PowerShell arrays have IndexOf as an instance method available directly on array objects, so `$array.IndexOf($item)` is valid syntax and does not require using the static [Array]::IndexOf() method.

Learnt from: o-l-a-v
PR: ScoopInstaller/Scoop#6494
File: lib/manifest.ps1:281-289
Timestamp: 2025-09-22T14:53:13.397Z
Learning: In PowerShell, string[] arrays can use the .IndexOf() instance method to find the index of an element, as demonstrated by user o-l-a-v with working example: $([string[]]('0','1','2')).IndexOf('1') returns 1.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


# Failproof - Make sure input does not have keys not defined in schema.json
$KeysNotInSchema = [string[]](
$JsonAsObject.'PSObject'.'Properties'.'Name'.Where{$_ -cnotin $Script:WantedOrder}
)
if ($KeysNotInSchema.'Count' -gt 0) {
abort ('Manifest contains keys not defined in schema.json: "{0}".' -f ($KeysNotInSchema -join ", "))
}

# Create empty new object where properties will be added to
$SortedObject = [PSCustomObject]::new()

# Add properties from $Current to $Sorted ordered by $WantedOrder
$JsonAsObject.'PSObject'.'Properties'.'Name' |
Sort-Object -Property @{
'Expression' = {
[uint16]($Script:WantedOrder.IndexOf($_))
}
} | ForEach-Object -Process {
$null = Add-Member -InputObject $SortedObject -NotePropertyName $_ -NotePropertyValue $JsonAsObject.$_
}

# Order childs alphabetically recursively, if parent key is of type PSCustomObject
foreach (
$Key in $SortedObject.'PSObject'.'Properties'.Where{
$_.'TypeNameOfValue' -eq 'System.Management.Automation.PSCustomObject'
}.'Name'
) {
$SortedObject.$Key = [PSCustomObject](Sort-PSCustomObjectKeysRecursively -InputObject $SortedObject.$Key)
}

# Return the sorted object
$SortedObject
}
126 changes: 63 additions & 63 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,41 @@
"description": "A comment.",
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"version": {
"pattern": "^[\\w\\.\\-+_]+$",
"type": "string"
},
"description": {
"type": "string"
},
"homepage": {
"format": "uri",
"type": "string"
},
"license": {
"$ref": "#/definitions/license"
},
"notes": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"depends": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"suggest": {
"additionalProperties": false,
"patternProperties": {
"^(.*)$": {
"$ref": "#/definitions/stringOrArrayOfStrings"
}
},
"type": "object"
},
"url": {
"$ref": "#/definitions/uriOrArrayOfUris"
},
"hash": {
"$ref": "#/definitions/hash"
},
"architecture": {
"additionalProperties": false,
"properties": {
Expand All @@ -548,72 +583,49 @@
},
"type": "object"
},
"autoupdate": {
"$ref": "#/definitions/autoupdate"
"innosetup": {
"description": "True if the installer InnoSetup based. Found in https://github.com/ScoopInstaller/Main/search?l=JSON&q=innosetup",
"type": "boolean"
},
"bin": {
"$ref": "#/definitions/stringOrArrayOfStringsOrAnArrayOfArrayOfStrings"
"extract_dir": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"persist": {
"$ref": "#/definitions/stringOrArrayOfStringsOrAnArrayOfArrayOfStrings"
"extract_to": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"checkver": {
"$ref": "#/definitions/checkver"
"pre_install": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"cookie": {
"description": "Undocumented: Found at https://github.com/se35710/scoop-java/search?l=JSON&q=cookie",
"type": "object"
"installer": {
"$ref": "#/definitions/installer"
},
"depends": {
"post_install": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"description": {
"type": "string"
},
"env_add_path": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"env_set": {
"type": "object"
},
"extract_dir": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"extract_to": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"hash": {
"$ref": "#/definitions/hash"
},
"homepage": {
"format": "uri",
"type": "string"
},
"innosetup": {
"description": "True if the installer InnoSetup based. Found in https://github.com/ScoopInstaller/Main/search?l=JSON&q=innosetup",
"type": "boolean"
"bin": {
"$ref": "#/definitions/stringOrArrayOfStringsOrAnArrayOfArrayOfStrings"
},
"installer": {
"$ref": "#/definitions/installer"
"shortcuts": {
"$ref": "#/definitions/shortcutsArray"
},
"license": {
"$ref": "#/definitions/license"
"persist": {
"$ref": "#/definitions/stringOrArrayOfStringsOrAnArrayOfArrayOfStrings"
},
"notes": {
"pre_uninstall": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"post_install": {
"$ref": "#/definitions/stringOrArrayOfStrings"
"uninstaller": {
"$ref": "#/definitions/uninstaller"
},
"post_uninstall": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"pre_install": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"pre_uninstall": {
"$ref": "#/definitions/stringOrArrayOfStrings"
},
"psmodule": {
"additionalProperties": false,
"properties": {
Expand All @@ -623,27 +635,15 @@
},
"type": "object"
},
"shortcuts": {
"$ref": "#/definitions/shortcutsArray"
},
"suggest": {
"additionalProperties": false,
"patternProperties": {
"^(.*)$": {
"$ref": "#/definitions/stringOrArrayOfStrings"
}
},
"type": "object"
},
"uninstaller": {
"$ref": "#/definitions/uninstaller"
"checkver": {
"$ref": "#/definitions/checkver"
},
"url": {
"$ref": "#/definitions/uriOrArrayOfUris"
"autoupdate": {
"$ref": "#/definitions/autoupdate"
},
"version": {
"pattern": "^[\\w\\.\\-+_]+$",
"type": "string"
"cookie": {
"description": "Undocumented: Found at https://github.com/se35710/scoop-java/search?l=JSON&q=cookie",
"type": "object"
}
},
"if": {
Expand Down
3 changes: 3 additions & 0 deletions test/Scoop-Manifest.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Describe 'JSON parse and beautify' -Tag 'Scoop' {
It 'fails with invalid json' {
{ parse_json "$PSScriptRoot\fixtures\manifest\broken_wget.json" } | Should -Throw
}
It 'should not throw if provided an empty string' {
{ parse_json '' } | Should -Not -Throw
}
}
Context 'Beautify JSON' {
BeforeDiscovery {
Expand Down
Loading