summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinteck <contact@minteck.org>2022-11-28 17:31:34 +0100
committerMinteck <contact@minteck.org>2022-11-28 17:31:34 +0100
commit7923aa8942b55884320ef2428417e3ee4b121613 (patch)
tree7993632f2898b1998f25b11ce40a8d2eb3d44730
downloadmistyos-og-7923aa8942b55884320ef2428417e3ee4b121613.tar.gz
mistyos-og-7923aa8942b55884320ef2428417e3ee4b121613.tar.bz2
mistyos-og-7923aa8942b55884320ef2428417e3ee4b121613.zip
Initial commitHEADmane
-rw-r--r--.idea/.gitignore8
-rw-r--r--.idea/jsLibraryMappings.xml6
-rw-r--r--.idea/mistyos.iml12
-rw-r--r--.idea/modules.xml8
-rw-r--r--Components/ChangeDir/index.js27
-rw-r--r--Components/ChangeDir/metadata.yml33
-rw-r--r--Components/Clear/index.js3
-rw-r--r--Components/Clear/metadata.yml20
-rw-r--r--Components/CoreDaemon/index.js352
-rw-r--r--Components/CoreDaemon/metadata.yml55
-rw-r--r--Components/CurrentDir/index.js3
-rw-r--r--Components/CurrentDir/metadata.yml20
-rw-r--r--Components/DisplayFile/hex.js44
-rw-r--r--Components/DisplayFile/index.js43
-rw-r--r--Components/DisplayFile/metadata.yml46
-rw-r--r--Components/Documentation/index.js129
-rw-r--r--Components/Documentation/metadata.yml30
-rw-r--r--Components/InternalShell/index.js14
-rw-r--r--Components/InternalShell/metadata.yml17
-rw-r--r--Components/ListDirectory/index.js85
-rw-r--r--Components/ListDirectory/metadata.yml40
-rw-r--r--Components/Restart/index.js11
-rw-r--r--Components/Restart/metadata.yml26
-rw-r--r--Components/ShowMisty/index.js30
-rw-r--r--Components/ShowMisty/metadata.yml22
-rw-r--r--Components/Shutdown/index.js11
-rw-r--r--Components/Shutdown/metadata.yml27
-rw-r--r--LaunchDaemons/MistyOS.yml9
-rw-r--r--LaunchDaemons/Node.yml9
-rw-r--r--LaunchDaemons/Test.yml7
-rw-r--r--MistyCore/banner.js37
-rw-r--r--MistyCore/error.js155
-rw-r--r--MistyCore/index.js150
-rw-r--r--MistyCore/log.js14
l---------MistyCore/node_modules/.bin/semver1
l---------MistyCore/node_modules/.bin/systeminformation1
-rw-r--r--MistyCore/node_modules/.package-lock.json134
-rw-r--r--MistyCore/node_modules/ansi-styles/index.d.ts345
-rw-r--r--MistyCore/node_modules/ansi-styles/index.js163
-rw-r--r--MistyCore/node_modules/ansi-styles/license9
-rw-r--r--MistyCore/node_modules/ansi-styles/package.json56
-rw-r--r--MistyCore/node_modules/ansi-styles/readme.md152
-rw-r--r--MistyCore/node_modules/chalk/index.d.ts415
-rw-r--r--MistyCore/node_modules/chalk/license9
-rw-r--r--MistyCore/node_modules/chalk/package.json68
-rw-r--r--MistyCore/node_modules/chalk/readme.md341
-rw-r--r--MistyCore/node_modules/chalk/source/index.js229
-rw-r--r--MistyCore/node_modules/chalk/source/templates.js134
-rw-r--r--MistyCore/node_modules/chalk/source/util.js39
-rw-r--r--MistyCore/node_modules/color-convert/CHANGELOG.md54
-rw-r--r--MistyCore/node_modules/color-convert/LICENSE21
-rw-r--r--MistyCore/node_modules/color-convert/README.md68
-rw-r--r--MistyCore/node_modules/color-convert/conversions.js839
-rw-r--r--MistyCore/node_modules/color-convert/index.js81
-rw-r--r--MistyCore/node_modules/color-convert/package.json48
-rw-r--r--MistyCore/node_modules/color-convert/route.js97
-rw-r--r--MistyCore/node_modules/color-name/LICENSE8
-rw-r--r--MistyCore/node_modules/color-name/README.md11
-rw-r--r--MistyCore/node_modules/color-name/index.js152
-rw-r--r--MistyCore/node_modules/color-name/package.json28
-rw-r--r--MistyCore/node_modules/has-flag/index.d.ts39
-rw-r--r--MistyCore/node_modules/has-flag/index.js8
-rw-r--r--MistyCore/node_modules/has-flag/license9
-rw-r--r--MistyCore/node_modules/has-flag/package.json46
-rw-r--r--MistyCore/node_modules/has-flag/readme.md89
-rw-r--r--MistyCore/node_modules/lru-cache/LICENSE15
-rw-r--r--MistyCore/node_modules/lru-cache/README.md166
-rw-r--r--MistyCore/node_modules/lru-cache/index.js334
-rw-r--r--MistyCore/node_modules/lru-cache/package.json34
-rw-r--r--MistyCore/node_modules/semver/LICENSE15
-rw-r--r--MistyCore/node_modules/semver/README.md568
-rwxr-xr-xMistyCore/node_modules/semver/bin/semver.js183
-rw-r--r--MistyCore/node_modules/semver/classes/comparator.js136
-rw-r--r--MistyCore/node_modules/semver/classes/index.js5
-rw-r--r--MistyCore/node_modules/semver/classes/range.js522
-rw-r--r--MistyCore/node_modules/semver/classes/semver.js287
-rw-r--r--MistyCore/node_modules/semver/functions/clean.js6
-rw-r--r--MistyCore/node_modules/semver/functions/cmp.js52
-rw-r--r--MistyCore/node_modules/semver/functions/coerce.js52
-rw-r--r--MistyCore/node_modules/semver/functions/compare-build.js7
-rw-r--r--MistyCore/node_modules/semver/functions/compare-loose.js3
-rw-r--r--MistyCore/node_modules/semver/functions/compare.js5
-rw-r--r--MistyCore/node_modules/semver/functions/diff.js23
-rw-r--r--MistyCore/node_modules/semver/functions/eq.js3
-rw-r--r--MistyCore/node_modules/semver/functions/gt.js3
-rw-r--r--MistyCore/node_modules/semver/functions/gte.js3
-rw-r--r--MistyCore/node_modules/semver/functions/inc.js18
-rw-r--r--MistyCore/node_modules/semver/functions/lt.js3
-rw-r--r--MistyCore/node_modules/semver/functions/lte.js3
-rw-r--r--MistyCore/node_modules/semver/functions/major.js3
-rw-r--r--MistyCore/node_modules/semver/functions/minor.js3
-rw-r--r--MistyCore/node_modules/semver/functions/neq.js3
-rw-r--r--MistyCore/node_modules/semver/functions/parse.js33
-rw-r--r--MistyCore/node_modules/semver/functions/patch.js3
-rw-r--r--MistyCore/node_modules/semver/functions/prerelease.js6
-rw-r--r--MistyCore/node_modules/semver/functions/rcompare.js3
-rw-r--r--MistyCore/node_modules/semver/functions/rsort.js3
-rw-r--r--MistyCore/node_modules/semver/functions/satisfies.js10
-rw-r--r--MistyCore/node_modules/semver/functions/sort.js3
-rw-r--r--MistyCore/node_modules/semver/functions/valid.js6
-rw-r--r--MistyCore/node_modules/semver/index.js88
-rw-r--r--MistyCore/node_modules/semver/internal/constants.js17
-rw-r--r--MistyCore/node_modules/semver/internal/debug.js9
-rw-r--r--MistyCore/node_modules/semver/internal/identifiers.js23
-rw-r--r--MistyCore/node_modules/semver/internal/parse-options.js11
-rw-r--r--MistyCore/node_modules/semver/internal/re.js182
-rw-r--r--MistyCore/node_modules/semver/package.json86
-rw-r--r--MistyCore/node_modules/semver/preload.js2
-rw-r--r--MistyCore/node_modules/semver/range.bnf16
-rw-r--r--MistyCore/node_modules/semver/ranges/gtr.js4
-rw-r--r--MistyCore/node_modules/semver/ranges/intersects.js7
-rw-r--r--MistyCore/node_modules/semver/ranges/ltr.js4
-rw-r--r--MistyCore/node_modules/semver/ranges/max-satisfying.js25
-rw-r--r--MistyCore/node_modules/semver/ranges/min-satisfying.js24
-rw-r--r--MistyCore/node_modules/semver/ranges/min-version.js61
-rw-r--r--MistyCore/node_modules/semver/ranges/outside.js80
-rw-r--r--MistyCore/node_modules/semver/ranges/simplify.js47
-rw-r--r--MistyCore/node_modules/semver/ranges/subset.js244
-rw-r--r--MistyCore/node_modules/semver/ranges/to-comparators.js8
-rw-r--r--MistyCore/node_modules/semver/ranges/valid.js11
-rw-r--r--MistyCore/node_modules/supports-color/browser.js5
-rw-r--r--MistyCore/node_modules/supports-color/index.js135
-rw-r--r--MistyCore/node_modules/supports-color/license9
-rw-r--r--MistyCore/node_modules/supports-color/package.json53
-rw-r--r--MistyCore/node_modules/supports-color/readme.md76
-rw-r--r--MistyCore/node_modules/systeminformation/LICENSE20
-rw-r--r--MistyCore/node_modules/systeminformation/README.md1088
-rw-r--r--MistyCore/node_modules/systeminformation/lib/audio.js216
-rw-r--r--MistyCore/node_modules/systeminformation/lib/battery.js308
-rw-r--r--MistyCore/node_modules/systeminformation/lib/bluetooth.js229
-rwxr-xr-xMistyCore/node_modules/systeminformation/lib/cli.js31
-rw-r--r--MistyCore/node_modules/systeminformation/lib/cpu.js1702
-rw-r--r--MistyCore/node_modules/systeminformation/lib/docker.js751
-rw-r--r--MistyCore/node_modules/systeminformation/lib/dockerSocket.js327
-rw-r--r--MistyCore/node_modules/systeminformation/lib/filesystem.js1301
-rw-r--r--MistyCore/node_modules/systeminformation/lib/graphics.js1066
-rw-r--r--MistyCore/node_modules/systeminformation/lib/index.d.ts996
-rw-r--r--MistyCore/node_modules/systeminformation/lib/index.js504
-rw-r--r--MistyCore/node_modules/systeminformation/lib/internet.js240
-rw-r--r--MistyCore/node_modules/systeminformation/lib/memory.js547
-rw-r--r--MistyCore/node_modules/systeminformation/lib/network.js1736
-rw-r--r--MistyCore/node_modules/systeminformation/lib/osinfo.js1154
-rw-r--r--MistyCore/node_modules/systeminformation/lib/printer.js210
-rw-r--r--MistyCore/node_modules/systeminformation/lib/processes.js1274
-rw-r--r--MistyCore/node_modules/systeminformation/lib/system.js831
-rw-r--r--MistyCore/node_modules/systeminformation/lib/usb.js258
-rw-r--r--MistyCore/node_modules/systeminformation/lib/users.js393
-rw-r--r--MistyCore/node_modules/systeminformation/lib/util.js1281
-rw-r--r--MistyCore/node_modules/systeminformation/lib/virtualbox.js107
-rw-r--r--MistyCore/node_modules/systeminformation/lib/wifi.js744
-rw-r--r--MistyCore/node_modules/systeminformation/package.json99
-rw-r--r--MistyCore/node_modules/yallist/LICENSE15
-rw-r--r--MistyCore/node_modules/yallist/README.md204
-rw-r--r--MistyCore/node_modules/yallist/iterator.js8
-rw-r--r--MistyCore/node_modules/yallist/package.json29
-rw-r--r--MistyCore/node_modules/yallist/yallist.js426
-rw-r--r--MistyCore/node_modules/yaml/LICENSE13
-rw-r--r--MistyCore/node_modules/yaml/README.md143
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/compose-collection.js59
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/compose-doc.js40
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/compose-node.js92
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/compose-scalar.js80
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/composer.js217
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-map.js110
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js194
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-seq.js45
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/resolve-end.js37
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js200
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js223
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/resolve-props.js134
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/util-contains-newline.js34
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js27
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js15
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/compose/util-map-includes.js17
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/doc/Document.js332
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/doc/anchors.js72
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/doc/applyReviver.js54
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/doc/createNode.js85
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/doc/directives.js169
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/errors.js57
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/index.js17
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/log.js14
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/node_modules/tslib/tslib.es6.js164
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/Alias.js94
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/Collection.js147
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/Node.js48
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/Pair.js36
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/Scalar.js23
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/YAMLMap.js116
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/YAMLSeq.js97
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js104
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/nodes/toJS.js37
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/parse/cst-scalar.js214
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/parse/cst-stringify.js61
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/parse/cst-visit.js97
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/parse/cst.js98
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/parse/lexer.js701
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/parse/line-counter.js39
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/parse/parser.js950
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/public-api.js99
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/Schema.js38
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/common/map.js42
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/common/null.js15
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/common/seq.js33
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/common/string.js14
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/core/bool.js19
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/core/float.js43
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/core/int.js38
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/core/schema.js23
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/json/schema.js62
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/tags.js83
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js66
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js26
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js46
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js71
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js73
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js77
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js37
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js92
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js101
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/stringify/foldFlowLines.js135
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/stringify/stringify.js122
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/stringify/stringifyCollection.js151
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/stringify/stringifyComment.js20
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/stringify/stringifyDocument.js85
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/stringify/stringifyNumber.js24
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/stringify/stringifyPair.js125
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/stringify/stringifyString.js314
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/util.js9
-rw-r--r--MistyCore/node_modules/yaml/browser/dist/visit.js233
-rw-r--r--MistyCore/node_modules/yaml/browser/index.js5
-rw-r--r--MistyCore/node_modules/yaml/browser/package.json3
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/compose-collection.d.ts5
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/compose-collection.js61
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/compose-doc.d.ts6
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/compose-doc.js42
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/compose-node.d.ts27
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/compose-node.js95
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/compose-scalar.d.ts5
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/compose-scalar.js82
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/composer.d.ts62
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/composer.js221
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-block-map.d.ts6
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-block-map.js112
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts10
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-block-scalar.js196
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-block-seq.d.ts5
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-block-seq.js47
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-end.d.ts6
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-end.js39
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts6
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-flow-collection.js202
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts10
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-flow-scalar.js225
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-props.d.ts22
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/resolve-props.js136
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/util-contains-newline.d.ts2
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/util-contains-newline.js36
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts2
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/util-empty-scalar-position.js29
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts3
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/util-flow-indent-check.js17
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/util-map-includes.d.ts4
-rw-r--r--MistyCore/node_modules/yaml/dist/compose/util-map-includes.js19
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/Document.d.ts139
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/Document.js334
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/anchors.d.ts24
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/anchors.js77
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/applyReviver.d.ts9
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/applyReviver.js56
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/createNode.d.ts17
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/createNode.js87
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/directives.d.ts49
-rw-r--r--MistyCore/node_modules/yaml/dist/doc/directives.js171
-rw-r--r--MistyCore/node_modules/yaml/dist/errors.d.ts21
-rw-r--r--MistyCore/node_modules/yaml/dist/errors.js62
-rw-r--r--MistyCore/node_modules/yaml/dist/index.d.ts21
-rw-r--r--MistyCore/node_modules/yaml/dist/index.js50
-rw-r--r--MistyCore/node_modules/yaml/dist/log.d.ts3
-rw-r--r--MistyCore/node_modules/yaml/dist/log.js17
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Alias.d.ts28
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Alias.js96
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Collection.d.ts73
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Collection.js151
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Node.d.ts59
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Node.js66
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Pair.d.ts21
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Pair.js39
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Scalar.d.ts42
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/Scalar.js26
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/YAMLMap.d.ts47
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/YAMLMap.js119
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/YAMLSeq.d.ts58
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/YAMLSeq.js99
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts4
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/addPairToJSMap.js106
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/toJS.d.ts30
-rw-r--r--MistyCore/node_modules/yaml/dist/nodes/toJS.js39
-rw-r--r--MistyCore/node_modules/yaml/dist/options.d.ts331
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/cst-scalar.d.ts64
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/cst-scalar.js218
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/cst-stringify.d.ts8
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/cst-stringify.js63
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/cst-visit.d.ts39
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/cst-visit.js99
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/cst.d.ts106
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/cst.js112
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/lexer.d.ts87
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/lexer.js703
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/line-counter.d.ts22
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/line-counter.js41
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/parser.d.ts84
-rw-r--r--MistyCore/node_modules/yaml/dist/parse/parser.js954
-rw-r--r--MistyCore/node_modules/yaml/dist/public-api.d.ts43
-rw-r--r--MistyCore/node_modules/yaml/dist/public-api.js104
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/Schema.d.ts18
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/Schema.js40
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/common/map.d.ts2
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/common/map.js44
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/common/null.d.ts4
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/common/null.js17
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/common/seq.d.ts2
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/common/seq.js35
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/common/string.d.ts2
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/common/string.js16
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/core/bool.d.ts4
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/core/bool.js21
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/core/float.d.ts4
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/core/float.js47
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/core/int.d.ts4
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/core/int.js42
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/core/schema.d.ts1
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/core/schema.js25
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/json-schema.d.ts69
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/json/schema.d.ts2
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/json/schema.js64
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/tags.d.ts40
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/tags.js86
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/types.d.ts82
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts2
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/binary.js68
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts7
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/bool.js29
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts4
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/float.js50
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts5
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/int.js76
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts25
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/omap.js76
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts10
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/pairs.js81
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts1
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/schema.js39
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts26
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/set.js95
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts6
-rw-r--r--MistyCore/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js105
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/foldFlowLines.d.ts34
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/foldFlowLines.js140
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringify.d.ts20
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringify.js125
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyCollection.d.ts17
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyCollection.js153
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyComment.d.ts10
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyComment.js24
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyDocument.d.ts3
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyDocument.js87
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyNumber.d.ts2
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyNumber.js26
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyPair.d.ts3
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyPair.js127
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyString.d.ts3
-rw-r--r--MistyCore/node_modules/yaml/dist/stringify/stringifyString.js316
-rw-r--r--MistyCore/node_modules/yaml/dist/test-events.d.ts4
-rw-r--r--MistyCore/node_modules/yaml/dist/test-events.js134
-rw-r--r--MistyCore/node_modules/yaml/dist/util.d.ts9
-rw-r--r--MistyCore/node_modules/yaml/dist/util.js24
-rw-r--r--MistyCore/node_modules/yaml/dist/visit.d.ts102
-rw-r--r--MistyCore/node_modules/yaml/dist/visit.js236
-rw-r--r--MistyCore/node_modules/yaml/package.json94
-rw-r--r--MistyCore/node_modules/yaml/util.d.ts3
-rw-r--r--MistyCore/node_modules/yaml/util.js2
-rw-r--r--MistyCore/package-lock.json218
-rw-r--r--MistyCore/package.json8
-rw-r--r--MistyCore/power.js128
-rw-r--r--MistyCore/power/reboot.js12
-rw-r--r--MistyCore/power/shutdown.js12
-rw-r--r--MistyCore/service.js216
-rw-r--r--MistyCore/shell.js709
-rw-r--r--MistyCore/socket.js68
-rw-r--r--MistyCore/test.js7
-rw-r--r--MistyOSVersion1
-rw-r--r--ROADMAP.md17
-rw-r--r--StartupItems/001--MistyOSRoot.js3
-rw-r--r--StartupItems/002--Logs.js13
-rw-r--r--StartupItems/100--Preferences.js15
-rw-r--r--StartupItems/200--Hostname.js6
-rw-r--r--StartupItems/201--Keyboard.js3
-rw-r--r--StartupItems/999--Shell.js8
399 files changed, 46447 insertions, 0 deletions
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml
new file mode 100644
index 0000000..d23208f
--- /dev/null
+++ b/.idea/jsLibraryMappings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="JavaScriptLibraryMappings">
+ <includedPredefinedLibrary name="Node.js Core" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/mistyos.iml b/.idea/mistyos.iml
new file mode 100644
index 0000000..0c8867d
--- /dev/null
+++ b/.idea/mistyos.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+ <component name="NewModuleRootManager">
+ <content url="file://$MODULE_DIR$">
+ <excludeFolder url="file://$MODULE_DIR$/temp" />
+ <excludeFolder url="file://$MODULE_DIR$/.tmp" />
+ <excludeFolder url="file://$MODULE_DIR$/tmp" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module> \ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..33e8be7
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/mistyos.iml" filepath="$PROJECT_DIR$/.idea/mistyos.iml" />
+ </modules>
+ </component>
+</project> \ No newline at end of file
diff --git a/Components/ChangeDir/index.js b/Components/ChangeDir/index.js
new file mode 100644
index 0000000..db9d82e
--- /dev/null
+++ b/Components/ChangeDir/index.js
@@ -0,0 +1,27 @@
+const fs = require('fs');
+const path = require('path');
+const chalk = require(__dirname + '/../../MistyCore/node_modules/chalk');
+
+module.exports = (arguments) => {
+ if (arguments._finals.length > 0) {
+ let newDirectory = path.resolve(arguments._finals[0]);
+
+ if (fs.existsSync(newDirectory)) {
+ try {
+ fs.accessSync(newDirectory, fs.constants.R_OK);
+
+ if (!fs.lstatSync(newDirectory).isDirectory()) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Not a directory: ") + arguments['_finals'][0]);
+ } else {
+ process.chdir(newDirectory);
+ }
+ } catch (e) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Permission denied: ") + arguments['_finals'][0]);
+ }
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such file or directory: ") + arguments['_finals'][0]);
+ }
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Missing operand"));
+ }
+} \ No newline at end of file
diff --git a/Components/ChangeDir/metadata.yml b/Components/ChangeDir/metadata.yml
new file mode 100644
index 0000000..3818d75
--- /dev/null
+++ b/Components/ChangeDir/metadata.yml
@@ -0,0 +1,33 @@
+description: Changes the directory commands work from
+internal: true
+
+aliases:
+ - cd
+ - chdir
+ - chwd
+
+manual:
+ summary: |
+ This command changes the current working directory (CWD) for a specified directory.
+
+ parameters: []
+
+ final:
+ name: Dir
+ description: The directory to change to
+ required: true
+ multiple: false
+ command: false
+ path: true
+ daemon: false
+
+ examples:
+ - command: ChangeDir /
+ description: Changes directory to go to the system's root directory
+
+ - command: ChangeDir ..
+ description: Changes directory to go to the parent directory
+
+ compatibility:
+ mistyos: '>=1.0.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/Clear/index.js b/Components/Clear/index.js
new file mode 100644
index 0000000..68c98ce
--- /dev/null
+++ b/Components/Clear/index.js
@@ -0,0 +1,3 @@
+module.exports = () => {
+ console.clear();
+} \ No newline at end of file
diff --git a/Components/Clear/metadata.yml b/Components/Clear/metadata.yml
new file mode 100644
index 0000000..fa28b6b
--- /dev/null
+++ b/Components/Clear/metadata.yml
@@ -0,0 +1,20 @@
+description: Clears the current screen
+internal: true
+
+aliases:
+ - cls
+ - clearscreen
+
+manual:
+ summary: |
+ This command clears the current screen.
+
+ parameters: []
+
+ final: null
+
+ examples: []
+
+ compatibility:
+ mistyos: '>=1.0.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/CoreDaemon/index.js b/Components/CoreDaemon/index.js
new file mode 100644
index 0000000..5e830b8
--- /dev/null
+++ b/Components/CoreDaemon/index.js
@@ -0,0 +1,352 @@
+let arguments = JSON.parse(process.argv[2]);
+const chalk = require(__dirname + '/../../MistyCore/node_modules/chalk');
+const YAML = require(__dirname + '/../../MistyCore/node_modules/yaml');
+const si = require(__dirname + '/../../MistyCore/node_modules/systeminformation');
+const fs = require('fs');
+const net = require("net");
+let systemRoot = "/System/Library";
+
+function size(bytes) {
+ if (bytes > 1024) {
+ if (bytes > 1024**2) {
+ if (bytes > 1024**3) {
+ if (bytes > 1024**4) {
+ return (bytes / 1024**4).toFixed(2) + "T";
+ } else {
+ return (bytes / 1024**3).toFixed(2) + "G";
+ }
+ } else {
+ return (bytes / 1024**2).toFixed(2) + "M";
+ }
+ } else {
+ return (bytes / 1024).toFixed(2) + "K";
+ }
+ } else {
+ return bytes + "B";
+ }
+}
+
+function waitForState(daemon, status) {
+ return new Promise((resolve) => {
+ let i = 0;
+ let me = setInterval(() => {
+ if (status === "running") {
+ if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() !== "-1" && fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() !== "-3" && fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() !== "-2") {
+ clearInterval(me);
+
+ if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() !== "0") {
+ console.log(daemon + " is now running with PID " + fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim());
+ } else if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() !== "-2") {
+ console.log(daemon + " has failed\nRun 'CoreDaemon -Status " + daemon + "' for details; 'CoreDaemon -ForceStop " + daemon + "' to force stop.");
+ process.exit(2);
+ } else {
+ console.log(daemon + " has now started");
+ }
+
+ resolve();
+ }
+ } else if (status === "stopped") {
+ if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() === "-1") {
+ clearInterval(me);
+ console.log(daemon + " is now stopped");
+ resolve();
+ }
+ if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() === "-2") {
+ clearInterval(me);
+ console.log(daemon + " has failed\nRun 'CoreDaemon -Status " + daemon + "' for details; 'CoreDaemon -ForceStop " + daemon + "' to force stop.");
+ process.exit(2);
+ resolve();
+ }
+ } else {
+ clearInterval(me);
+ resolve();
+ }
+
+ if (i >= 100) {
+ console.log("Timed out waiting for " + daemon + " after 10 seconds. Has the launch daemon failed?\nRun 'CoreDaemon -Status " + daemon + "' for details; 'CoreDaemon -ForceStop " + daemon + "' to force stop.");
+ process.exit(2);
+ }
+
+ i++;
+ }, 100);
+ });
+}
+
+(async () => {
+ let processes = (await si.processes()).list;
+
+ if (arguments['start'] && !arguments['stop'] && !arguments['restart'] && !arguments['status'] && !arguments['forcestop']) {
+ if (arguments['_finals'].length > 0) {
+ if (!fs.existsSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0])) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such launch daemon: ") + arguments['_finals'][0]);
+ return;
+ }
+
+ let state; switch (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString()) { case "0": state = "running"; break; case "-1": state = "stopped"; break; case "-2": state = "failed"; break; default: state = "running"; break }
+
+ if (state === "running") {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("The launch daemon is not stopped or failed"));
+ return;
+ }
+
+ const socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", () => {
+ console.log("Waiting for " + arguments['_finals'][0] + " to have started...");
+ socket.write(JSON.stringify({
+ action: "SERVICE",
+ payload: {
+ option: "start",
+ service: arguments['_finals'][0] + ".yml"
+ }
+ }));
+ waitForState(arguments['_finals'][0], "running");
+ });
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Missing operand"));
+ }
+ } else if (arguments['stop'] && !arguments['start'] && !arguments['restart'] && !arguments['status'] && !arguments['forcestop']) {
+ if (arguments['_finals'].length > 0) {
+ if (!fs.existsSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0])) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such launch daemon: ") + arguments['_finals'][0]);
+ return;
+ }
+
+ let state; switch (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString()) { case "0": state = "running"; break; case "-1": state = "stopped"; break; case "-2": state = "failed"; break; default: state = "running"; break }
+
+ if (state !== "running") {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("The launch daemon is not running"));
+ return;
+ }
+
+ const socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", async () => {
+ console.log("Waiting for " + arguments['_finals'][0] + " to have stopped...");
+ socket.write(JSON.stringify({
+ action: "SERVICE",
+ payload: {
+ option: "stop",
+ service: arguments['_finals'][0] + ".yml"
+ }
+ }));
+ await waitForState(arguments['_finals'][0], "stopped");
+ });
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Missing operand"));
+ }
+ } else if (arguments['forcestop'] && !arguments['start'] && !arguments['restart'] && !arguments['status'] && !arguments['stop']) {
+ if (arguments['_finals'].length > 0) {
+ if (!fs.existsSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0])) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such launch daemon: ") + arguments['_finals'][0]);
+ return;
+ }
+
+ let state; switch (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString()) { case "0": state = "running"; break; case "-1": state = "stopped"; break; case "-2": state = "failed"; break; default: state = "running"; break }
+
+ if (state !== "running") {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("The launch daemon is not running"));
+ return;
+ }
+
+ const socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", async () => {
+ console.log("Waiting for " + arguments['_finals'][0] + " to have force-stopped...");
+ socket.write(JSON.stringify({
+ action: "SERVICE",
+ payload: {
+ option: "forcestop",
+ service: arguments['_finals'][0] + ".yml"
+ }
+ }));
+ await waitForState(arguments['_finals'][0], "stopped");
+ });
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Missing operand"));
+ }
+ } else if (arguments['restart'] && !arguments['stop'] && !arguments['start'] && !arguments['status'] && !arguments['forcestop']) {
+ if (arguments['_finals'].length > 0) {
+ if (!fs.existsSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0])) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such launch daemon: ") + arguments['_finals'][0]);
+ return;
+ }
+
+ let state; switch (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString()) { case "0": state = "running"; break; case "-1": state = "stopped"; break; case "-2": state = "failed"; break; default: state = "running"; break }
+
+ if (state !== "running") {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("The launch daemon is not running"));
+ return;
+ }
+
+ const socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", async () => {
+ console.log("Waiting for " + arguments['_finals'][0] + " to have restarted...");
+ socket.write(JSON.stringify({
+ action: "SERVICE",
+ payload: {
+ option: "restart",
+ service: arguments['_finals'][0] + ".yml"
+ }
+ }));
+ await waitForState(arguments['_finals'][0], "running");
+ });
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Missing operand"));
+ }
+ } else if (arguments['status'] && !arguments['stop'] && !arguments['restart'] && !arguments['start'] && !arguments['forcestop']) {
+ if (arguments['_finals'].length > 0) {
+ if (!fs.existsSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0])) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such launch daemon: ") + arguments['_finals'][0]);
+ return;
+ }
+
+ let state; switch (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString()) { case "0": state = "running"; break; case "-1": state = "stopped"; break; case "-3": state = "starting"; break; case "-2": state = "failed"; break; default: state = "running"; break }
+
+ let name = arguments['_finals'][0], displayName = arguments['_finals'][0];
+ let service = YAML.parse(fs.readFileSync(systemRoot + "/LaunchDaemons/" + name + ".yml").toString());
+
+ let memoryUsage;
+ let pid;
+ let parent = "-";
+
+ switch (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString()) {
+ case "0":
+ case "-1":
+ case "-2":
+ case "-3":
+ memoryUsage = "-";
+ pid = "-";
+ break;
+
+ default:
+ let _processInfo = processes.filter(i => i.pid === parseInt(fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString()));
+
+ if (_processInfo.length > 0) {
+ pid = fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString() + " (" + _processInfo[0].name + ")";
+
+ let _parentInfo = processes.filter(i => i.pid === _processInfo[0].parentPid);
+ if (_parentInfo.length > 0) {
+ parent = _processInfo[0].parentPid + " (" + _parentInfo[0].name + ")";
+ } else {
+ parent = _processInfo[0].parentPid;
+ }
+
+ memoryUsage = size(_processInfo[0].memVsz);
+ } else {
+ pid = fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + arguments['_finals'][0]).toString();
+ memoryUsage = "-";
+ }
+
+ break;
+ }
+
+ let statusColor;
+
+ switch (state) {
+ case "running":
+ statusColor = chalk.green("running");
+ break;
+
+ case "starting":
+ statusColor = chalk.yellow("starting");
+ break;
+
+ case "failed":
+ statusColor = chalk.cyan("failed");
+ break;
+
+ case "stopped":
+ statusColor = chalk.red("stopped");
+ break;
+
+ default:
+ statusColor = chalk.gray("unknown");
+ break;
+ }
+
+ let reachDate = "-";
+
+ if (fs.existsSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + arguments['_finals'][0])) {
+ reachDate = new Date(parseInt(fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + arguments['_finals'][0]).toString())).toString();
+ }
+
+ let autoStart;
+ if (service.metadata.target === false) {
+ autoStart = chalk.gray("manual");
+ } else {
+ if (!isNaN(parseInt(service.metadata.target)) && parseInt(service.metadata.target) > -1 && parseInt(service.metadata.target) < 10) {
+ autoStart = "on target " + parseInt(service.metadata.target);
+ } else {
+ autoStart = chalk.red("invalid");
+ }
+ }
+
+ console.log(name + " - " + (service.metadata.description ?? "<no description>"));
+ console.log(chalk.cyan(" Loaded from:") + " " + systemRoot + "/LaunchDaemons/" + name + ".yml");
+ console.log(chalk.cyan(" Auto-start:") + " " + autoStart);
+ console.log(chalk.cyan(" Status:") + " " + statusColor);
+ console.log(chalk.cyan(" Reached:") + " " + reachDate);
+ console.log(chalk.cyan(" Main PID:") + " " + pid);
+ console.log(chalk.cyan(" Initiator:") + " " + parent);
+ console.log(chalk.cyan(" Memory:") + " " + memoryUsage);
+
+ if (service.commands.stop || service.commands.restart) {
+ console.log(chalk.cyan(" Type:") + " MistyCore:RunOnce");
+ } else {
+ console.log(chalk.cyan(" Type:") + " MistyCore:Daemon");
+ }
+
+ console.log("");
+
+ switch (state) {
+ case "running":
+ console.log("Run 'Logger -Unit " + name + "' to view logs; 'CoreDaemon -Stop " + name + "' to stop.");
+ break;
+
+ case "starting":
+ console.log("Run 'Logger -Unit " + name + "' to view logs; 'CoreDaemon -ForceStop " + name + "' to abort.");
+ break;
+
+ case "failed":
+ console.log("Run 'Logger -Unit " + name + "' to view logs; 'CoreDaemon -Start " + name + "' to start.");
+ break;
+
+ case "stopped":
+ console.log("Run 'Logger -Unit " + name + "' to view logs; 'CoreDaemon -Start " + name + "' to start.");
+ break;
+
+ default:
+ console.log("Run 'Logger -Unit " + name + "' to view logs");
+ break;
+ }
+ } else {
+ for (let name of fs.readdirSync(systemRoot + "/LaunchDaemons")) {
+ let daemon = name.substring(0, name.length - 4);
+
+ if (fs.existsSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon)) {
+ let state; switch (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString()) { case "0": state = "running"; break; case "-1": state = "stopped"; break; case "-3": state = "starting"; break; case "-2": state = "failed"; break; default: state = "running"; break }
+
+ switch (state) {
+ case "running":
+ console.log(" [ " + chalk.green("+") + " ] " + daemon);
+ break;
+
+ case "starting":
+ console.log(" [ " + chalk.yellow("W") + " ] " + daemon);
+ break;
+
+ case "failed":
+ console.log(" [ " + chalk.cyan("x") + " ] " + daemon);
+ break;
+
+ case "stopped":
+ console.log(" [ " + chalk.red("-") + " ] " + daemon);
+ break;
+
+ default:
+ console.log(" [ " + chalk.gray("?") + " ] " + daemon);
+ break;
+ }
+ } else {
+ console.log(" [ " + chalk.gray("?") + " ] " + daemon);
+ }
+ }
+ }
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Only exactly one operation can be done at a time"));
+ }
+})(); \ No newline at end of file
diff --git a/Components/CoreDaemon/metadata.yml b/Components/CoreDaemon/metadata.yml
new file mode 100644
index 0000000..7cea718
--- /dev/null
+++ b/Components/CoreDaemon/metadata.yml
@@ -0,0 +1,55 @@
+description: Manages launch daemons running on the system
+internal: false
+
+aliases:
+ - service
+ - systemctl
+ - rc-service
+
+manual:
+ summary: |
+ This command starts, stops, gets the status and restarts launch daemons on the system.
+
+ parameters:
+ - name: Start
+ description: Start a launch daemon
+ required: false
+
+ - name: Stop
+ description: Stop a launch daemon
+ required: false
+
+ - name: ForceStop
+ description: Force-stop a launch daemon, having it exit immediately without finishing properly
+ required: false
+
+ - name: Restart
+ description: Restart a launch daemon
+ required: false
+
+ - name: Status
+ description: Show the status of a launch daemon
+ required: false
+
+ final:
+ name: LaunchDaemon
+ description: The launch daemon to manage
+ required: false
+ multiple: false
+ command: false
+ path: false
+ daemon: true
+
+ examples:
+ - command: CoreDaemon -Restart Something
+ description: Restarts the launch daemon named Something
+
+ - command: CoreDaemon -ForceStop HangingThing
+ description: Forces the launch daemon named HangingThing to stop
+
+ - command: CoreDaemon -Status
+ description: Shows the status of all launch daemons on the system
+
+ compatibility:
+ mistyos: '>=1.2.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/CurrentDir/index.js b/Components/CurrentDir/index.js
new file mode 100644
index 0000000..9d954fc
--- /dev/null
+++ b/Components/CurrentDir/index.js
@@ -0,0 +1,3 @@
+module.exports = () => {
+ console.log(process.cwd());
+} \ No newline at end of file
diff --git a/Components/CurrentDir/metadata.yml b/Components/CurrentDir/metadata.yml
new file mode 100644
index 0000000..a8f5a32
--- /dev/null
+++ b/Components/CurrentDir/metadata.yml
@@ -0,0 +1,20 @@
+description: Returns the name of the current working directory
+internal: true
+
+aliases:
+ - pwd
+ - cwd
+
+manual:
+ summary: |
+ This command returns the current working directory (CWD) commands run from.
+
+ parameters: []
+
+ final: null
+
+ examples: []
+
+ compatibility:
+ mistyos: '>=1.0.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/DisplayFile/hex.js b/Components/DisplayFile/hex.js
new file mode 100644
index 0000000..f062608
--- /dev/null
+++ b/Components/DisplayFile/hex.js
@@ -0,0 +1,44 @@
+const chalk = require(__dirname + '/../../MistyCore/node_modules/chalk');
+
+function hexEight(dec) {
+ let hex = Math.round(dec).toString(16);
+ let zero = "00000000";
+ return zero.substring(0, 8 - hex.length) + hex;
+}
+
+function fixLength(string, length) {
+ let end = " ".repeat(length);
+ if (string.length > length) return string.substring(0, length);
+
+ return string + end.substring(0, length - string.length);
+}
+
+module.exports = (buffer, color) => {
+ let ret = "";
+ let lines = buffer.toString("hex").match(/.{1,32}/g).map(i => i.match(/.{1,2}/g).join(" "));
+
+ let byte = 0;
+ for (let line of lines) {
+ if (color) {
+ ret += chalk.gray(hexEight(byte)) + " " + fixLength(line, 47).split(" ").map((i, _) => {
+ if ((_ + 1) % 2 === 1) {
+ return chalk.red(i);
+ } else {
+ return chalk.magenta(i);
+ }
+ }).join(" ") + " " + chalk.blue(Buffer.from(line.replaceAll(" ", ""), "hex").toString().replace(/[\x00-\x1F]/gm, chalk.gray("."))) + "\n";
+ } else {
+ ret += hexEight(byte) + " " + fixLength(line, 47) + " " + Buffer.from(line.replaceAll(" ", ""), "hex").toString().replace(/[\x00-\x1F]/gm, ".") + "\n";
+ }
+
+ byte += line.replaceAll(" ", "").length / 2;
+ }
+
+ if (color) {
+ ret += chalk.gray(hexEight(byte));
+ } else {
+ ret += hexEight(byte);
+ }
+
+ return ret;
+} \ No newline at end of file
diff --git a/Components/DisplayFile/index.js b/Components/DisplayFile/index.js
new file mode 100644
index 0000000..c6b3f25
--- /dev/null
+++ b/Components/DisplayFile/index.js
@@ -0,0 +1,43 @@
+let arguments = JSON.parse(process.argv[2]);
+const chalk = require(__dirname + '/../../MistyCore/node_modules/chalk');
+const fs = require("fs");
+const child_process = require("child_process");
+
+if (arguments._finals.length > 0) {
+ for (let file of arguments._finals) {
+ if (fs.existsSync(file)) {
+ try {
+ fs.accessSync(file, fs.constants.R_OK);
+
+ if (arguments['hex']) {
+ fs.writeFileSync("/System/Volumes/VM/HexDump", require('./hex')(fs.readFileSync(file), !arguments['pagination']));
+ file = "/System/Volumes/VM/HexDump";
+ }
+
+ if (fs.lstatSync(file).isDirectory()) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Is a directory: ") + file);
+ } else {
+ if (arguments['pagination']) {
+ console.clear();
+ child_process.execFileSync("/System/Binaries/busybox", [ "less", "-~", "-S", "--", file ], { stdio: "inherit" });
+ console.clear();
+ } else {
+ if (arguments['search']) {
+ console.log(chalk.white(fs.readFileSync(file).toString().replace(arguments['search'], chalk.bold.red(arguments['search']))));
+ } else {
+ console.log(chalk.white(fs.readFileSync(file).toString()));
+ }
+ }
+ }
+
+ if (fs.existsSync("/System/Volumes/VM/HexDump")) fs.unlinkSync("/System/Volumes/VM/HexDump");
+ } catch (e) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Permission denied: ") + file);
+ }
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such file or directory: ") + file);
+ }
+ }
+} else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Missing operand"));
+} \ No newline at end of file
diff --git a/Components/DisplayFile/metadata.yml b/Components/DisplayFile/metadata.yml
new file mode 100644
index 0000000..e05d233
--- /dev/null
+++ b/Components/DisplayFile/metadata.yml
@@ -0,0 +1,46 @@
+description: Displays one or multiple file(s) in the terminal
+internal: false
+
+aliases:
+ - cat
+ - type
+ - more
+ - less
+
+manual:
+ summary: |
+ This command displays one or multiple file(s) in the terminal.
+
+ parameters:
+ - name: Pagination
+ description: Enable pagination (scrolling)
+ required: false
+
+ - name: Hex
+ description: Display an hexadecimal dump of the file instead of the contents of the file itself
+ required: false
+
+ - name: Search
+ value: Query
+ description: Search for text in the file(s); does not work with -Pagination
+ required: false
+
+ final:
+ name: File
+ description: The file(s) to display
+ required: true
+ multiple: true
+ command: false
+ path: true
+ daemon: false
+
+ examples:
+ - command: DisplayFile /User/Document.txt
+ description: Display the "Document.txt" file
+
+ - command: DisplayFile -Pagination /User/Essay.txt
+ description: Display the "Essay.txt" file with pagination
+
+ compatibility:
+ mistyos: '>=1.0.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/Documentation/index.js b/Components/Documentation/index.js
new file mode 100644
index 0000000..1b0e132
--- /dev/null
+++ b/Components/Documentation/index.js
@@ -0,0 +1,129 @@
+const fs = require('fs');
+const path = require('path');
+const chalk = require(__dirname + '/../../MistyCore/node_modules/chalk');
+const child_process = require("child_process");
+const semver = require(__dirname + '/../../MistyCore/node_modules/semver');
+
+function prettyVersion(version) {
+ return version.replace(/^\*$/gm, "<all versions>").replace(/^>=(| *)(\d+\.\d+\.\d+)$/gm, "$2 and later").replace(/^=(| *)(\d+\.\d+\.\d+)$/gm, "$2").replace(/^(\d+\.\d+\.\d+)(| +)-(| +)(\d+\.\d+\.\d+)$/gm, "$1 to $4");
+}
+
+module.exports = (arguments) => {
+ if (arguments['_finals'].length === 0) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Missing operand"));
+ return;
+ }
+
+ let input = arguments['_finals'][0];
+ let command = null;
+
+ let commands = global.commands;
+ let commandsMetadata = global.commandsMetadata;
+
+ for (let cmd of commands) {
+ if (cmd.toLowerCase() === input.toLowerCase()) {
+ command = cmd;
+ break;
+ }
+
+ let metadata = commandsMetadata[commands.indexOf(cmd)];
+ if (metadata['aliases'].map(i => i.toLowerCase()).includes(input.toLowerCase())) {
+ command = cmd;
+ break;
+ }
+ }
+
+ let metadata = commandsMetadata[commands.indexOf(command)];
+ if (!command) {
+ console.log(chalk.bgRed.white("<!>") + " " + chalk.red("Command not found: ") + input);
+ } else {
+ let out = chalk.reset("") + "\n";
+ let pack = "*";
+
+ out += chalk.red(" ╔" + "═".repeat(command.length + 2) + "╗\n ║ " + command + " ║\n " + "╚" + "═".repeat(command.length + 2) + "╝") + "\n\n";
+
+ out += chalk.magenta(" Name\n ----") + "\n";
+ out += chalk.whiteBright(" " + command + " - " + metadata.description) + "\n\n";
+
+ out += chalk.magenta(" Synopsis\n --------") + "\n";
+ out += chalk.whiteBright(" " + chalk.green(command));
+
+ for (let param of metadata['manual']['parameters']) {
+ out += " ";
+
+ if (!param.required) out += "[";
+ if (param.value) {
+ out += chalk.cyan("-" + param.name) + chalk.magenta(chalk.bgGray("=") + param.value);
+ } else {
+ out += chalk.magenta("-" + param.name);
+ }
+ if (!param.required) out += "]";
+ }
+
+ if (metadata['manual']['final']) {
+ out += " ";
+
+ if (!metadata['manual']['final'].required) out += "[";
+
+ if (metadata['manual']['final']['command']) {
+ out += chalk.yellow(metadata['manual']['final'].name);
+ } else {
+ out += metadata['manual']['final'].name;
+ }
+
+ if (metadata['manual']['final'].multiple) out += " ...";
+ if (!metadata['manual']['final'].required) out += "]";
+ }
+
+ out += "\n";
+
+ for (let alias of metadata.aliases) {
+ out += chalk.whiteBright(" " + chalk.green(alias) + chalk.gray(" (-> " + command + ")") + "\n");
+ }
+
+ if (metadata['manual']['summary'] || metadata['manual']['parameters'].length > 0) {
+ out += chalk.magenta("\n Description\n -----------") + "\n";
+ if (metadata['manual']['summary']) {
+ out += " " + metadata['manual']['summary'].trim();
+ for (let param of metadata['manual']['parameters']) {
+ out += "\n\n ";
+
+ if (param.value) {
+ out += chalk.cyan("-" + param.name) + chalk.magenta(chalk.bgGray("=") + param.value);
+ } else {
+ out += chalk.magenta("-" + param.name);
+ }
+
+ out += "\n " + param.description ?? "<no description>";
+ }
+
+ if (metadata['manual']['final']) {
+ out += "\n\n ";
+
+ if (metadata['manual']['final']['command']) {
+ out += chalk.yellow(metadata['manual']['final'].name);
+ } else {
+ out += metadata['manual']['final'].name;
+ }
+
+ if (metadata['manual']['final'].multiple) out += " ...";
+ out += "\n " + metadata['manual']['final'].description ?? "<no description>";
+ }
+ }
+ }
+
+ if (metadata['manual']['examples']) {
+ out += chalk.magenta("\n\n Examples\n --------") + "\n";
+
+ for (let example of metadata['manual']['examples']) {
+ out += " " + example.description + "\n " + chalk.blue("> ") + example.command + "\n";
+ }
+ }
+
+ out += chalk.magenta("\n\n Compatibility\n -------------") + "\n";
+ out += " MistyOS: " + prettyVersion(metadata['manual']['compatibility']['mistyos']) + "\n";
+ out += " Kernel: " + prettyVersion(metadata['manual']['compatibility']['kernel']);
+
+ console.log("\n" + out.trim() + "\n");
+ }
+} \ No newline at end of file
diff --git a/Components/Documentation/metadata.yml b/Components/Documentation/metadata.yml
new file mode 100644
index 0000000..799f509
--- /dev/null
+++ b/Components/Documentation/metadata.yml
@@ -0,0 +1,30 @@
+description: Shows documentation about a command
+internal: true
+
+aliases:
+ - man
+ - help
+ - docs
+
+manual:
+ summary: |
+ This command shows documentation about another command, including how to use it.
+
+ parameters: []
+
+ final:
+ name: Command
+ description: The command to get help for
+ required: true
+ multiple: false
+ command: true
+ path: false
+ daemon: false
+
+ examples:
+ - command: Documentation ChangeDir
+ description: Shows documentation for the ChangeDir command
+
+ compatibility:
+ mistyos: '>=1.0.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/InternalShell/index.js b/Components/InternalShell/index.js
new file mode 100644
index 0000000..682da6e
--- /dev/null
+++ b/Components/InternalShell/index.js
@@ -0,0 +1,14 @@
+const child_process = require("child_process");
+global.log = require('../../MistyCore/log');
+
+module.exports = (arguments) => {
+ let args = [];
+
+ if (arguments['_finals'].length > 0) {
+ args = [ "-c", arguments['_finals'].join(" ") ];
+ }
+
+ log("Shell-InternalShell", "Starting internal shell");
+ child_process.execFileSync("/System/Binaries/sh", args, { stdio: "inherit" });
+ log("Shell-InternalShell", "Stopped internal shell");
+} \ No newline at end of file
diff --git a/Components/InternalShell/metadata.yml b/Components/InternalShell/metadata.yml
new file mode 100644
index 0000000..d196032
--- /dev/null
+++ b/Components/InternalShell/metadata.yml
@@ -0,0 +1,17 @@
+description: Internal shell
+internal: true
+
+aliases: []
+
+manual:
+ summary: ""
+
+ parameters: []
+
+ final: null
+
+ examples: []
+
+ compatibility:
+ mistyos: '>=1.0.0'
+ kernel: '>=5.10.0'
diff --git a/Components/ListDirectory/index.js b/Components/ListDirectory/index.js
new file mode 100644
index 0000000..a7fa45b
--- /dev/null
+++ b/Components/ListDirectory/index.js
@@ -0,0 +1,85 @@
+let arguments = JSON.parse(process.argv[2]);
+const chalk = require(__dirname + '/../../MistyCore/node_modules/chalk');
+const fs = require("fs");
+const path = require('path');
+
+let list = [];
+
+function processList(list, dir, arguments) {
+ if (!Object.keys(arguments).includes("all") && dir === "/") {
+ list = list.filter(i => i !== "dev" && i !== "etc" && i !== "bin" && i !== "lib" && i !== "lib64" && i !== "lost+found" && i !== "proc" && i !== "run" && i !== "sys" && i !== "MistyOSPrivate");
+ } else if (!Object.keys(arguments).includes("All") &&dir === "/User") {
+ list = list.filter(i => i !== "Library");
+ }
+
+ if (Object.keys(arguments).includes("all")) list.unshift(".", "..");
+ if (Object.keys(arguments).includes("search")) list = list.filter(i => i.includes(arguments["search"]));
+
+ if (!Object.keys(arguments).includes("all")) list = list.filter(i => !i.startsWith("."));
+ return list.map((i) => {
+ if (fs.existsSync(dir + "/" + i)) {
+ try {
+ fs.accessSync(dir + "/" + i, fs.constants.R_OK);
+
+ if (fs.lstatSync(dir + "/" + i).isDirectory()) {
+ return i + chalk.gray("/");
+ } else if (fs.lstatSync(dir + "/" + i).isSymbolicLink()) {
+ return i + chalk.gray(">");
+ } else {
+ return i;
+ }
+ } catch (e) {
+ return i + chalk.gray("?");
+ }
+ } else {
+ return i + chalk.gray("x");
+ }
+ });
+}
+
+if (arguments._finals.length > 0) {
+ if (arguments._finals.length === 1) {
+ if (fs.existsSync(arguments._finals[0])) {
+ try {
+ fs.accessSync(arguments._finals[0], fs.constants.R_OK);
+
+ if (!fs.lstatSync(arguments._finals[0]).isDirectory()) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Not a directory: ") + arguments._finals[0]);
+ } else {
+ list = require('fs').readdirSync(arguments._finals[0]);
+ list = processList(list, path.resolve(arguments['_finals'][0]), arguments);
+ console.log(list.join(chalk.gray(", ")));
+ }
+ } catch (e) {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("Permission denied: ") + arguments._finals[0]);
+ }
+ } else {
+ console.log(chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such file or directory: ") + arguments._finals[0]);
+ }
+ } else {
+ for (let final of arguments._finals) {
+ console.log(final + ":");
+ if (fs.existsSync(final)) {
+ try {
+ fs.accessSync(final, fs.constants.R_OK);
+
+ if (!fs.lstatSync(final).isDirectory()) {
+ console.log(" " + chalk.bgYellow.white("<!>") + " " + chalk.yellow("Not a directory: ") + final);
+ } else {
+ list = require('fs').readdirSync(final);
+ list = processList(list, path.resolve(final), arguments);
+ console.log(" " + list.join(chalk.gray(", ")));
+ }
+ } catch (e) {
+ console.log(" " + chalk.bgYellow.white("<!>") + " " + chalk.yellow("Permission denied: ") + final);
+ }
+ } else {
+ console.log(" " + chalk.bgYellow.white("<!>") + " " + chalk.yellow("No such file or directory: ") + final);
+ }
+ }
+ }
+} else {
+ list = require('fs').readdirSync(".");
+ list = processList(list, path.resolve("."), arguments);
+ console.log(list.join(chalk.gray(", ")));
+} \ No newline at end of file
diff --git a/Components/ListDirectory/metadata.yml b/Components/ListDirectory/metadata.yml
new file mode 100644
index 0000000..431c999
--- /dev/null
+++ b/Components/ListDirectory/metadata.yml
@@ -0,0 +1,40 @@
+description: Lists files in the current or a select directory
+internal: false
+
+aliases:
+ - ls
+ - dir
+
+manual:
+ summary: |
+ This command lists all files that exist in the specific directory, or the current working directory if not specified.
+
+ parameters:
+ - name: All
+ description: Show hidden files (starting with . or system files)
+ required: false
+
+ - name: Search
+ value: Query
+ description: Search for a specific file containing the query
+ required: false
+
+ final:
+ name: Dir
+ description: The directory or directories to list files of
+ required: false
+ multiple: true
+ command: false
+ path: true
+ daemon: false
+
+ examples:
+ - command: ListDirectory -All
+ description: List all the files in the current directory, including hidden files
+
+ - command: ListDirectory /
+ description: List all the files in the root directory
+
+ compatibility:
+ mistyos: '>=1.0.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/Restart/index.js b/Components/Restart/index.js
new file mode 100644
index 0000000..3846afe
--- /dev/null
+++ b/Components/Restart/index.js
@@ -0,0 +1,11 @@
+let net = require('net');
+let systemRoot = "/System/Library";
+const socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", () => {
+ socket.write(JSON.stringify({
+ action: "SERVICE",
+ payload: {
+ option: "restart",
+ service: "MistyOS.yml"
+ }
+ }));
+}); \ No newline at end of file
diff --git a/Components/Restart/metadata.yml b/Components/Restart/metadata.yml
new file mode 100644
index 0000000..165b987
--- /dev/null
+++ b/Components/Restart/metadata.yml
@@ -0,0 +1,26 @@
+description: Restarts the system properly
+internal: false
+
+aliases:
+ - reboot
+ - boot
+ - reset
+
+manual:
+ summary: |
+ This command restarts the system by passing a reboot command through MistyCore, causing the system to restart properly.
+
+ parameters: []
+
+ final: null
+
+ examples:
+ - command: Restart
+ description: Restarts the system normally
+
+ - command: CoreDaemon -Restart MistyOS
+ description: Restarts the system by using MistyCore's frontend directly
+
+ compatibility:
+ mistyos: '>=1.2.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/ShowMisty/index.js b/Components/ShowMisty/index.js
new file mode 100644
index 0000000..2078a46
--- /dev/null
+++ b/Components/ShowMisty/index.js
@@ -0,0 +1,30 @@
+const chalk = require(__dirname + '/../../MistyCore/node_modules/chalk');
+const fs = require("fs");
+
+module.exports = () => {
+ process.stdout.write("\n ");
+ process.stdout.write(chalk.blue("██"));
+ process.stdout.write(chalk.yellow("██"));
+ process.stdout.write(" \n ");
+ process.stdout.write(chalk.yellow("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(" \n ");
+ process.stdout.write(chalk.yellow("██"));
+ process.stdout.write(" ");
+ process.stdout.write(chalk.blue("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(" \n ");
+ process.stdout.write(chalk.blue("██"));
+ process.stdout.write(" ");
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(" \n ");
+ process.stdout.write(chalk.yellow("██"));
+ process.stdout.write(" ");
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(" ");
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(" \n\n");
+} \ No newline at end of file
diff --git a/Components/ShowMisty/metadata.yml b/Components/ShowMisty/metadata.yml
new file mode 100644
index 0000000..e4d4266
--- /dev/null
+++ b/Components/ShowMisty/metadata.yml
@@ -0,0 +1,22 @@
+description: Shows a Misty ASCII art
+internal: true
+
+aliases:
+ - misty
+ - brightdawn
+ - mistybrightdawn
+ - mlp
+
+manual:
+ summary: |
+ This command shows a Misty ASCII art on the console. Yes, that's literally it.
+
+ parameters: []
+
+ final: null
+
+ examples: []
+
+ compatibility:
+ mistyos: '>=1.0.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/Components/Shutdown/index.js b/Components/Shutdown/index.js
new file mode 100644
index 0000000..cd26bd1
--- /dev/null
+++ b/Components/Shutdown/index.js
@@ -0,0 +1,11 @@
+let net = require('net');
+let systemRoot = "/System/Library";
+const socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", () => {
+ socket.write(JSON.stringify({
+ action: "SERVICE",
+ payload: {
+ option: "stop",
+ service: "MistyOS.yml"
+ }
+ }));
+}); \ No newline at end of file
diff --git a/Components/Shutdown/metadata.yml b/Components/Shutdown/metadata.yml
new file mode 100644
index 0000000..b335adb
--- /dev/null
+++ b/Components/Shutdown/metadata.yml
@@ -0,0 +1,27 @@
+description: Shuts down the system properly
+internal: false
+
+aliases:
+ - poweroff
+ - off
+ - turnoff
+ - halt
+
+manual:
+ summary: |
+ This command shuts down the system by passing a shutdown command through MistyCore, causing the system to power off properly.
+
+ parameters: []
+
+ final: null
+
+ examples:
+ - command: Shutdown
+ description: Shuts down the system normally
+
+ - command: CoreDaemon -Stop MistyOS
+ description: Shuts down the system by using MistyCore's frontend directly
+
+ compatibility:
+ mistyos: '>=1.2.0'
+ kernel: '>=5.10.0' \ No newline at end of file
diff --git a/LaunchDaemons/MistyOS.yml b/LaunchDaemons/MistyOS.yml
new file mode 100644
index 0000000..45605c5
--- /dev/null
+++ b/LaunchDaemons/MistyOS.yml
@@ -0,0 +1,9 @@
+metadata:
+ description: MistyOS Operating System
+ target: 0
+
+commands:
+ start: "true"
+ stop: "/System/Library/Frameworks/NodeJS/MistyRuntime /System/Library/MistyCore/power/shutdown.js"
+ restart: "/System/Library/Frameworks/NodeJS/MistyRuntime /System/Library/MistyCore/power/reboot.js"
+
diff --git a/LaunchDaemons/Node.yml b/LaunchDaemons/Node.yml
new file mode 100644
index 0000000..1ffc084
--- /dev/null
+++ b/LaunchDaemons/Node.yml
@@ -0,0 +1,9 @@
+metadata:
+ description: Test launch daemon
+ target: false
+
+commands:
+ start: "/System/Library/Frameworks/NodeJS/MistyRuntime"
+ stop: "/System/Library/Frameworks/NodeJS/MistyRuntime"
+ restart: "/System/Library/Frameworks/NodeJS/MistyRuntime"
+
diff --git a/LaunchDaemons/Test.yml b/LaunchDaemons/Test.yml
new file mode 100644
index 0000000..67b47f7
--- /dev/null
+++ b/LaunchDaemons/Test.yml
@@ -0,0 +1,7 @@
+metadata:
+ description: Test launch daemon
+ target: false
+
+commands:
+ start: "/System/Library/Frameworks/NodeJS/MistyRuntime"
+
diff --git a/MistyCore/banner.js b/MistyCore/banner.js
new file mode 100644
index 0000000..b75c182
--- /dev/null
+++ b/MistyCore/banner.js
@@ -0,0 +1,37 @@
+const chalk = require("chalk");
+const fs = require("fs");
+
+module.exports = () => {
+ console.log("");
+ process.stdout.write(" ");
+ process.stdout.write(chalk.blue("██"));
+ process.stdout.write(chalk.yellow("██"));
+ process.stdout.write(" \n ");
+ process.stdout.write(chalk.yellow("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(" " + chalk.cyan("MistyOS"));
+ process.stdout.write(" \n ");
+ process.stdout.write(chalk.yellow("██"));
+ process.stdout.write(" ");
+ process.stdout.write(chalk.blue("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(chalk.yellow(" Version " + fs.readFileSync(systemRoot + "/MistyOSVersion").toString().trim()));
+ process.stdout.write(" \n ");
+ process.stdout.write(chalk.blue("██"));
+ process.stdout.write(" ");
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(chalk.yellow(" Copyright (c) Equestria.dev Developers"));
+ process.stdout.write(" \n ");
+ process.stdout.write(chalk.yellow("██"));
+ process.stdout.write(" ");
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(" ");
+ process.stdout.write(chalk.cyan("██"));
+ process.stdout.write(" \n\n");
+ console.log(chalk.red("████") + chalk.green("████") + chalk.yellow("████") + chalk.blue("████") + chalk.magenta("████") + chalk.cyan("████") + chalk.white("████") + chalk.gray("████") + chalk.black("████"));
+ console.log(chalk.redBright("████") + chalk.greenBright("████") + chalk.yellowBright("████") + chalk.blueBright("████") + chalk.magentaBright("████") + chalk.cyanBright("████") + chalk.whiteBright("████") + chalk.gray("████") + chalk.blackBright("████"));
+ console.log("");
+} \ No newline at end of file
diff --git a/MistyCore/error.js b/MistyCore/error.js
new file mode 100644
index 0000000..fd5e2b2
--- /dev/null
+++ b/MistyCore/error.js
@@ -0,0 +1,155 @@
+const path = require('path');
+const fs = require('fs');
+const crypto = require('crypto');
+const chalk = require("chalk");
+
+let fixLength = (string, length) => {
+ let end = " ".repeat(length);
+ if (string.length > length) return string.substring(0, length);
+
+ return string + end.substring(0, length - string.length);
+}
+
+let hexEight = (dec) => {
+ let hex = Math.round(dec).toString(16);
+ let zero = "00000000";
+ return zero.substring(0, 8 - hex.length) + hex;
+}
+
+let errorName = (name) => {
+ switch (name) {
+ case "InternalError":
+ case "Error":
+ return "TRAP_CAUSE_UNKNOWN";
+
+ case "RangeError":
+ return "OUT_OF_RANGE_EXCEPTION";
+
+ case "ReferenceError":
+ return "MEMORY_MANAGEMENT";
+
+ case "SyntaxError":
+ return "INSTRUCTION_COHERENCY_EXCEPTION";
+
+ case "TypeError":
+ return "NO_USER_MODE_CONTEXT";
+
+ case "URIError":
+ return "INTERRUPT_UNWIND_ATTEMPTED";
+
+ default:
+ return null;
+ }
+}
+
+module.exports = (error, currentStage, version) => {
+ let lines = error.stack.split("\n").map(i => i.trim());
+ let dump = lines.map(i => i.substring(3)); dump.shift();
+ let name = lines[0].split(":")[0];
+ let baseCodes = [...Buffer.from(name).toString("hex").match(/.{1,8}/g).map(i => parseInt(i, 16)).map(i => hexEight(i).toUpperCase()), "00000000", "00000000", "00000000", "00000000"];
+
+ let addressesRaw = dump.filter(i => i.includes("(")).map(i => i.split("(")[1].split(")")[0].trim()).map((i) => {
+ if (i.startsWith("node:internal/")) {
+ if (i.startsWith("node:internal/modules/")) {
+ return "__" + i.substring(21);
+ } else {
+ return "_" + i.substring(13);
+ }
+ } else {
+ return i;
+ }
+ });
+ let addressesFull = [...new Set(dump.filter(i => i.includes("(")).map(i => i.split("(")[1].split(")")[0].trim()).map(i => i.split(":")[0]))];
+
+ let bases = addressesFull.map((i) => {
+ if (fs.existsSync(i)) {
+ try {
+ fs.accessSync(i, fs.constants.R_OK);
+ return crypto.createHash("sha256").update(fs.readFileSync(i)).digest("hex").substring(0, 8);
+ } catch (e) {
+ return "ffffffff";
+ }
+ } else {
+ return "ffffffff";
+ }
+ });
+ let dateStamps = addressesFull.map((i) => {
+ if (fs.existsSync(i)) {
+ try {
+ fs.accessSync(i, fs.constants.R_OK);
+ return hexEight(Math.round((new Date().getTime() / 1000) - (fs.lstatSync(i).mtimeMs / 1000)));
+ } catch (e) {
+ return "ffffffff";
+ }
+ } else {
+ return "ffffffff";
+ }
+ });
+
+ let fileNamesFull = addressesFull.map(i => path.basename(i.split(":")[0]));
+
+ let fileNames = addressesRaw.map(i => path.basename(i.split(":")[0]));
+ let dumpsRaws = dump.filter(i => i.includes("(")).map(i => i.split("(")[0].trim());
+
+ let addresses = addressesRaw.map((i) => {
+ let hex = Buffer.from(i).toString("hex");
+
+ return hex.substring(0, 4) + hex.substring(hex.length - 4, hex.length);
+ });
+
+ let dumps = dumpsRaws.map((i) => {
+ let arr = ["00000000", "00000000", "00000000", "00000000", "00000000", "00000000"];
+ let hex = Buffer.from(i).toString("hex");
+
+ arr.unshift(hex.substring(0, 8), hex.substring(8, 16), hex.substring(16, 24), hex.substring(24, 32), hex.substring(32, 40), hex.substring(40, 48));
+ arr = arr.filter(i => i.trim() !== "").map(i => hexEight(parseInt(i, 16)));
+
+ return arr;
+ });
+
+ console.log(chalk.bgYellow.white("*** STOP: 0x" + hexEight(process.uptime()).toUpperCase() + " (0x" + baseCodes[0] + ",0x" + baseCodes[1] + ",0x" + baseCodes[2] + ",0x" + baseCodes[3] + ")"));
+
+ let pName = errorName(name);
+ if (pName) {
+ console.log(chalk.bgYellow.white(pName));
+ }
+
+ console.log(chalk.bgYellow.white(""));
+ console.log(chalk.bgYellow.white("CPUID:" + (require('os').cpus()[0] ?? { model: "???" }).model + " SYSVER 0x" + hexEight(parseInt(Buffer.from(version.replace(/(\.| \(.*\))/gm, "")).toString("hex"), 16))));
+
+ console.log(chalk.bgYellow.white(""));
+ console.log(chalk.bgYellow.white("Sys Base DateStmp - Name Sys Base DateStmp - Name"));
+
+ for (let indexes of [
+ [0, 1],
+ [2, 3],
+ [4, 5],
+ [6, 7],
+ [8, 9],
+ [10, 11]
+ ]) {
+ if (bases[indexes[0]] && bases[indexes[1]]) {
+ console.log(chalk.bgYellow.white(bases[indexes[0]], dateStamps[indexes[0]], "-", fixLength(fileNamesFull[indexes[0]], 18), bases[indexes[1]], dateStamps[indexes[1]], "-", fixLength(fileNamesFull[indexes[1]], 18)));
+ } else if (bases[indexes[0]]) {
+ console.log(chalk.bgYellow.white(bases[indexes[0]], dateStamps[indexes[0]], "-", fixLength(fileNamesFull[indexes[0]], 18)));
+ } else {
+ console.log(chalk.bgYellow.white(""));
+ }
+ }
+
+ console.log(chalk.bgYellow.white(""));
+ console.log(chalk.bgYellow.white("Address dword dump - Name"));
+
+ for (let index in addresses) {
+ let address = addresses[index];
+ let dump = dumps[index];
+ let fileName = fileNames[index];
+
+ console.log(chalk.bgYellow.white(address, dump[0], dump[1], dump[2], dump[3], dump[4], dump[5], "-", fileName));
+ }
+
+ console.log(chalk.bgYellow.white(""));
+ console.log(chalk.bgYellow.white("Restart and press Shift on startup to access recovery options"));
+ console.log(chalk.bgYellow.white("or read the system journal information. If this message reappears,"))
+ console.log(chalk.bgYellow.white("contact your system administrator or technical support group."))
+} \ No newline at end of file
diff --git a/MistyCore/index.js b/MistyCore/index.js
new file mode 100644
index 0000000..6f09b4a
--- /dev/null
+++ b/MistyCore/index.js
@@ -0,0 +1,150 @@
+process.stdout.write(".");
+const fs = require('fs');
+const path = require('path');
+const chalk = require("chalk");
+
+global._error = require('./error');
+
+process.stdout.write(".");
+global.systemRoot = path.resolve(__dirname + "/..");
+global.systemLog = path.resolve(systemRoot + "/../Volumes/VM/CurrentLog.log");
+global.hostname = "(none)";
+global.currentStage = 0;
+global.uiProcess = null;
+global.osVersion = fs.readFileSync(systemRoot + "/MistyOSVersion").toString().trim();
+
+process.stdout.write(".");
+process.on('uncaughtException', (error) => {
+ try {
+ log("MistyCore", "An internal exception occurred.");
+ log("MistyCore", error.stack);
+ log("MistyCore", "Aborting system operation");
+ } catch (e) {}
+
+ try {
+ fs.copyFileSync(systemLog, systemRoot + "/Logs/LastCrash.log");
+ } catch (e) {}
+
+ try {
+ require('child_process').execFileSync("/System/Binaries/sh", [ "-c", "echo 's' > /System/Volumes/FieldService/sysrq-trigger" ]);
+ } catch (e) {}
+
+ console.clear();
+ for (let i = 0; i < process.stdout.rows - 1; i++) {
+ process.stdout.write(chalk.bgYellow.white(" ".repeat(process.stdout.columns)));
+ }
+
+ process.stdout.cursorTo(0, 0);
+ _error(error, currentStage, osVersion);
+ global.halt();
+})
+
+process.stdout.write(".");
+global.halt = () => {
+ let v = true;
+ while (v) {}
+}
+
+process.stdout.write(".");
+global.log = (service, text) => {
+ let lines = text.split("\n");
+
+ for (let line of lines) {
+ fs.appendFileSync(systemLog, "\n" + new Date().toDateString().substring(4, 10) + " " + new Date().toTimeString().split(" ")[0] + " " + hostname + " " + service + ": " + text);
+ }
+}
+
+process.stdout.write(".");
+if (!fs.existsSync(systemRoot + "/../Volumes")) fs.mkdirSync(systemRoot + "/../Volumes");
+if (!fs.existsSync(systemRoot + "/../Volumes/VM")) fs.mkdirSync(systemRoot + "/../Volumes/VM");
+fs.writeFileSync(systemLog, "");
+
+process.stdout.write(".");
+log("MistyCore", "Setting runtime variables...");
+fs.writeFileSync(systemRoot + "/../Volumes/VM/SystemRoot", systemRoot);
+fs.writeFileSync(systemRoot + "/../Volumes/VM/SystemLog", systemLog);
+fs.writeFileSync(systemRoot + "/../Volumes/VM/Hostname", hostname);
+fs.writeFileSync(systemRoot + "/../Volumes/VM/Version", fs.readFileSync(systemRoot + "/MistyOSVersion").toString().trim());
+fs.mkdirSync(systemRoot + "/../Volumes/VM/LaunchDaemons");
+fs.mkdirSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes");
+log("MistyCore", "Done setting runtime variables");
+
+process.stdout.write(".");
+global.services = require('./service');
+global.socket = require('./socket');
+
+process.stdout.write(".");
+log("MistyCore", "Creating launch daemons wrappers...");
+let servicesList = services.list();
+for (let name in servicesList) {
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + name, "-1");
+}
+log("MistyCore", "Done creating launch daemons wrappers");
+
+log("MistyCore", "Starting MistyCore on MistyOS " + fs.readFileSync(systemRoot + "/MistyOSVersion").toString().trim());
+
+process.stdout.write(".");
+console.clear();
+log("MistyCore", "Showing banner");
+
+require('./banner')();
+
+console.log("");
+console.log("MistyOS is starting up...");
+process.stdout.write(" Initializing MistyCore...\n");
+
+log("MistyCore", "Done showing banner");
+log("MistyCore-Startup", "Running startup items...");
+
+for (let unit of fs.readdirSync(systemRoot + "/StartupItems")) {
+ let startupItemStage = parseInt(unit.substring(0, 1));
+ if (startupItemStage !== currentStage) {
+ services.reachTarget(currentStage);
+ currentStage = startupItemStage;
+ }
+
+ log("MistyCore-Startup", "Starting item: " + systemRoot + "/StartupItems/" + unit);
+
+ let unitName = unit.split("--")[1];
+ let unitNamePretty = unitName.substring(0, unitName.length - 3);
+
+ process.stdout.write(" Running " + unitNamePretty + "...");
+
+ try {
+ log("MistyCore-Startup", "Executing file: " + systemRoot + "/StartupItems/" + unit);
+ require(systemRoot + "/StartupItems/" + unit);
+ log("MistyCore-Startup", "Registered success for item: " + systemRoot + "/StartupItems/" + unit);
+
+ process.stdout.write(chalk.green(" Success") + "\n");
+ } catch (e) {
+ log("MistyCore-Startup", "Registered failure for item: " + systemRoot + "/StartupItems/" + unit);
+ log("MistyCore-Startup", e.stack);
+
+ process.stdout.write(chalk.yellow(" Failure") + "\n");
+ console.log("");
+ console.log(chalk.red.inverse("MistyOS is unable to start up."));
+ console.log("");
+ console.log(chalk.red("A failing startup item is preventing MistyOS from starting up correctly."));
+ console.log(" " + chalk.red("Startup item: " + unitNamePretty));
+ console.log(" " + chalk.red("Error message: " + e.message));
+ console.log("");
+ console.log(chalk.red("Try starting your device in safe mode by holding Shift during start up."));
+ global.halt();
+ }
+}
+
+services.reachTarget(9);
+
+if (!global.uiProcess) {
+ console.log("");
+ console.log(chalk.red.inverse("MistyOS does not have a user interface."));
+ console.log("");
+ console.log(chalk.red("MistyOS has started successfully, but no user interface has been started."));
+ console.log(" " + chalk.red("Wanted startup item: /System/Library/StartupItems/999--Shell.js"));
+ console.log(" " + chalk.red("Try reinstall MistyOS if this is not expected."));
+ console.log("");
+ console.log(chalk.red("Try starting your device in safe mode by holding Shift during start up."));
+ global.halt();
+}
+
+setInterval(() => {}) \ No newline at end of file
diff --git a/MistyCore/log.js b/MistyCore/log.js
new file mode 100644
index 0000000..9d786e4
--- /dev/null
+++ b/MistyCore/log.js
@@ -0,0 +1,14 @@
+let net = require('net');
+let systemRoot = "/System/Library";
+
+module.exports = (service, text) => {
+ let socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", () => {
+ socket.write(JSON.stringify({
+ action: "LOG",
+ payload: {
+ service,
+ text
+ }
+ }));
+ });
+} \ No newline at end of file
diff --git a/MistyCore/node_modules/.bin/semver b/MistyCore/node_modules/.bin/semver
new file mode 120000
index 0000000..5aaadf4
--- /dev/null
+++ b/MistyCore/node_modules/.bin/semver
@@ -0,0 +1 @@
+../semver/bin/semver.js \ No newline at end of file
diff --git a/MistyCore/node_modules/.bin/systeminformation b/MistyCore/node_modules/.bin/systeminformation
new file mode 120000
index 0000000..681d01e
--- /dev/null
+++ b/MistyCore/node_modules/.bin/systeminformation
@@ -0,0 +1 @@
+../systeminformation/lib/cli.js \ No newline at end of file
diff --git a/MistyCore/node_modules/.package-lock.json b/MistyCore/node_modules/.package-lock.json
new file mode 100644
index 0000000..9a1c654
--- /dev/null
+++ b/MistyCore/node_modules/.package-lock.json
@@ -0,0 +1,134 @@
+{
+ "name": "MistyCore",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/systeminformation": {
+ "version": "5.12.11",
+ "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.12.11.tgz",
+ "integrity": "sha512-4N5nT4BFWqRyadTLO8c/t8/gM6wqgg26/WNjjZCS/UU7VuURuBy/pR6Z6+j0nD3ff+zCpX/sdVfyn+EoIg9saQ==",
+ "os": [
+ "darwin",
+ "linux",
+ "win32",
+ "freebsd",
+ "openbsd",
+ "netbsd",
+ "sunos",
+ "android"
+ ],
+ "bin": {
+ "systeminformation": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ },
+ "funding": {
+ "type": "Buy me a coffee",
+ "url": "https://www.buymeacoffee.com/systeminfo"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/yaml": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
+ "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
+ "engines": {
+ "node": ">= 14"
+ }
+ }
+ }
+}
diff --git a/MistyCore/node_modules/ansi-styles/index.d.ts b/MistyCore/node_modules/ansi-styles/index.d.ts
new file mode 100644
index 0000000..44a907e
--- /dev/null
+++ b/MistyCore/node_modules/ansi-styles/index.d.ts
@@ -0,0 +1,345 @@
+declare type CSSColor =
+ | 'aliceblue'
+ | 'antiquewhite'
+ | 'aqua'
+ | 'aquamarine'
+ | 'azure'
+ | 'beige'
+ | 'bisque'
+ | 'black'
+ | 'blanchedalmond'
+ | 'blue'
+ | 'blueviolet'
+ | 'brown'
+ | 'burlywood'
+ | 'cadetblue'
+ | 'chartreuse'
+ | 'chocolate'
+ | 'coral'
+ | 'cornflowerblue'
+ | 'cornsilk'
+ | 'crimson'
+ | 'cyan'
+ | 'darkblue'
+ | 'darkcyan'
+ | 'darkgoldenrod'
+ | 'darkgray'
+ | 'darkgreen'
+ | 'darkgrey'
+ | 'darkkhaki'
+ | 'darkmagenta'
+ | 'darkolivegreen'
+ | 'darkorange'
+ | 'darkorchid'
+ | 'darkred'
+ | 'darksalmon'
+ | 'darkseagreen'
+ | 'darkslateblue'
+ | 'darkslategray'
+ | 'darkslategrey'
+ | 'darkturquoise'
+ | 'darkviolet'
+ | 'deeppink'
+ | 'deepskyblue'
+ | 'dimgray'
+ | 'dimgrey'
+ | 'dodgerblue'
+ | 'firebrick'
+ | 'floralwhite'
+ | 'forestgreen'
+ | 'fuchsia'
+ | 'gainsboro'
+ | 'ghostwhite'
+ | 'gold'
+ | 'goldenrod'
+ | 'gray'
+ | 'green'
+ | 'greenyellow'
+ | 'grey'
+ | 'honeydew'
+ | 'hotpink'
+ | 'indianred'
+ | 'indigo'
+ | 'ivory'
+ | 'khaki'
+ | 'lavender'
+ | 'lavenderblush'
+ | 'lawngreen'
+ | 'lemonchiffon'
+ | 'lightblue'
+ | 'lightcoral'
+ | 'lightcyan'
+ | 'lightgoldenrodyellow'
+ | 'lightgray'
+ | 'lightgreen'
+ | 'lightgrey'
+ | 'lightpink'
+ | 'lightsalmon'
+ | 'lightseagreen'
+ | 'lightskyblue'
+ | 'lightslategray'
+ | 'lightslategrey'
+ | 'lightsteelblue'
+ | 'lightyellow'
+ | 'lime'
+ | 'limegreen'
+ | 'linen'
+ | 'magenta'
+ | 'maroon'
+ | 'mediumaquamarine'
+ | 'mediumblue'
+ | 'mediumorchid'
+ | 'mediumpurple'
+ | 'mediumseagreen'
+ | 'mediumslateblue'
+ | 'mediumspringgreen'
+ | 'mediumturquoise'
+ | 'mediumvioletred'
+ | 'midnightblue'
+ | 'mintcream'
+ | 'mistyrose'
+ | 'moccasin'
+ | 'navajowhite'
+ | 'navy'
+ | 'oldlace'
+ | 'olive'
+ | 'olivedrab'
+ | 'orange'
+ | 'orangered'
+ | 'orchid'
+ | 'palegoldenrod'
+ | 'palegreen'
+ | 'paleturquoise'
+ | 'palevioletred'
+ | 'papayawhip'
+ | 'peachpuff'
+ | 'peru'
+ | 'pink'
+ | 'plum'
+ | 'powderblue'
+ | 'purple'
+ | 'rebeccapurple'
+ | 'red'
+ | 'rosybrown'
+ | 'royalblue'
+ | 'saddlebrown'
+ | 'salmon'
+ | 'sandybrown'
+ | 'seagreen'
+ | 'seashell'
+ | 'sienna'
+ | 'silver'
+ | 'skyblue'
+ | 'slateblue'
+ | 'slategray'
+ | 'slategrey'
+ | 'snow'
+ | 'springgreen'
+ | 'steelblue'
+ | 'tan'
+ | 'teal'
+ | 'thistle'
+ | 'tomato'
+ | 'turquoise'
+ | 'violet'
+ | 'wheat'
+ | 'white'
+ | 'whitesmoke'
+ | 'yellow'
+ | 'yellowgreen';
+
+declare namespace ansiStyles {
+ interface ColorConvert {
+ /**
+ The RGB color space.
+
+ @param red - (`0`-`255`)
+ @param green - (`0`-`255`)
+ @param blue - (`0`-`255`)
+ */
+ rgb(red: number, green: number, blue: number): string;
+
+ /**
+ The RGB HEX color space.
+
+ @param hex - A hexadecimal string containing RGB data.
+ */
+ hex(hex: string): string;
+
+ /**
+ @param keyword - A CSS color name.
+ */
+ keyword(keyword: CSSColor): string;
+
+ /**
+ The HSL color space.
+
+ @param hue - (`0`-`360`)
+ @param saturation - (`0`-`100`)
+ @param lightness - (`0`-`100`)
+ */
+ hsl(hue: number, saturation: number, lightness: number): string;
+
+ /**
+ The HSV color space.
+
+ @param hue - (`0`-`360`)
+ @param saturation - (`0`-`100`)
+ @param value - (`0`-`100`)
+ */
+ hsv(hue: number, saturation: number, value: number): string;
+
+ /**
+ The HSV color space.
+
+ @param hue - (`0`-`360`)
+ @param whiteness - (`0`-`100`)
+ @param blackness - (`0`-`100`)
+ */
+ hwb(hue: number, whiteness: number, blackness: number): string;
+
+ /**
+ Use a [4-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4-bit) to set text color.
+ */
+ ansi(ansi: number): string;
+
+ /**
+ Use an [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
+ */
+ ansi256(ansi: number): string;
+ }
+
+ interface CSPair {
+ /**
+ The ANSI terminal control sequence for starting this style.
+ */
+ readonly open: string;
+
+ /**
+ The ANSI terminal control sequence for ending this style.
+ */
+ readonly close: string;
+ }
+
+ interface ColorBase {
+ readonly ansi: ColorConvert;
+ readonly ansi256: ColorConvert;
+ readonly ansi16m: ColorConvert;
+
+ /**
+ The ANSI terminal control sequence for ending this color.
+ */
+ readonly close: string;
+ }
+
+ interface Modifier {
+ /**
+ Resets the current color chain.
+ */
+ readonly reset: CSPair;
+
+ /**
+ Make text bold.
+ */
+ readonly bold: CSPair;
+
+ /**
+ Emitting only a small amount of light.
+ */
+ readonly dim: CSPair;
+
+ /**
+ Make text italic. (Not widely supported)
+ */
+ readonly italic: CSPair;
+
+ /**
+ Make text underline. (Not widely supported)
+ */
+ readonly underline: CSPair;
+
+ /**
+ Inverse background and foreground colors.
+ */
+ readonly inverse: CSPair;
+
+ /**
+ Prints the text, but makes it invisible.
+ */
+ readonly hidden: CSPair;
+
+ /**
+ Puts a horizontal line through the center of the text. (Not widely supported)
+ */
+ readonly strikethrough: CSPair;
+ }
+
+ interface ForegroundColor {
+ readonly black: CSPair;
+ readonly red: CSPair;
+ readonly green: CSPair;
+ readonly yellow: CSPair;
+ readonly blue: CSPair;
+ readonly cyan: CSPair;
+ readonly magenta: CSPair;
+ readonly white: CSPair;
+
+ /**
+ Alias for `blackBright`.
+ */
+ readonly gray: CSPair;
+
+ /**
+ Alias for `blackBright`.
+ */
+ readonly grey: CSPair;
+
+ readonly blackBright: CSPair;
+ readonly redBright: CSPair;
+ readonly greenBright: CSPair;
+ readonly yellowBright: CSPair;
+ readonly blueBright: CSPair;
+ readonly cyanBright: CSPair;
+ readonly magentaBright: CSPair;
+ readonly whiteBright: CSPair;
+ }
+
+ interface BackgroundColor {
+ readonly bgBlack: CSPair;
+ readonly bgRed: CSPair;
+ readonly bgGreen: CSPair;
+ readonly bgYellow: CSPair;
+ readonly bgBlue: CSPair;
+ readonly bgCyan: CSPair;
+ readonly bgMagenta: CSPair;
+ readonly bgWhite: CSPair;
+
+ /**
+ Alias for `bgBlackBright`.
+ */
+ readonly bgGray: CSPair;
+
+ /**
+ Alias for `bgBlackBright`.
+ */
+ readonly bgGrey: CSPair;
+
+ readonly bgBlackBright: CSPair;
+ readonly bgRedBright: CSPair;
+ readonly bgGreenBright: CSPair;
+ readonly bgYellowBright: CSPair;
+ readonly bgBlueBright: CSPair;
+ readonly bgCyanBright: CSPair;
+ readonly bgMagentaBright: CSPair;
+ readonly bgWhiteBright: CSPair;
+ }
+}
+
+declare const ansiStyles: {
+ readonly modifier: ansiStyles.Modifier;
+ readonly color: ansiStyles.ForegroundColor & ansiStyles.ColorBase;
+ readonly bgColor: ansiStyles.BackgroundColor & ansiStyles.ColorBase;
+ readonly codes: ReadonlyMap<number, number>;
+} & ansiStyles.BackgroundColor & ansiStyles.ForegroundColor & ansiStyles.Modifier;
+
+export = ansiStyles;
diff --git a/MistyCore/node_modules/ansi-styles/index.js b/MistyCore/node_modules/ansi-styles/index.js
new file mode 100644
index 0000000..5d82581
--- /dev/null
+++ b/MistyCore/node_modules/ansi-styles/index.js
@@ -0,0 +1,163 @@
+'use strict';
+
+const wrapAnsi16 = (fn, offset) => (...args) => {
+ const code = fn(...args);
+ return `\u001B[${code + offset}m`;
+};
+
+const wrapAnsi256 = (fn, offset) => (...args) => {
+ const code = fn(...args);
+ return `\u001B[${38 + offset};5;${code}m`;
+};
+
+const wrapAnsi16m = (fn, offset) => (...args) => {
+ const rgb = fn(...args);
+ return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
+};
+
+const ansi2ansi = n => n;
+const rgb2rgb = (r, g, b) => [r, g, b];
+
+const setLazyProperty = (object, property, get) => {
+ Object.defineProperty(object, property, {
+ get: () => {
+ const value = get();
+
+ Object.defineProperty(object, property, {
+ value,
+ enumerable: true,
+ configurable: true
+ });
+
+ return value;
+ },
+ enumerable: true,
+ configurable: true
+ });
+};
+
+/** @type {typeof import('color-convert')} */
+let colorConvert;
+const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => {
+ if (colorConvert === undefined) {
+ colorConvert = require('color-convert');
+ }
+
+ const offset = isBackground ? 10 : 0;
+ const styles = {};
+
+ for (const [sourceSpace, suite] of Object.entries(colorConvert)) {
+ const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace;
+ if (sourceSpace === targetSpace) {
+ styles[name] = wrap(identity, offset);
+ } else if (typeof suite === 'object') {
+ styles[name] = wrap(suite[targetSpace], offset);
+ }
+ }
+
+ return styles;
+};
+
+function assembleStyles() {
+ const codes = new Map();
+ const styles = {
+ modifier: {
+ reset: [0, 0],
+ // 21 isn't widely supported and 22 does the same thing
+ bold: [1, 22],
+ dim: [2, 22],
+ italic: [3, 23],
+ underline: [4, 24],
+ inverse: [7, 27],
+ hidden: [8, 28],
+ strikethrough: [9, 29]
+ },
+ color: {
+ black: [30, 39],
+ red: [31, 39],
+ green: [32, 39],
+ yellow: [33, 39],
+ blue: [34, 39],
+ magenta: [35, 39],
+ cyan: [36, 39],
+ white: [37, 39],
+
+ // Bright color
+ blackBright: [90, 39],
+ redBright: [91, 39],
+ greenBright: [92, 39],
+ yellowBright: [93, 39],
+ blueBright: [94, 39],
+ magentaBright: [95, 39],
+ cyanBright: [96, 39],
+ whiteBright: [97, 39]
+ },
+ bgColor: {
+ bgBlack: [40, 49],
+ bgRed: [41, 49],
+ bgGreen: [42, 49],
+ bgYellow: [43, 49],
+ bgBlue: [44, 49],
+ bgMagenta: [45, 49],
+ bgCyan: [46, 49],
+ bgWhite: [47, 49],
+
+ // Bright color
+ bgBlackBright: [100, 49],
+ bgRedBright: [101, 49],
+ bgGreenBright: [102, 49],
+ bgYellowBright: [103, 49],
+ bgBlueBright: [104, 49],
+ bgMagentaBright: [105, 49],
+ bgCyanBright: [106, 49],
+ bgWhiteBright: [107, 49]
+ }
+ };
+
+ // Alias bright black as gray (and grey)
+ styles.color.gray = styles.color.blackBright;
+ styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
+ styles.color.grey = styles.color.blackBright;
+ styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
+
+ for (const [groupName, group] of Object.entries(styles)) {
+ for (const [styleName, style] of Object.entries(group)) {
+ styles[styleName] = {
+ open: `\u001B[${style[0]}m`,
+ close: `\u001B[${style[1]}m`
+ };
+
+ group[styleName] = styles[styleName];
+
+ codes.set(style[0], style[1]);
+ }
+
+ Object.defineProperty(styles, groupName, {
+ value: group,
+ enumerable: false
+ });
+ }
+
+ Object.defineProperty(styles, 'codes', {
+ value: codes,
+ enumerable: false
+ });
+
+ styles.color.close = '\u001B[39m';
+ styles.bgColor.close = '\u001B[49m';
+
+ setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false));
+ setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false));
+ setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false));
+ setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true));
+ setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true));
+ setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true));
+
+ return styles;
+}
+
+// Make the export immutable
+Object.defineProperty(module, 'exports', {
+ enumerable: true,
+ get: assembleStyles
+});
diff --git a/MistyCore/node_modules/ansi-styles/license b/MistyCore/node_modules/ansi-styles/license
new file mode 100644
index 0000000..e7af2f7
--- /dev/null
+++ b/MistyCore/node_modules/ansi-styles/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MistyCore/node_modules/ansi-styles/package.json b/MistyCore/node_modules/ansi-styles/package.json
new file mode 100644
index 0000000..7539328
--- /dev/null
+++ b/MistyCore/node_modules/ansi-styles/package.json
@@ -0,0 +1,56 @@
+{
+ "name": "ansi-styles",
+ "version": "4.3.0",
+ "description": "ANSI escape codes for styling strings in the terminal",
+ "license": "MIT",
+ "repository": "chalk/ansi-styles",
+ "funding": "https://github.com/chalk/ansi-styles?sponsor=1",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "scripts": {
+ "test": "xo && ava && tsd",
+ "screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"
+ },
+ "files": [
+ "index.js",
+ "index.d.ts"
+ ],
+ "keywords": [
+ "ansi",
+ "styles",
+ "color",
+ "colour",
+ "colors",
+ "terminal",
+ "console",
+ "cli",
+ "string",
+ "tty",
+ "escape",
+ "formatting",
+ "rgb",
+ "256",
+ "shell",
+ "xterm",
+ "log",
+ "logging",
+ "command-line",
+ "text"
+ ],
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "devDependencies": {
+ "@types/color-convert": "^1.9.0",
+ "ava": "^2.3.0",
+ "svg-term-cli": "^2.1.1",
+ "tsd": "^0.11.0",
+ "xo": "^0.25.3"
+ }
+}
diff --git a/MistyCore/node_modules/ansi-styles/readme.md b/MistyCore/node_modules/ansi-styles/readme.md
new file mode 100644
index 0000000..24883de
--- /dev/null
+++ b/MistyCore/node_modules/ansi-styles/readme.md
@@ -0,0 +1,152 @@
+# ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles)
+
+> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
+
+You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
+
+<img src="screenshot.svg" width="900">
+
+## Install
+
+```
+$ npm install ansi-styles
+```
+
+## Usage
+
+```js
+const style = require('ansi-styles');
+
+console.log(`${style.green.open}Hello world!${style.green.close}`);
+
+
+// Color conversion between 16/256/truecolor
+// NOTE: If conversion goes to 16 colors or 256 colors, the original color
+// may be degraded to fit that color palette. This means terminals
+// that do not support 16 million colors will best-match the
+// original color.
+console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close);
+console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close);
+console.log(style.color.ansi16m.hex('#abcdef') + 'Hello world!' + style.color.close);
+```
+
+## API
+
+Each style has an `open` and `close` property.
+
+## Styles
+
+### Modifiers
+
+- `reset`
+- `bold`
+- `dim`
+- `italic` *(Not widely supported)*
+- `underline`
+- `inverse`
+- `hidden`
+- `strikethrough` *(Not widely supported)*
+
+### Colors
+
+- `black`
+- `red`
+- `green`
+- `yellow`
+- `blue`
+- `magenta`
+- `cyan`
+- `white`
+- `blackBright` (alias: `gray`, `grey`)
+- `redBright`
+- `greenBright`
+- `yellowBright`
+- `blueBright`
+- `magentaBright`
+- `cyanBright`
+- `whiteBright`
+
+### Background colors
+
+- `bgBlack`
+- `bgRed`
+- `bgGreen`
+- `bgYellow`
+- `bgBlue`
+- `bgMagenta`
+- `bgCyan`
+- `bgWhite`
+- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
+- `bgRedBright`
+- `bgGreenBright`
+- `bgYellowBright`
+- `bgBlueBright`
+- `bgMagentaBright`
+- `bgCyanBright`
+- `bgWhiteBright`
+
+## Advanced usage
+
+By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
+
+- `style.modifier`
+- `style.color`
+- `style.bgColor`
+
+###### Example
+
+```js
+console.log(style.color.green.open);
+```
+
+Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `style.codes`, which returns a `Map` with the open codes as keys and close codes as values.
+
+###### Example
+
+```js
+console.log(style.codes.get(36));
+//=> 39
+```
+
+## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728)
+
+`ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors.
+
+The following color spaces from `color-convert` are supported:
+
+- `rgb`
+- `hex`
+- `keyword`
+- `hsl`
+- `hsv`
+- `hwb`
+- `ansi`
+- `ansi256`
+
+To use these, call the associated conversion function with the intended output, for example:
+
+```js
+style.color.ansi.rgb(100, 200, 15); // RGB to 16 color ansi foreground code
+style.bgColor.ansi.rgb(100, 200, 15); // RGB to 16 color ansi background code
+
+style.color.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
+style.bgColor.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
+
+style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground code
+style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code
+```
+
+## Related
+
+- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal
+
+## Maintainers
+
+- [Sindre Sorhus](https://github.com/sindresorhus)
+- [Josh Junon](https://github.com/qix-)
+
+## For enterprise
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of `ansi-styles` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-ansi-styles?utm_source=npm-ansi-styles&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
diff --git a/MistyCore/node_modules/chalk/index.d.ts b/MistyCore/node_modules/chalk/index.d.ts
new file mode 100644
index 0000000..9cd88f3
--- /dev/null
+++ b/MistyCore/node_modules/chalk/index.d.ts
@@ -0,0 +1,415 @@
+/**
+Basic foreground colors.
+
+[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
+*/
+declare type ForegroundColor =
+ | 'black'
+ | 'red'
+ | 'green'
+ | 'yellow'
+ | 'blue'
+ | 'magenta'
+ | 'cyan'
+ | 'white'
+ | 'gray'
+ | 'grey'
+ | 'blackBright'
+ | 'redBright'
+ | 'greenBright'
+ | 'yellowBright'
+ | 'blueBright'
+ | 'magentaBright'
+ | 'cyanBright'
+ | 'whiteBright';
+
+/**
+Basic background colors.
+
+[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
+*/
+declare type BackgroundColor =
+ | 'bgBlack'
+ | 'bgRed'
+ | 'bgGreen'
+ | 'bgYellow'
+ | 'bgBlue'
+ | 'bgMagenta'
+ | 'bgCyan'
+ | 'bgWhite'
+ | 'bgGray'
+ | 'bgGrey'
+ | 'bgBlackBright'
+ | 'bgRedBright'
+ | 'bgGreenBright'
+ | 'bgYellowBright'
+ | 'bgBlueBright'
+ | 'bgMagentaBright'
+ | 'bgCyanBright'
+ | 'bgWhiteBright';
+
+/**
+Basic colors.
+
+[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
+*/
+declare type Color = ForegroundColor | BackgroundColor;
+
+declare type Modifiers =
+ | 'reset'
+ | 'bold'
+ | 'dim'
+ | 'italic'
+ | 'underline'
+ | 'inverse'
+ | 'hidden'
+ | 'strikethrough'
+ | 'visible';
+
+declare namespace chalk {
+ /**
+ Levels:
+ - `0` - All colors disabled.
+ - `1` - Basic 16 colors support.
+ - `2` - ANSI 256 colors support.
+ - `3` - Truecolor 16 million colors support.
+ */
+ type Level = 0 | 1 | 2 | 3;
+
+ interface Options {
+ /**
+ Specify the color support for Chalk.
+
+ By default, color support is automatically detected based on the environment.
+
+ Levels:
+ - `0` - All colors disabled.
+ - `1` - Basic 16 colors support.
+ - `2` - ANSI 256 colors support.
+ - `3` - Truecolor 16 million colors support.
+ */
+ level?: Level;
+ }
+
+ /**
+ Return a new Chalk instance.
+ */
+ type Instance = new (options?: Options) => Chalk;
+
+ /**
+ Detect whether the terminal supports color.
+ */
+ interface ColorSupport {
+ /**
+ The color level used by Chalk.
+ */
+ level: Level;
+
+ /**
+ Return whether Chalk supports basic 16 colors.
+ */
+ hasBasic: boolean;
+
+ /**
+ Return whether Chalk supports ANSI 256 colors.
+ */
+ has256: boolean;
+
+ /**
+ Return whether Chalk supports Truecolor 16 million colors.
+ */
+ has16m: boolean;
+ }
+
+ interface ChalkFunction {
+ /**
+ Use a template string.
+
+ @remarks Template literals are unsupported for nested calls (see [issue #341](https://github.com/chalk/chalk/issues/341))
+
+ @example
+ ```
+ import chalk = require('chalk');
+
+ log(chalk`
+ CPU: {red ${cpu.totalPercent}%}
+ RAM: {green ${ram.used / ram.total * 100}%}
+ DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
+ `);
+ ```
+
+ @example
+ ```
+ import chalk = require('chalk');
+
+ log(chalk.red.bgBlack`2 + 3 = {bold ${2 + 3}}`)
+ ```
+ */
+ (text: TemplateStringsArray, ...placeholders: unknown[]): string;
+
+ (...text: unknown[]): string;
+ }
+
+ interface Chalk extends ChalkFunction {
+ /**
+ Return a new Chalk instance.
+ */
+ Instance: Instance;
+
+ /**
+ The color support for Chalk.
+
+ By default, color support is automatically detected based on the environment.
+
+ Levels:
+ - `0` - All colors disabled.
+ - `1` - Basic 16 colors support.
+ - `2` - ANSI 256 colors support.
+ - `3` - Truecolor 16 million colors support.
+ */
+ level: Level;
+
+ /**
+ Use HEX value to set text color.
+
+ @param color - Hexadecimal value representing the desired color.
+
+ @example
+ ```
+ import chalk = require('chalk');
+
+ chalk.hex('#DEADED');
+ ```
+ */
+ hex(color: string): Chalk;
+
+ /**
+ Use keyword color value to set text color.
+
+ @param color - Keyword value representing the desired color.
+
+ @example
+ ```
+ import chalk = require('chalk');
+
+ chalk.keyword('orange');
+ ```
+ */
+ keyword(color: string): Chalk;
+
+ /**
+ Use RGB values to set text color.
+ */
+ rgb(red: number, green: number, blue: number): Chalk;
+
+ /**
+ Use HSL values to set text color.
+ */
+ hsl(hue: number, saturation: number, lightness: number): Chalk;
+
+ /**
+ Use HSV values to set text color.
+ */
+ hsv(hue: number, saturation: number, value: number): Chalk;
+
+ /**
+ Use HWB values to set text color.
+ */
+ hwb(hue: number, whiteness: number, blackness: number): Chalk;
+
+ /**
+ Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set text color.
+
+ 30 <= code && code < 38 || 90 <= code && code < 98
+ For example, 31 for red, 91 for redBright.
+ */
+ ansi(code: number): Chalk;
+
+ /**
+ Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
+ */
+ ansi256(index: number): Chalk;
+
+ /**
+ Use HEX value to set background color.
+
+ @param color - Hexadecimal value representing the desired color.
+
+ @example
+ ```
+ import chalk = require('chalk');
+
+ chalk.bgHex('#DEADED');
+ ```
+ */
+ bgHex(color: string): Chalk;
+
+ /**
+ Use keyword color value to set background color.
+
+ @param color - Keyword value representing the desired color.
+
+ @example
+ ```
+ import chalk = require('chalk');
+
+ chalk.bgKeyword('orange');
+ ```
+ */
+ bgKeyword(color: string): Chalk;
+
+ /**
+ Use RGB values to set background color.
+ */
+ bgRgb(red: number, green: number, blue: number): Chalk;
+
+ /**
+ Use HSL values to set background color.
+ */
+ bgHsl(hue: number, saturation: number, lightness: number): Chalk;
+
+ /**
+ Use HSV values to set background color.
+ */
+ bgHsv(hue: number, saturation: number, value: number): Chalk;
+
+ /**
+ Use HWB values to set background color.
+ */
+ bgHwb(hue: number, whiteness: number, blackness: number): Chalk;
+
+ /**
+ Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set background color.
+
+ 30 <= code && code < 38 || 90 <= code && code < 98
+ For example, 31 for red, 91 for redBright.
+ Use the foreground code, not the background code (for example, not 41, nor 101).
+ */
+ bgAnsi(code: number): Chalk;
+
+ /**
+ Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set background color.
+ */
+ bgAnsi256(index: number): Chalk;
+
+ /**
+ Modifier: Resets the current color chain.
+ */
+ readonly reset: Chalk;
+
+ /**
+ Modifier: Make text bold.
+ */
+ readonly bold: Chalk;
+
+ /**
+ Modifier: Emitting only a small amount of light.
+ */
+ readonly dim: Chalk;
+
+ /**
+ Modifier: Make text italic. (Not widely supported)
+ */
+ readonly italic: Chalk;
+
+ /**
+ Modifier: Make text underline. (Not widely supported)
+ */
+ readonly underline: Chalk;
+
+ /**
+ Modifier: Inverse background and foreground colors.
+ */
+ readonly inverse: Chalk;
+
+ /**
+ Modifier: Prints the text, but makes it invisible.
+ */
+ readonly hidden: Chalk;
+
+ /**
+ Modifier: Puts a horizontal line through the center of the text. (Not widely supported)
+ */
+ readonly strikethrough: Chalk;
+
+ /**
+ Modifier: Prints the text only when Chalk has a color support level > 0.
+ Can be useful for things that are purely cosmetic.
+ */
+ readonly visible: Chalk;
+
+ readonly black: Chalk;
+ readonly red: Chalk;
+ readonly green: Chalk;
+ readonly yellow: Chalk;
+ readonly blue: Chalk;
+ readonly magenta: Chalk;
+ readonly cyan: Chalk;
+ readonly white: Chalk;
+
+ /*
+ Alias for `blackBright`.
+ */
+ readonly gray: Chalk;
+
+ /*
+ Alias for `blackBright`.
+ */
+ readonly grey: Chalk;
+
+ readonly blackBright: Chalk;
+ readonly redBright: Chalk;
+ readonly greenBright: Chalk;
+ readonly yellowBright: Chalk;
+ readonly blueBright: Chalk;
+ readonly magentaBright: Chalk;
+ readonly cyanBright: Chalk;
+ readonly whiteBright: Chalk;
+
+ readonly bgBlack: Chalk;
+ readonly bgRed: Chalk;
+ readonly bgGreen: Chalk;
+ readonly bgYellow: Chalk;
+ readonly bgBlue: Chalk;
+ readonly bgMagenta: Chalk;
+ readonly bgCyan: Chalk;
+ readonly bgWhite: Chalk;
+
+ /*
+ Alias for `bgBlackBright`.
+ */
+ readonly bgGray: Chalk;
+
+ /*
+ Alias for `bgBlackBright`.
+ */
+ readonly bgGrey: Chalk;
+
+ readonly bgBlackBright: Chalk;
+ readonly bgRedBright: Chalk;
+ readonly bgGreenBright: Chalk;
+ readonly bgYellowBright: Chalk;
+ readonly bgBlueBright: Chalk;
+ readonly bgMagentaBright: Chalk;
+ readonly bgCyanBright: Chalk;
+ readonly bgWhiteBright: Chalk;
+ }
+}
+
+/**
+Main Chalk object that allows to chain styles together.
+Call the last one as a method with a string argument.
+Order doesn't matter, and later styles take precedent in case of a conflict.
+This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
+*/
+declare const chalk: chalk.Chalk & chalk.ChalkFunction & {
+ supportsColor: chalk.ColorSupport | false;
+ Level: chalk.Level;
+ Color: Color;
+ ForegroundColor: ForegroundColor;
+ BackgroundColor: BackgroundColor;
+ Modifiers: Modifiers;
+ stderr: chalk.Chalk & {supportsColor: chalk.ColorSupport | false};
+};
+
+export = chalk;
diff --git a/MistyCore/node_modules/chalk/license b/MistyCore/node_modules/chalk/license
new file mode 100644
index 0000000..e7af2f7
--- /dev/null
+++ b/MistyCore/node_modules/chalk/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MistyCore/node_modules/chalk/package.json b/MistyCore/node_modules/chalk/package.json
new file mode 100644
index 0000000..47c23f2
--- /dev/null
+++ b/MistyCore/node_modules/chalk/package.json
@@ -0,0 +1,68 @@
+{
+ "name": "chalk",
+ "version": "4.1.2",
+ "description": "Terminal string styling done right",
+ "license": "MIT",
+ "repository": "chalk/chalk",
+ "funding": "https://github.com/chalk/chalk?sponsor=1",
+ "main": "source",
+ "engines": {
+ "node": ">=10"
+ },
+ "scripts": {
+ "test": "xo && nyc ava && tsd",
+ "bench": "matcha benchmark.js"
+ },
+ "files": [
+ "source",
+ "index.d.ts"
+ ],
+ "keywords": [
+ "color",
+ "colour",
+ "colors",
+ "terminal",
+ "console",
+ "cli",
+ "string",
+ "str",
+ "ansi",
+ "style",
+ "styles",
+ "tty",
+ "formatting",
+ "rgb",
+ "256",
+ "shell",
+ "xterm",
+ "log",
+ "logging",
+ "command-line",
+ "text"
+ ],
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "devDependencies": {
+ "ava": "^2.4.0",
+ "coveralls": "^3.0.7",
+ "execa": "^4.0.0",
+ "import-fresh": "^3.1.0",
+ "matcha": "^0.7.0",
+ "nyc": "^15.0.0",
+ "resolve-from": "^5.0.0",
+ "tsd": "^0.7.4",
+ "xo": "^0.28.2"
+ },
+ "xo": {
+ "rules": {
+ "unicorn/prefer-string-slice": "off",
+ "unicorn/prefer-includes": "off",
+ "@typescript-eslint/member-ordering": "off",
+ "no-redeclare": "off",
+ "unicorn/string-content": "off",
+ "unicorn/better-regex": "off"
+ }
+ }
+}
diff --git a/MistyCore/node_modules/chalk/readme.md b/MistyCore/node_modules/chalk/readme.md
new file mode 100644
index 0000000..a055d21
--- /dev/null
+++ b/MistyCore/node_modules/chalk/readme.md
@@ -0,0 +1,341 @@
+<h1 align="center">
+ <br>
+ <br>
+ <img width="320" src="media/logo.svg" alt="Chalk">
+ <br>
+ <br>
+ <br>
+</h1>
+
+> Terminal string styling done right
+
+[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg) [![run on repl.it](https://repl.it/badge/github/chalk/chalk)](https://repl.it/github/chalk/chalk)
+
+<img src="https://cdn.jsdelivr.net/gh/chalk/ansi-styles@8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
+
+<br>
+
+---
+
+<div align="center">
+ <p>
+ <p>
+ <sup>
+ Sindre Sorhus' open source work is supported by the community on <a href="https://github.com/sponsors/sindresorhus">GitHub Sponsors</a> and <a href="https://stakes.social/0x44d871aebF0126Bf646753E2C976Aa7e68A66c15">Dev</a>
+ </sup>
+ </p>
+ <sup>Special thanks to:</sup>
+ <br>
+ <br>
+ <a href="https://standardresume.co/tech">
+ <img src="https://sindresorhus.com/assets/thanks/standard-resume-logo.svg" width="160"/>
+ </a>
+ <br>
+ <br>
+ <a href="https://retool.com/?utm_campaign=sindresorhus">
+ <img src="https://sindresorhus.com/assets/thanks/retool-logo.svg" width="230"/>
+ </a>
+ <br>
+ <br>
+ <a href="https://doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=chalk&utm_source=github">
+ <div>
+ <img src="https://dashboard.doppler.com/imgs/logo-long.svg" width="240" alt="Doppler">
+ </div>
+ <b>All your environment variables, in one place</b>
+ <div>
+ <span>Stop struggling with scattered API keys, hacking together home-brewed tools,</span>
+ <br>
+ <span>and avoiding access controls. Keep your team and servers in sync with Doppler.</span>
+ </div>
+ </a>
+ <br>
+ <a href="https://uibakery.io/?utm_source=chalk&utm_medium=sponsor&utm_campaign=github">
+ <div>
+ <img src="https://sindresorhus.com/assets/thanks/uibakery-logo.jpg" width="270" alt="UI Bakery">
+ </div>
+ </a>
+ </p>
+</div>
+
+---
+
+<br>
+
+## Highlights
+
+- Expressive API
+- Highly performant
+- Ability to nest styles
+- [256/Truecolor color support](#256-and-truecolor-color-support)
+- Auto-detects color support
+- Doesn't extend `String.prototype`
+- Clean and focused
+- Actively maintained
+- [Used by ~50,000 packages](https://www.npmjs.com/browse/depended/chalk) as of January 1, 2020
+
+## Install
+
+```console
+$ npm install chalk
+```
+
+## Usage
+
+```js
+const chalk = require('chalk');
+
+console.log(chalk.blue('Hello world!'));
+```
+
+Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
+
+```js
+const chalk = require('chalk');
+const log = console.log;
+
+// Combine styled and normal strings
+log(chalk.blue('Hello') + ' World' + chalk.red('!'));
+
+// Compose multiple styles using the chainable API
+log(chalk.blue.bgRed.bold('Hello world!'));
+
+// Pass in multiple arguments
+log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));
+
+// Nest styles
+log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));
+
+// Nest styles of the same type even (color, underline, background)
+log(chalk.green(
+ 'I am a green line ' +
+ chalk.blue.underline.bold('with a blue substring') +
+ ' that becomes green again!'
+));
+
+// ES2015 template literal
+log(`
+CPU: ${chalk.red('90%')}
+RAM: ${chalk.green('40%')}
+DISK: ${chalk.yellow('70%')}
+`);
+
+// ES2015 tagged template literal
+log(chalk`
+CPU: {red ${cpu.totalPercent}%}
+RAM: {green ${ram.used / ram.total * 100}%}
+DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
+`);
+
+// Use RGB colors in terminal emulators that support it.
+log(chalk.keyword('orange')('Yay for orange colored text!'));
+log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));
+log(chalk.hex('#DEADED').bold('Bold gray!'));
+```
+
+Easily define your own themes:
+
+```js
+const chalk = require('chalk');
+
+const error = chalk.bold.red;
+const warning = chalk.keyword('orange');
+
+console.log(error('Error!'));
+console.log(warning('Warning!'));
+```
+
+Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):
+
+```js
+const name = 'Sindre';
+console.log(chalk.green('Hello %s'), name);
+//=> 'Hello Sindre'
+```
+
+## API
+
+### chalk.`<style>[.<style>...](string, [string...])`
+
+Example: `chalk.red.bold.underline('Hello', 'world');`
+
+Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
+
+Multiple arguments will be separated by space.
+
+### chalk.level
+
+Specifies the level of color support.
+
+Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
+
+If you need to change this in a reusable module, create a new instance:
+
+```js
+const ctx = new chalk.Instance({level: 0});
+```
+
+| Level | Description |
+| :---: | :--- |
+| `0` | All colors disabled |
+| `1` | Basic color support (16 colors) |
+| `2` | 256 color support |
+| `3` | Truecolor support (16 million colors) |
+
+### chalk.supportsColor
+
+Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
+
+Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
+
+Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
+
+### chalk.stderr and chalk.stderr.supportsColor
+
+`chalk.stderr` contains a separate instance configured with color support detected for `stderr` stream instead of `stdout`. Override rules from `chalk.supportsColor` apply to this too. `chalk.stderr.supportsColor` is exposed for convenience.
+
+## Styles
+
+### Modifiers
+
+- `reset` - Resets the current color chain.
+- `bold` - Make text bold.
+- `dim` - Emitting only a small amount of light.
+- `italic` - Make text italic. *(Not widely supported)*
+- `underline` - Make text underline. *(Not widely supported)*
+- `inverse`- Inverse background and foreground colors.
+- `hidden` - Prints the text, but makes it invisible.
+- `strikethrough` - Puts a horizontal line through the center of the text. *(Not widely supported)*
+- `visible`- Prints the text only when Chalk has a color level > 0. Can be useful for things that are purely cosmetic.
+
+### Colors
+
+- `black`
+- `red`
+- `green`
+- `yellow`
+- `blue`
+- `magenta`
+- `cyan`
+- `white`
+- `blackBright` (alias: `gray`, `grey`)
+- `redBright`
+- `greenBright`
+- `yellowBright`
+- `blueBright`
+- `magentaBright`
+- `cyanBright`
+- `whiteBright`
+
+### Background colors
+
+- `bgBlack`
+- `bgRed`
+- `bgGreen`
+- `bgYellow`
+- `bgBlue`
+- `bgMagenta`
+- `bgCyan`
+- `bgWhite`
+- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
+- `bgRedBright`
+- `bgGreenBright`
+- `bgYellowBright`
+- `bgBlueBright`
+- `bgMagentaBright`
+- `bgCyanBright`
+- `bgWhiteBright`
+
+## Tagged template literal
+
+Chalk can be used as a [tagged template literal](https://exploringjs.com/es6/ch_template-literals.html#_tagged-template-literals).
+
+```js
+const chalk = require('chalk');
+
+const miles = 18;
+const calculateFeet = miles => miles * 5280;
+
+console.log(chalk`
+ There are {bold 5280 feet} in a mile.
+ In {bold ${miles} miles}, there are {green.bold ${calculateFeet(miles)} feet}.
+`);
+```
+
+Blocks are delimited by an opening curly brace (`{`), a style, some content, and a closing curly brace (`}`).
+
+Template styles are chained exactly like normal Chalk styles. The following three statements are equivalent:
+
+```js
+console.log(chalk.bold.rgb(10, 100, 200)('Hello!'));
+console.log(chalk.bold.rgb(10, 100, 200)`Hello!`);
+console.log(chalk`{bold.rgb(10,100,200) Hello!}`);
+```
+
+Note that function styles (`rgb()`, `hsl()`, `keyword()`, etc.) may not contain spaces between parameters.
+
+All interpolated values (`` chalk`${foo}` ``) are converted to strings via the `.toString()` method. All curly braces (`{` and `}`) in interpolated value strings are escaped.
+
+## 256 and Truecolor color support
+
+Chalk supports 256 colors and [Truecolor](https://gist.github.com/XVilka/8346728) (16 million colors) on supported terminal apps.
+
+Colors are downsampled from 16 million RGB values to an ANSI color format that is supported by the terminal emulator (or by specifying `{level: n}` as a Chalk option). For example, Chalk configured to run at level 1 (basic color support) will downsample an RGB value of #FF0000 (red) to 31 (ANSI escape for red).
+
+Examples:
+
+- `chalk.hex('#DEADED').underline('Hello, world!')`
+- `chalk.keyword('orange')('Some orange text')`
+- `chalk.rgb(15, 100, 204).inverse('Hello!')`
+
+Background versions of these models are prefixed with `bg` and the first level of the module capitalized (e.g. `keyword` for foreground colors and `bgKeyword` for background colors).
+
+- `chalk.bgHex('#DEADED').underline('Hello, world!')`
+- `chalk.bgKeyword('orange')('Some orange text')`
+- `chalk.bgRgb(15, 100, 204).inverse('Hello!')`
+
+The following color models can be used:
+
+- [`rgb`](https://en.wikipedia.org/wiki/RGB_color_model) - Example: `chalk.rgb(255, 136, 0).bold('Orange!')`
+- [`hex`](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) - Example: `chalk.hex('#FF8800').bold('Orange!')`
+- [`keyword`](https://www.w3.org/wiki/CSS/Properties/color/keywords) (CSS keywords) - Example: `chalk.keyword('orange').bold('Orange!')`
+- [`hsl`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsl(32, 100, 50).bold('Orange!')`
+- [`hsv`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsv(32, 100, 100).bold('Orange!')`
+- [`hwb`](https://en.wikipedia.org/wiki/HWB_color_model) - Example: `chalk.hwb(32, 0, 50).bold('Orange!')`
+- [`ansi`](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) - Example: `chalk.ansi(31).bgAnsi(93)('red on yellowBright')`
+- [`ansi256`](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) - Example: `chalk.bgAnsi256(194)('Honeydew, more or less')`
+
+## Windows
+
+If you're on Windows, do yourself a favor and use [Windows Terminal](https://github.com/microsoft/terminal) instead of `cmd.exe`.
+
+## Origin story
+
+[colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68) and the package is unmaintained. Although there are other packages, they either do too much or not enough. Chalk is a clean and focused alternative.
+
+## chalk for enterprise
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of chalk and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-chalk?utm_source=npm-chalk&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
+
+## Related
+
+- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
+- [ansi-styles](https://github.com/chalk/ansi-styles) - ANSI escape codes for styling strings in the terminal
+- [supports-color](https://github.com/chalk/supports-color) - Detect whether a terminal supports color
+- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
+- [strip-ansi-stream](https://github.com/chalk/strip-ansi-stream) - Strip ANSI escape codes from a stream
+- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
+- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
+- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
+- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
+- [color-convert](https://github.com/qix-/color-convert) - Converts colors between different models
+- [chalk-animation](https://github.com/bokub/chalk-animation) - Animate strings in the terminal
+- [gradient-string](https://github.com/bokub/gradient-string) - Apply color gradients to strings
+- [chalk-pipe](https://github.com/LitoMore/chalk-pipe) - Create chalk style schemes with simpler style strings
+- [terminal-link](https://github.com/sindresorhus/terminal-link) - Create clickable links in the terminal
+
+## Maintainers
+
+- [Sindre Sorhus](https://github.com/sindresorhus)
+- [Josh Junon](https://github.com/qix-)
diff --git a/MistyCore/node_modules/chalk/source/index.js b/MistyCore/node_modules/chalk/source/index.js
new file mode 100644
index 0000000..75ec663
--- /dev/null
+++ b/MistyCore/node_modules/chalk/source/index.js
@@ -0,0 +1,229 @@
+'use strict';
+const ansiStyles = require('ansi-styles');
+const {stdout: stdoutColor, stderr: stderrColor} = require('supports-color');
+const {
+ stringReplaceAll,
+ stringEncaseCRLFWithFirstIndex
+} = require('./util');
+
+const {isArray} = Array;
+
+// `supportsColor.level` → `ansiStyles.color[name]` mapping
+const levelMapping = [
+ 'ansi',
+ 'ansi',
+ 'ansi256',
+ 'ansi16m'
+];
+
+const styles = Object.create(null);
+
+const applyOptions = (object, options = {}) => {
+ if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
+ throw new Error('The `level` option should be an integer from 0 to 3');
+ }
+
+ // Detect level if not set manually
+ const colorLevel = stdoutColor ? stdoutColor.level : 0;
+ object.level = options.level === undefined ? colorLevel : options.level;
+};
+
+class ChalkClass {
+ constructor(options) {
+ // eslint-disable-next-line no-constructor-return
+ return chalkFactory(options);
+ }
+}
+
+const chalkFactory = options => {
+ const chalk = {};
+ applyOptions(chalk, options);
+
+ chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_);
+
+ Object.setPrototypeOf(chalk, Chalk.prototype);
+ Object.setPrototypeOf(chalk.template, chalk);
+
+ chalk.template.constructor = () => {
+ throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.');
+ };
+
+ chalk.template.Instance = ChalkClass;
+
+ return chalk.template;
+};
+
+function Chalk(options) {
+ return chalkFactory(options);
+}
+
+for (const [styleName, style] of Object.entries(ansiStyles)) {
+ styles[styleName] = {
+ get() {
+ const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty);
+ Object.defineProperty(this, styleName, {value: builder});
+ return builder;
+ }
+ };
+}
+
+styles.visible = {
+ get() {
+ const builder = createBuilder(this, this._styler, true);
+ Object.defineProperty(this, 'visible', {value: builder});
+ return builder;
+ }
+};
+
+const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256'];
+
+for (const model of usedModels) {
+ styles[model] = {
+ get() {
+ const {level} = this;
+ return function (...arguments_) {
+ const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler);
+ return createBuilder(this, styler, this._isEmpty);
+ };
+ }
+ };
+}
+
+for (const model of usedModels) {
+ const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
+ styles[bgModel] = {
+ get() {
+ const {level} = this;
+ return function (...arguments_) {
+ const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler);
+ return createBuilder(this, styler, this._isEmpty);
+ };
+ }
+ };
+}
+
+const proto = Object.defineProperties(() => {}, {
+ ...styles,
+ level: {
+ enumerable: true,
+ get() {
+ return this._generator.level;
+ },
+ set(level) {
+ this._generator.level = level;
+ }
+ }
+});
+
+const createStyler = (open, close, parent) => {
+ let openAll;
+ let closeAll;
+ if (parent === undefined) {
+ openAll = open;
+ closeAll = close;
+ } else {
+ openAll = parent.openAll + open;
+ closeAll = close + parent.closeAll;
+ }
+
+ return {
+ open,
+ close,
+ openAll,
+ closeAll,
+ parent
+ };
+};
+
+const createBuilder = (self, _styler, _isEmpty) => {
+ const builder = (...arguments_) => {
+ if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) {
+ // Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}`
+ return applyStyle(builder, chalkTag(builder, ...arguments_));
+ }
+
+ // Single argument is hot path, implicit coercion is faster than anything
+ // eslint-disable-next-line no-implicit-coercion
+ return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
+ };
+
+ // We alter the prototype because we must return a function, but there is
+ // no way to create a function with a different prototype
+ Object.setPrototypeOf(builder, proto);
+
+ builder._generator = self;
+ builder._styler = _styler;
+ builder._isEmpty = _isEmpty;
+
+ return builder;
+};
+
+const applyStyle = (self, string) => {
+ if (self.level <= 0 || !string) {
+ return self._isEmpty ? '' : string;
+ }
+
+ let styler = self._styler;
+
+ if (styler === undefined) {
+ return string;
+ }
+
+ const {openAll, closeAll} = styler;
+ if (string.indexOf('\u001B') !== -1) {
+ while (styler !== undefined) {
+ // Replace any instances already present with a re-opening code
+ // otherwise only the part of the string until said closing code
+ // will be colored, and the rest will simply be 'plain'.
+ string = stringReplaceAll(string, styler.close, styler.open);
+
+ styler = styler.parent;
+ }
+ }
+
+ // We can move both next actions out of loop, because remaining actions in loop won't have
+ // any/visible effect on parts we add here. Close the styling before a linebreak and reopen
+ // after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92
+ const lfIndex = string.indexOf('\n');
+ if (lfIndex !== -1) {
+ string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
+ }
+
+ return openAll + string + closeAll;
+};
+
+let template;
+const chalkTag = (chalk, ...strings) => {
+ const [firstString] = strings;
+
+ if (!isArray(firstString) || !isArray(firstString.raw)) {
+ // If chalk() was called by itself or with a string,
+ // return the string itself as a string.
+ return strings.join(' ');
+ }
+
+ const arguments_ = strings.slice(1);
+ const parts = [firstString.raw[0]];
+
+ for (let i = 1; i < firstString.length; i++) {
+ parts.push(
+ String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'),
+ String(firstString.raw[i])
+ );
+ }
+
+ if (template === undefined) {
+ template = require('./templates');
+ }
+
+ return template(chalk, parts.join(''));
+};
+
+Object.defineProperties(Chalk.prototype, styles);
+
+const chalk = Chalk(); // eslint-disable-line new-cap
+chalk.supportsColor = stdoutColor;
+chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap
+chalk.stderr.supportsColor = stderrColor;
+
+module.exports = chalk;
diff --git a/MistyCore/node_modules/chalk/source/templates.js b/MistyCore/node_modules/chalk/source/templates.js
new file mode 100644
index 0000000..b130949
--- /dev/null
+++ b/MistyCore/node_modules/chalk/source/templates.js
@@ -0,0 +1,134 @@
+'use strict';
+const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
+const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
+const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
+const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi;
+
+const ESCAPES = new Map([
+ ['n', '\n'],
+ ['r', '\r'],
+ ['t', '\t'],
+ ['b', '\b'],
+ ['f', '\f'],
+ ['v', '\v'],
+ ['0', '\0'],
+ ['\\', '\\'],
+ ['e', '\u001B'],
+ ['a', '\u0007']
+]);
+
+function unescape(c) {
+ const u = c[0] === 'u';
+ const bracket = c[1] === '{';
+
+ if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
+ return String.fromCharCode(parseInt(c.slice(1), 16));
+ }
+
+ if (u && bracket) {
+ return String.fromCodePoint(parseInt(c.slice(2, -1), 16));
+ }
+
+ return ESCAPES.get(c) || c;
+}
+
+function parseArguments(name, arguments_) {
+ const results = [];
+ const chunks = arguments_.trim().split(/\s*,\s*/g);
+ let matches;
+
+ for (const chunk of chunks) {
+ const number = Number(chunk);
+ if (!Number.isNaN(number)) {
+ results.push(number);
+ } else if ((matches = chunk.match(STRING_REGEX))) {
+ results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character));
+ } else {
+ throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
+ }
+ }
+
+ return results;
+}
+
+function parseStyle(style) {
+ STYLE_REGEX.lastIndex = 0;
+
+ const results = [];
+ let matches;
+
+ while ((matches = STYLE_REGEX.exec(style)) !== null) {
+ const name = matches[1];
+
+ if (matches[2]) {
+ const args = parseArguments(name, matches[2]);
+ results.push([name].concat(args));
+ } else {
+ results.push([name]);
+ }
+ }
+
+ return results;
+}
+
+function buildStyle(chalk, styles) {
+ const enabled = {};
+
+ for (const layer of styles) {
+ for (const style of layer.styles) {
+ enabled[style[0]] = layer.inverse ? null : style.slice(1);
+ }
+ }
+
+ let current = chalk;
+ for (const [styleName, styles] of Object.entries(enabled)) {
+ if (!Array.isArray(styles)) {
+ continue;
+ }
+
+ if (!(styleName in current)) {
+ throw new Error(`Unknown Chalk style: ${styleName}`);
+ }
+
+ current = styles.length > 0 ? current[styleName](...styles) : current[styleName];
+ }
+
+ return current;
+}
+
+module.exports = (chalk, temporary) => {
+ const styles = [];
+ const chunks = [];
+ let chunk = [];
+
+ // eslint-disable-next-line max-params
+ temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => {
+ if (escapeCharacter) {
+ chunk.push(unescape(escapeCharacter));
+ } else if (style) {
+ const string = chunk.join('');
+ chunk = [];
+ chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string));
+ styles.push({inverse, styles: parseStyle(style)});
+ } else if (close) {
+ if (styles.length === 0) {
+ throw new Error('Found extraneous } in Chalk template literal');
+ }
+
+ chunks.push(buildStyle(chalk, styles)(chunk.join('')));
+ chunk = [];
+ styles.pop();
+ } else {
+ chunk.push(character);
+ }
+ });
+
+ chunks.push(chunk.join(''));
+
+ if (styles.length > 0) {
+ const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
+ throw new Error(errMessage);
+ }
+
+ return chunks.join('');
+};
diff --git a/MistyCore/node_modules/chalk/source/util.js b/MistyCore/node_modules/chalk/source/util.js
new file mode 100644
index 0000000..ca466fd
--- /dev/null
+++ b/MistyCore/node_modules/chalk/source/util.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const stringReplaceAll = (string, substring, replacer) => {
+ let index = string.indexOf(substring);
+ if (index === -1) {
+ return string;
+ }
+
+ const substringLength = substring.length;
+ let endIndex = 0;
+ let returnValue = '';
+ do {
+ returnValue += string.substr(endIndex, index - endIndex) + substring + replacer;
+ endIndex = index + substringLength;
+ index = string.indexOf(substring, endIndex);
+ } while (index !== -1);
+
+ returnValue += string.substr(endIndex);
+ return returnValue;
+};
+
+const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => {
+ let endIndex = 0;
+ let returnValue = '';
+ do {
+ const gotCR = string[index - 1] === '\r';
+ returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix;
+ endIndex = index + 1;
+ index = string.indexOf('\n', endIndex);
+ } while (index !== -1);
+
+ returnValue += string.substr(endIndex);
+ return returnValue;
+};
+
+module.exports = {
+ stringReplaceAll,
+ stringEncaseCRLFWithFirstIndex
+};
diff --git a/MistyCore/node_modules/color-convert/CHANGELOG.md b/MistyCore/node_modules/color-convert/CHANGELOG.md
new file mode 100644
index 0000000..0a7bce4
--- /dev/null
+++ b/MistyCore/node_modules/color-convert/CHANGELOG.md
@@ -0,0 +1,54 @@
+# 1.0.0 - 2016-01-07
+
+- Removed: unused speed test
+- Added: Automatic routing between previously unsupported conversions
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Removed: `xxx2xxx()` and `xxx2xxxRaw()` functions
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Removed: `convert()` class
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Changed: all functions to lookup dictionary
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Changed: `ansi` to `ansi256`
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Fixed: argument grouping for functions requiring only one argument
+([#27](https://github.com/Qix-/color-convert/pull/27))
+
+# 0.6.0 - 2015-07-23
+
+- Added: methods to handle
+[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 16/256 colors:
+ - rgb2ansi16
+ - rgb2ansi
+ - hsl2ansi16
+ - hsl2ansi
+ - hsv2ansi16
+ - hsv2ansi
+ - hwb2ansi16
+ - hwb2ansi
+ - cmyk2ansi16
+ - cmyk2ansi
+ - keyword2ansi16
+ - keyword2ansi
+ - ansi162rgb
+ - ansi162hsl
+ - ansi162hsv
+ - ansi162hwb
+ - ansi162cmyk
+ - ansi162keyword
+ - ansi2rgb
+ - ansi2hsl
+ - ansi2hsv
+ - ansi2hwb
+ - ansi2cmyk
+ - ansi2keyword
+([#18](https://github.com/harthur/color-convert/pull/18))
+
+# 0.5.3 - 2015-06-02
+
+- Fixed: hsl2hsv does not return `NaN` anymore when using `[0,0,0]`
+([#15](https://github.com/harthur/color-convert/issues/15))
+
+---
+
+Check out commit logs for older releases
diff --git a/MistyCore/node_modules/color-convert/LICENSE b/MistyCore/node_modules/color-convert/LICENSE
new file mode 100644
index 0000000..5b4c386
--- /dev/null
+++ b/MistyCore/node_modules/color-convert/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/MistyCore/node_modules/color-convert/README.md b/MistyCore/node_modules/color-convert/README.md
new file mode 100644
index 0000000..d4b08fc
--- /dev/null
+++ b/MistyCore/node_modules/color-convert/README.md
@@ -0,0 +1,68 @@
+# color-convert
+
+[![Build Status](https://travis-ci.org/Qix-/color-convert.svg?branch=master)](https://travis-ci.org/Qix-/color-convert)
+
+Color-convert is a color conversion library for JavaScript and node.
+It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest):
+
+```js
+var convert = require('color-convert');
+
+convert.rgb.hsl(140, 200, 100); // [96, 48, 59]
+convert.keyword.rgb('blue'); // [0, 0, 255]
+
+var rgbChannels = convert.rgb.channels; // 3
+var cmykChannels = convert.cmyk.channels; // 4
+var ansiChannels = convert.ansi16.channels; // 1
+```
+
+# Install
+
+```console
+$ npm install color-convert
+```
+
+# API
+
+Simply get the property of the _from_ and _to_ conversion that you're looking for.
+
+All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function.
+
+All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha).
+
+```js
+var convert = require('color-convert');
+
+// Hex to LAB
+convert.hex.lab('DEADBF'); // [ 76, 21, -2 ]
+convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ]
+
+// RGB to CMYK
+convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ]
+convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ]
+```
+
+### Arrays
+All functions that accept multiple arguments also support passing an array.
+
+Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.)
+
+```js
+var convert = require('color-convert');
+
+convert.rgb.hex(123, 45, 67); // '7B2D43'
+convert.rgb.hex([123, 45, 67]); // '7B2D43'
+```
+
+## Routing
+
+Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex).
+
+Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js).
+
+# Contribute
+
+If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request.
+
+# License
+Copyright &copy; 2011-2016, Heather Arthur and Josh Junon. Licensed under the [MIT License](LICENSE).
diff --git a/MistyCore/node_modules/color-convert/conversions.js b/MistyCore/node_modules/color-convert/conversions.js
new file mode 100644
index 0000000..2657f26
--- /dev/null
+++ b/MistyCore/node_modules/color-convert/conversions.js
@@ -0,0 +1,839 @@
+/* MIT license */
+/* eslint-disable no-mixed-operators */
+const cssKeywords = require('color-name');
+
+// NOTE: conversions should only return primitive values (i.e. arrays, or
+// values that give correct `typeof` results).
+// do not use box values types (i.e. Number(), String(), etc.)
+
+const reverseKeywords = {};
+for (const key of Object.keys(cssKeywords)) {
+ reverseKeywords[cssKeywords[key]] = key;
+}
+
+const convert = {
+ rgb: {channels: 3, labels: 'rgb'},
+ hsl: {channels: 3, labels: 'hsl'},
+ hsv: {channels: 3, labels: 'hsv'},
+ hwb: {channels: 3, labels: 'hwb'},
+ cmyk: {channels: 4, labels: 'cmyk'},
+ xyz: {channels: 3, labels: 'xyz'},
+ lab: {channels: 3, labels: 'lab'},
+ lch: {channels: 3, labels: 'lch'},
+ hex: {channels: 1, labels: ['hex']},
+ keyword: {channels: 1, labels: ['keyword']},
+ ansi16: {channels: 1, labels: ['ansi16']},
+ ansi256: {channels: 1, labels: ['ansi256']},
+ hcg: {channels: 3, labels: ['h', 'c', 'g']},
+ apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
+ gray: {channels: 1, labels: ['gray']}
+};
+
+module.exports = convert;
+
+// Hide .channels and .labels properties
+for (const model of Object.keys(convert)) {
+ if (!('channels' in convert[model])) {
+ throw new Error('missing channels property: ' + model);
+ }
+
+ if (!('labels' in convert[model])) {
+ throw new Error('missing channel labels property: ' + model);
+ }
+
+ if (convert[model].labels.length !== convert[model].channels) {
+ throw new Error('channel and label counts mismatch: ' + model);
+ }
+
+ const {channels, labels} = convert[model];
+ delete convert[model].channels;
+ delete convert[model].labels;
+ Object.defineProperty(convert[model], 'channels', {value: channels});
+ Object.defineProperty(convert[model], 'labels', {value: labels});
+}
+
+convert.rgb.hsl = function (rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const min = Math.min(r, g, b);
+ const max = Math.max(r, g, b);
+ const delta = max - min;
+ let h;
+ let s;
+
+ if (max === min) {
+ h = 0;
+ } else if (r === max) {
+ h = (g - b) / delta;
+ } else if (g === max) {
+ h = 2 + (b - r) / delta;
+ } else if (b === max) {
+ h = 4 + (r - g) / delta;
+ }
+
+ h = Math.min(h * 60, 360);
+
+ if (h < 0) {
+ h += 360;
+ }
+
+ const l = (min + max) / 2;
+
+ if (max === min) {
+ s = 0;
+ } else if (l <= 0.5) {
+ s = delta / (max + min);
+ } else {
+ s = delta / (2 - max - min);
+ }
+
+ return [h, s * 100, l * 100];
+};
+
+convert.rgb.hsv = function (rgb) {
+ let rdif;
+ let gdif;
+ let bdif;
+ let h;
+ let s;
+
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const v = Math.max(r, g, b);
+ const diff = v - Math.min(r, g, b);
+ const diffc = function (c) {
+ return (v - c) / 6 / diff + 1 / 2;
+ };
+
+ if (diff === 0) {
+ h = 0;
+ s = 0;
+ } else {
+ s = diff / v;
+ rdif = diffc(r);
+ gdif = diffc(g);
+ bdif = diffc(b);
+
+ if (r === v) {
+ h = bdif - gdif;
+ } else if (g === v) {
+ h = (1 / 3) + rdif - bdif;
+ } else if (b === v) {
+ h = (2 / 3) + gdif - rdif;
+ }
+
+ if (h < 0) {
+ h += 1;
+ } else if (h > 1) {
+ h -= 1;
+ }
+ }
+
+ return [
+ h * 360,
+ s * 100,
+ v * 100
+ ];
+};
+
+convert.rgb.hwb = function (rgb) {
+ const r = rgb[0];
+ const g = rgb[1];
+ let b = rgb[2];
+ const h = convert.rgb.hsl(rgb)[0];
+ const w = 1 / 255 * Math.min(r, Math.min(g, b));
+
+ b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
+
+ return [h, w * 100, b * 100];
+};
+
+convert.rgb.cmyk = function (rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+
+ const k = Math.min(1 - r, 1 - g, 1 - b);
+ const c = (1 - r - k) / (1 - k) || 0;
+ const m = (1 - g - k) / (1 - k) || 0;
+ const y = (1 - b - k) / (1 - k) || 0;
+
+ return [c * 100, m * 100, y * 100, k * 100];
+};
+
+function comparativeDistance(x, y) {
+ /*
+ See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
+ */
+ return (
+ ((x[0] - y[0]) ** 2) +
+ ((x[1] - y[1]) ** 2) +
+ ((x[2] - y[2]) ** 2)
+ );
+}
+
+convert.rgb.keyword = function (rgb) {
+ const reversed = reverseKeywords[rgb];
+ if (reversed) {
+ return reversed;
+ }
+
+ let currentClosestDistance = Infinity;
+ let currentClosestKeyword;
+
+ for (const keyword of Object.keys(cssKeywords)) {
+ const value = cssKeywords[keyword];
+
+ // Compute comparative distance
+ const distance = comparativeDistance(rgb, value);
+
+ // Check if its less, if so set as closest
+ if (distance < currentClosestDistance) {
+ currentClosestDistance = distance;
+ currentClosestKeyword = keyword;
+ }
+ }
+
+ return currentClosestKeyword;
+};
+
+convert.keyword.rgb = function (keyword) {
+ return cssKeywords[keyword];
+};
+
+convert.rgb.xyz = function (rgb) {
+ let r = rgb[0] / 255;
+ let g = rgb[1] / 255;
+ let b = rgb[2] / 255;
+
+ // Assume sRGB
+ r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92);
+ g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92);
+ b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92);
+
+ const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
+ const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
+ const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
+
+ return [x * 100, y * 100, z * 100];
+};
+
+convert.rgb.lab = function (rgb) {
+ const xyz = convert.rgb.xyz(rgb);
+ let x = xyz[0];
+ let y = xyz[1];
+ let z = xyz[2];
+
+ x /= 95.047;
+ y /= 100;
+ z /= 108.883;
+
+ x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
+ y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
+ z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
+
+ const l = (116 * y) - 16;
+ const a = 500 * (x - y);
+ const b = 200 * (y - z);
+
+ return [l, a, b];
+};
+
+convert.hsl.rgb = function (hsl) {
+ const h = hsl[0] / 360;
+ const s = hsl[1] / 100;
+ const l = hsl[2] / 100;
+ let t2;
+ let t3;
+ let val;
+
+ if (s === 0) {
+ val = l * 255;
+ return [val, val, val];
+ }
+
+ if (l < 0.5) {
+ t2 = l * (1 + s);
+ } else {
+ t2 = l + s - l * s;
+ }
+
+ const t1 = 2 * l - t2;
+
+ const rgb = [0, 0, 0];
+ for (let i = 0; i < 3; i++) {
+ t3 = h + 1 / 3 * -(i - 1);
+ if (t3 < 0) {
+ t3++;
+ }
+
+ if (t3 > 1) {
+ t3--;
+ }
+
+ if (6 * t3 < 1) {
+ val = t1 + (t2 - t1) * 6 * t3;
+ } else if (2 * t3 < 1) {
+ val = t2;
+ } else if (3 * t3 < 2) {
+ val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
+ } else {
+ val = t1;
+ }
+
+ rgb[i] = val * 255;
+ }
+
+ return rgb;
+};
+
+convert.hsl.hsv = function (hsl) {
+ const h = hsl[0];
+ let s = hsl[1] / 100;
+ let l = hsl[2] / 100;
+ let smin = s;
+ const lmin = Math.max(l, 0.01);
+
+ l *= 2;
+ s *= (l <= 1) ? l : 2 - l;
+ smin *= lmin <= 1 ? lmin : 2 - lmin;
+ const v = (l + s) / 2;
+ const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
+
+ return [h, sv * 100, v * 100];
+};
+
+convert.hsv.rgb = function (hsv) {
+ const h = hsv[0] / 60;
+ const s = hsv[1] / 100;
+ let v = hsv[2] / 100;
+ const hi = Math.floor(h) % 6;
+
+ const f = h - Math.floor(h);
+ const p = 255 * v * (1 - s);
+ const q = 255 * v * (1 - (s * f));
+ const t = 255 * v * (1 - (s * (1 - f)));
+ v *= 255;
+
+ switch (hi) {
+ case 0:
+ return [v, t, p];
+ case 1:
+ return [q, v, p];
+ case 2:
+ return [p, v, t];
+ case 3:
+ return [p, q, v];
+ case 4:
+ return [t, p, v];
+ case 5:
+ return [v, p, q];
+ }
+};
+
+convert.hsv.hsl = function (hsv) {
+ const h = hsv[0];
+ const s = hsv[1] / 100;
+ const v = hsv[2] / 100;
+ const vmin = Math.max(v, 0.01);
+ let sl;
+ let l;
+
+ l = (2 - s) * v;
+ const lmin = (2 - s) * vmin;
+ sl = s * vmin;
+ sl /= (lmin <= 1) ? lmin : 2 - lmin;
+ sl = sl || 0;
+ l /= 2;
+
+ return [h, sl * 100, l * 100];
+};
+
+// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
+convert.hwb.rgb = function (hwb) {
+ const h = hwb[0] / 360;
+ let wh = hwb[1] / 100;
+ let bl = hwb[2] / 100;
+ const ratio = wh + bl;
+ let f;
+
+ // Wh + bl cant be > 1
+ if (ratio > 1) {
+ wh /= ratio;
+ bl /= ratio;
+ }
+
+ const i = Math.floor(6 * h);
+ const v = 1 - bl;
+ f = 6 * h - i;
+
+ if ((i & 0x01) !== 0) {
+ f = 1 - f;
+ }
+
+ const n = wh + f * (v - wh); // Linear interpolation
+
+ let r;
+ let g;
+ let b;
+ /* eslint-disable max-statements-per-line,no-multi-spaces */
+ switch (i) {
+ default:
+ case 6:
+ case 0: r = v; g = n; b = wh; break;
+ case 1: r = n; g = v; b = wh; break;
+ case 2: r = wh; g = v; b = n; break;
+ case 3: r = wh; g = n; b = v; break;
+ case 4: r = n; g = wh; b = v; break;
+ case 5: r = v; g = wh; b = n; break;
+ }
+ /* eslint-enable max-statements-per-line,no-multi-spaces */
+
+ return [r * 255, g * 255, b * 255];
+};
+
+convert.cmyk.rgb = function (cmyk) {
+ const c = cmyk[0] / 100;
+ const m = cmyk[1] / 100;
+ const y = cmyk[2] / 100;
+ const k = cmyk[3] / 100;
+
+ const r = 1 - Math.min(1, c * (1 - k) + k);
+ const g = 1 - Math.min(1, m * (1 - k) + k);
+ const b = 1 - Math.min(1, y * (1 - k) + k);
+
+ return [r * 255, g * 255, b * 255];
+};
+
+convert.xyz.rgb = function (xyz) {
+ const x = xyz[0] / 100;
+ const y = xyz[1] / 100;
+ const z = xyz[2] / 100;
+ let r;
+ let g;
+ let b;
+
+ r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
+ g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
+ b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
+
+ // Assume sRGB
+ r = r > 0.0031308
+ ? ((1.055 * (r ** (1.0 / 2.4))) - 0.055)
+ : r * 12.92;
+
+ g = g > 0.0031308
+ ? ((1.055 * (g ** (1.0 / 2.4))) - 0.055)
+ : g * 12.92;
+
+ b = b > 0.0031308
+ ? ((1.055 * (b ** (1.0 / 2.4))) - 0.055)
+ : b * 12.92;
+
+ r = Math.min(Math.max(0, r), 1);
+ g = Math.min(Math.max(0, g), 1);
+ b = Math.min(Math.max(0, b), 1);
+
+ return [r * 255, g * 255, b * 255];
+};
+
+convert.xyz.lab = function (xyz) {
+ let x = xyz[0];
+ let y = xyz[1];
+ let z = xyz[2];
+
+ x /= 95.047;
+ y /= 100;
+ z /= 108.883;
+
+ x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
+ y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
+ z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
+
+ const l = (116 * y) - 16;
+ const a = 500 * (x - y);
+ const b = 200 * (y - z);
+
+ return [l, a, b];
+};
+
+convert.lab.xyz = function (lab) {
+ const l = lab[0];
+ const a = lab[1];
+ const b = lab[2];
+ let x;
+ let y;
+ let z;
+
+ y = (l + 16) / 116;
+ x = a / 500 + y;
+ z = y - b / 200;
+
+ const y2 = y ** 3;
+ const x2 = x ** 3;
+ const z2 = z ** 3;
+ y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
+ x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
+ z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
+
+ x *= 95.047;
+ y *= 100;
+ z *= 108.883;
+
+ return [x, y, z];
+};
+
+convert.lab.lch = function (lab) {
+ const l = lab[0];
+ const a = lab[1];
+ const b = lab[2];
+ let h;
+
+ const hr = Math.atan2(b, a);
+ h = hr * 360 / 2 / Math.PI;
+
+ if (h < 0) {
+ h += 360;
+ }
+
+ const c = Math.sqrt(a * a + b * b);
+
+ return [l, c, h];
+};
+
+convert.lch.lab = function (lch) {
+ const l = lch[0];
+ const c = lch[1];
+ const h = lch[2];
+
+ const hr = h / 360 * 2 * Math.PI;
+ const a = c * Math.cos(hr);
+ const b = c * Math.sin(hr);
+
+ return [l, a, b];
+};
+
+convert.rgb.ansi16 = function (args, saturation = null) {
+ const [r, g, b] = args;
+ let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization
+
+ value = Math.round(value / 50);
+
+ if (value === 0) {
+ return 30;
+ }
+
+ let ansi = 30
+ + ((Math.round(b / 255) << 2)
+ | (Math.round(g / 255) << 1)
+ | Math.round(r / 255));
+
+ if (value === 2) {
+ ansi += 60;
+ }
+
+ return ansi;
+};
+
+convert.hsv.ansi16 = function (args) {
+ // Optimization here; we already know the value and don't need to get
+ // it converted for us.
+ return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
+};
+
+convert.rgb.ansi256 = function (args) {
+ const r = args[0];
+ const g = args[1];
+ const b = args[2];
+
+ // We use the extended greyscale palette here, with the exception of
+ // black and white. normal palette only has 4 greyscale shades.
+ if (r === g && g === b) {
+ if (r < 8) {
+ return 16;
+ }
+
+ if (r > 248) {
+ return 231;
+ }
+
+ return Math.round(((r - 8) / 247) * 24) + 232;
+ }
+
+ const ansi = 16
+ + (36 * Math.round(r / 255 * 5))
+ + (6 * Math.round(g / 255 * 5))
+ + Math.round(b / 255 * 5);
+
+ return ansi;
+};
+
+convert.ansi16.rgb = function (args) {
+ let color = args % 10;
+
+ // Handle greyscale
+ if (color === 0 || color === 7) {
+ if (args > 50) {
+ color += 3.5;
+ }
+
+ color = color / 10.5 * 255;
+
+ return [color, color, color];
+ }
+
+ const mult = (~~(args > 50) + 1) * 0.5;
+ const r = ((color & 1) * mult) * 255;
+ const g = (((color >> 1) & 1) * mult) * 255;
+ const b = (((color >> 2) & 1) * mult) * 255;
+
+ return [r, g, b];
+};
+
+convert.ansi256.rgb = function (args) {
+ // Handle greyscale
+ if (args >= 232) {
+ const c = (args - 232) * 10 + 8;
+ return [c, c, c];
+ }
+
+ args -= 16;
+
+ let rem;
+ const r = Math.floor(args / 36) / 5 * 255;
+ const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
+ const b = (rem % 6) / 5 * 255;
+
+ return [r, g, b];
+};
+
+convert.rgb.hex = function (args) {
+ const integer = ((Math.round(args[0]) & 0xFF) << 16)
+ + ((Math.round(args[1]) & 0xFF) << 8)
+ + (Math.round(args[2]) & 0xFF);
+
+ const string = integer.toString(16).toUpperCase();
+ return '000000'.substring(string.length) + string;
+};
+
+convert.hex.rgb = function (args) {
+ const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
+ if (!match) {
+ return [0, 0, 0];
+ }
+
+ let colorString = match[0];
+
+ if (match[0].length === 3) {
+ colorString = colorString.split('').map(char => {
+ return char + char;
+ }).join('');
+ }
+
+ const integer = parseInt(colorString, 16);
+ const r = (integer >> 16) & 0xFF;
+ const g = (integer >> 8) & 0xFF;
+ const b = integer & 0xFF;
+
+ return [r, g, b];
+};
+
+convert.rgb.hcg = function (rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const max = Math.max(Math.max(r, g), b);
+ const min = Math.min(Math.min(r, g), b);
+ const chroma = (max - min);
+ let grayscale;
+ let hue;
+
+ if (chroma < 1) {
+ grayscale = min / (1 - chroma);
+ } else {
+ grayscale = 0;
+ }
+
+ if (chroma <= 0) {
+ hue = 0;
+ } else
+ if (max === r) {
+ hue = ((g - b) / chroma) % 6;
+ } else
+ if (max === g) {
+ hue = 2 + (b - r) / chroma;
+ } else {
+ hue = 4 + (r - g) / chroma;
+ }
+
+ hue /= 6;
+ hue %= 1;
+
+ return [hue * 360, chroma * 100, grayscale * 100];
+};
+
+convert.hsl.hcg = function (hsl) {
+ const s = hsl[1] / 100;
+ const l = hsl[2] / 100;
+
+ const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l));
+
+ let f = 0;
+ if (c < 1.0) {
+ f = (l - 0.5 * c) / (1.0 - c);
+ }
+
+ return [hsl[0], c * 100, f * 100];
+};
+
+convert.hsv.hcg = function (hsv) {
+ const s = hsv[1] / 100;
+ const v = hsv[2] / 100;
+
+ const c = s * v;
+ let f = 0;
+
+ if (c < 1.0) {
+ f = (v - c) / (1 - c);
+ }
+
+ return [hsv[0], c * 100, f * 100];
+};
+
+convert.hcg.rgb = function (hcg) {
+ const h = hcg[0] / 360;
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+
+ if (c === 0.0) {
+ return [g * 255, g * 255, g * 255];
+ }
+
+ const pure = [0, 0, 0];
+ const hi = (h % 1) * 6;
+ const v = hi % 1;
+ const w = 1 - v;
+ let mg = 0;
+
+ /* eslint-disable max-statements-per-line */
+ switch (Math.floor(hi)) {
+ case 0:
+ pure[0] = 1; pure[1] = v; pure[2] = 0; break;
+ case 1:
+ pure[0] = w; pure[1] = 1; pure[2] = 0; break;
+ case 2:
+ pure[0] = 0; pure[1] = 1; pure[2] = v; break;
+ case 3:
+ pure[0] = 0; pure[1] = w; pure[2] = 1; break;
+ case 4:
+ pure[0] = v; pure[1] = 0; pure[2] = 1; break;
+ default:
+ pure[0] = 1; pure[1] = 0; pure[2] = w;
+ }
+ /* eslint-enable max-statements-per-line */
+
+ mg = (1.0 - c) * g;
+
+ return [
+ (c * pure[0] + mg) * 255,
+ (c * pure[1] + mg) * 255,
+ (c * pure[2] + mg) * 255
+ ];
+};
+
+convert.hcg.hsv = function (hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+
+ const v = c + g * (1.0 - c);
+ let f = 0;
+
+ if (v > 0.0) {
+ f = c / v;
+ }
+
+ return [hcg[0], f * 100, v * 100];
+};
+
+convert.hcg.hsl = function (hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+
+ const l = g * (1.0 - c) + 0.5 * c;
+ let s = 0;
+
+ if (l > 0.0 && l < 0.5) {
+ s = c / (2 * l);
+ } else
+ if (l >= 0.5 && l < 1.0) {
+ s = c / (2 * (1 - l));
+ }
+
+ return [hcg[0], s * 100, l * 100];
+};
+
+convert.hcg.hwb = function (hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+ const v = c + g * (1.0 - c);
+ return [hcg[0], (v - c) * 100, (1 - v) * 100];
+};
+
+convert.hwb.hcg = function (hwb) {
+ const w = hwb[1] / 100;
+ const b = hwb[2] / 100;
+ const v = 1 - b;
+ const c = v - w;
+ let g = 0;
+
+ if (c < 1) {
+ g = (v - c) / (1 - c);
+ }
+
+ return [hwb[0], c * 100, g * 100];
+};
+
+convert.apple.rgb = function (apple) {
+ return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
+};
+
+convert.rgb.apple = function (rgb) {
+ return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
+};
+
+convert.gray.rgb = function (args) {
+ return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
+};
+
+convert.gray.hsl = function (args) {
+ return [0, 0, args[0]];
+};
+
+convert.gray.hsv = convert.gray.hsl;
+
+convert.gray.hwb = function (gray) {
+ return [0, 100, gray[0]];
+};
+
+convert.gray.cmyk = function (gray) {
+ return [0, 0, 0, gray[0]];
+};
+
+convert.gray.lab = function (gray) {
+ return [gray[0], 0, 0];
+};
+
+convert.gray.hex = function (gray) {
+ const val = Math.round(gray[0] / 100 * 255) & 0xFF;
+ const integer = (val << 16) + (val << 8) + val;
+
+ const string = integer.toString(16).toUpperCase();
+ return '000000'.substring(string.length) + string;
+};
+
+convert.rgb.gray = function (rgb) {
+ const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
+ return [val / 255 * 100];
+};
diff --git a/MistyCore/node_modules/color-convert/index.js b/MistyCore/node_modules/color-convert/index.js
new file mode 100644
index 0000000..b648e57
--- /dev/null
+++ b/MistyCore/node_modules/color-convert/index.js
@@ -0,0 +1,81 @@
+const conversions = require('./conversions');
+const route = require('./route');
+
+const convert = {};
+
+const models = Object.keys(conversions);
+
+function wrapRaw(fn) {
+ const wrappedFn = function (...args) {
+ const arg0 = args[0];
+ if (arg0 === undefined || arg0 === null) {
+ return arg0;
+ }
+
+ if (arg0.length > 1) {
+ args = arg0;
+ }
+
+ return fn(args);
+ };
+
+ // Preserve .conversion property if there is one
+ if ('conversion' in fn) {
+ wrappedFn.conversion = fn.conversion;
+ }
+
+ return wrappedFn;
+}
+
+function wrapRounded(fn) {
+ const wrappedFn = function (...args) {
+ const arg0 = args[0];
+
+ if (arg0 === undefined || arg0 === null) {
+ return arg0;
+ }
+
+ if (arg0.length > 1) {
+ args = arg0;
+ }
+
+ const result = fn(args);
+
+ // We're assuming the result is an array here.
+ // see notice in conversions.js; don't use box types
+ // in conversion functions.
+ if (typeof result === 'object') {
+ for (let len = result.length, i = 0; i < len; i++) {
+ result[i] = Math.round(result[i]);
+ }
+ }
+
+ return result;
+ };
+
+ // Preserve .conversion property if there is one
+ if ('conversion' in fn) {
+ wrappedFn.conversion = fn.conversion;
+ }
+
+ return wrappedFn;
+}
+
+models.forEach(fromModel => {
+ convert[fromModel] = {};
+
+ Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels});
+ Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels});
+
+ const routes = route(fromModel);
+ const routeModels = Object.keys(routes);
+
+ routeModels.forEach(toModel => {
+ const fn = routes[toModel];
+
+ convert[fromModel][toModel] = wrapRounded(fn);
+ convert[fromModel][toModel].raw = wrapRaw(fn);
+ });
+});
+
+module.exports = convert;
diff --git a/MistyCore/node_modules/color-convert/package.json b/MistyCore/node_modules/color-convert/package.json
new file mode 100644
index 0000000..6e48000
--- /dev/null
+++ b/MistyCore/node_modules/color-convert/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "color-convert",
+ "description": "Plain color conversion functions",
+ "version": "2.0.1",
+ "author": "Heather Arthur <fayearthur@gmail.com>",
+ "license": "MIT",
+ "repository": "Qix-/color-convert",
+ "scripts": {
+ "pretest": "xo",
+ "test": "node test/basic.js"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ },
+ "keywords": [
+ "color",
+ "colour",
+ "convert",
+ "converter",
+ "conversion",
+ "rgb",
+ "hsl",
+ "hsv",
+ "hwb",
+ "cmyk",
+ "ansi",
+ "ansi16"
+ ],
+ "files": [
+ "index.js",
+ "conversions.js",
+ "route.js"
+ ],
+ "xo": {
+ "rules": {
+ "default-case": 0,
+ "no-inline-comments": 0,
+ "operator-linebreak": 0
+ }
+ },
+ "devDependencies": {
+ "chalk": "^2.4.2",
+ "xo": "^0.24.0"
+ },
+ "dependencies": {
+ "color-name": "~1.1.4"
+ }
+}
diff --git a/MistyCore/node_modules/color-convert/route.js b/MistyCore/node_modules/color-convert/route.js
new file mode 100644
index 0000000..1a08521
--- /dev/null
+++ b/MistyCore/node_modules/color-convert/route.js
@@ -0,0 +1,97 @@
+const conversions = require('./conversions');
+
+/*
+ This function routes a model to all other models.
+
+ all functions that are routed have a property `.conversion` attached
+ to the returned synthetic function. This property is an array
+ of strings, each with the steps in between the 'from' and 'to'
+ color models (inclusive).
+
+ conversions that are not possible simply are not included.
+*/
+
+function buildGraph() {
+ const graph = {};
+ // https://jsperf.com/object-keys-vs-for-in-with-closure/3
+ const models = Object.keys(conversions);
+
+ for (let len = models.length, i = 0; i < len; i++) {
+ graph[models[i]] = {
+ // http://jsperf.com/1-vs-infinity
+ // micro-opt, but this is simple.
+ distance: -1,
+ parent: null
+ };
+ }
+
+ return graph;
+}
+
+// https://en.wikipedia.org/wiki/Breadth-first_search
+function deriveBFS(fromModel) {
+ const graph = buildGraph();
+ const queue = [fromModel]; // Unshift -> queue -> pop
+
+ graph[fromModel].distance = 0;
+
+ while (queue.length) {
+ const current = queue.pop();
+ const adjacents = Object.keys(conversions[current]);
+
+ for (let len = adjacents.length, i = 0; i < len; i++) {
+ const adjacent = adjacents[i];
+ const node = graph[adjacent];
+
+ if (node.distance === -1) {
+ node.distance = graph[current].distance + 1;
+ node.parent = current;
+ queue.unshift(adjacent);
+ }
+ }
+ }
+
+ return graph;
+}
+
+function link(from, to) {
+ return function (args) {
+ return to(from(args));
+ };
+}
+
+function wrapConversion(toModel, graph) {
+ const path = [graph[toModel].parent, toModel];
+ let fn = conversions[graph[toModel].parent][toModel];
+
+ let cur = graph[toModel].parent;
+ while (graph[cur].parent) {
+ path.unshift(graph[cur].parent);
+ fn = link(conversions[graph[cur].parent][cur], fn);
+ cur = graph[cur].parent;
+ }
+
+ fn.conversion = path;
+ return fn;
+}
+
+module.exports = function (fromModel) {
+ const graph = deriveBFS(fromModel);
+ const conversion = {};
+
+ const models = Object.keys(graph);
+ for (let len = models.length, i = 0; i < len; i++) {
+ const toModel = models[i];
+ const node = graph[toModel];
+
+ if (node.parent === null) {
+ // No possible conversion, or this node is the source model.
+ continue;
+ }
+
+ conversion[toModel] = wrapConversion(toModel, graph);
+ }
+
+ return conversion;
+};
+
diff --git a/MistyCore/node_modules/color-name/LICENSE b/MistyCore/node_modules/color-name/LICENSE
new file mode 100644
index 0000000..c6b1001
--- /dev/null
+++ b/MistyCore/node_modules/color-name/LICENSE
@@ -0,0 +1,8 @@
+The MIT License (MIT)
+Copyright (c) 2015 Dmitry Ivanov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/MistyCore/node_modules/color-name/README.md b/MistyCore/node_modules/color-name/README.md
new file mode 100644
index 0000000..932b979
--- /dev/null
+++ b/MistyCore/node_modules/color-name/README.md
@@ -0,0 +1,11 @@
+A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors.
+
+[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/)
+
+
+```js
+var colors = require('color-name');
+colors.red //[255,0,0]
+```
+
+<a href="LICENSE"><img src="https://upload.wikimedia.org/wikipedia/commons/0/0c/MIT_logo.svg" width="120"/></a>
diff --git a/MistyCore/node_modules/color-name/index.js b/MistyCore/node_modules/color-name/index.js
new file mode 100644
index 0000000..b7c198a
--- /dev/null
+++ b/MistyCore/node_modules/color-name/index.js
@@ -0,0 +1,152 @@
+'use strict'
+
+module.exports = {
+ "aliceblue": [240, 248, 255],
+ "antiquewhite": [250, 235, 215],
+ "aqua": [0, 255, 255],
+ "aquamarine": [127, 255, 212],
+ "azure": [240, 255, 255],
+ "beige": [245, 245, 220],
+ "bisque": [255, 228, 196],
+ "black": [0, 0, 0],
+ "blanchedalmond": [255, 235, 205],
+ "blue": [0, 0, 255],
+ "blueviolet": [138, 43, 226],
+ "brown": [165, 42, 42],
+ "burlywood": [222, 184, 135],
+ "cadetblue": [95, 158, 160],
+ "chartreuse": [127, 255, 0],
+ "chocolate": [210, 105, 30],
+ "coral": [255, 127, 80],
+ "cornflowerblue": [100, 149, 237],
+ "cornsilk": [255, 248, 220],
+ "crimson": [220, 20, 60],
+ "cyan": [0, 255, 255],
+ "darkblue": [0, 0, 139],
+ "darkcyan": [0, 139, 139],
+ "darkgoldenrod": [184, 134, 11],
+ "darkgray": [169, 169, 169],
+ "darkgreen": [0, 100, 0],
+ "darkgrey": [169, 169, 169],
+ "darkkhaki": [189, 183, 107],
+ "darkmagenta": [139, 0, 139],
+ "darkolivegreen": [85, 107, 47],
+ "darkorange": [255, 140, 0],
+ "darkorchid": [153, 50, 204],
+ "darkred": [139, 0, 0],
+ "darksalmon": [233, 150, 122],
+ "darkseagreen": [143, 188, 143],
+ "darkslateblue": [72, 61, 139],
+ "darkslategray": [47, 79, 79],
+ "darkslategrey": [47, 79, 79],
+ "darkturquoise": [0, 206, 209],
+ "darkviolet": [148, 0, 211],
+ "deeppink": [255, 20, 147],
+ "deepskyblue": [0, 191, 255],
+ "dimgray": [105, 105, 105],
+ "dimgrey": [105, 105, 105],
+ "dodgerblue": [30, 144, 255],
+ "firebrick": [178, 34, 34],
+ "floralwhite": [255, 250, 240],
+ "forestgreen": [34, 139, 34],
+ "fuchsia": [255, 0, 255],
+ "gainsboro": [220, 220, 220],
+ "ghostwhite": [248, 248, 255],
+ "gold": [255, 215, 0],
+ "goldenrod": [218, 165, 32],
+ "gray": [128, 128, 128],
+ "green": [0, 128, 0],
+ "greenyellow": [173, 255, 47],
+ "grey": [128, 128, 128],
+ "honeydew": [240, 255, 240],
+ "hotpink": [255, 105, 180],
+ "indianred": [205, 92, 92],
+ "indigo": [75, 0, 130],
+ "ivory": [255, 255, 240],
+ "khaki": [240, 230, 140],
+ "lavender": [230, 230, 250],
+ "lavenderblush": [255, 240, 245],
+ "lawngreen": [124, 252, 0],
+ "lemonchiffon": [255, 250, 205],
+ "lightblue": [173, 216, 230],
+ "lightcoral": [240, 128, 128],
+ "lightcyan": [224, 255, 255],
+ "lightgoldenrodyellow": [250, 250, 210],
+ "lightgray": [211, 211, 211],
+ "lightgreen": [144, 238, 144],
+ "lightgrey": [211, 211, 211],
+ "lightpink": [255, 182, 193],
+ "lightsalmon": [255, 160, 122],
+ "lightseagreen": [32, 178, 170],
+ "lightskyblue": [135, 206, 250],
+ "lightslategray": [119, 136, 153],
+ "lightslategrey": [119, 136, 153],
+ "lightsteelblue": [176, 196, 222],
+ "lightyellow": [255, 255, 224],
+ "lime": [0, 255, 0],
+ "limegreen": [50, 205, 50],
+ "linen": [250, 240, 230],
+ "magenta": [255, 0, 255],
+ "maroon": [128, 0, 0],
+ "mediumaquamarine": [102, 205, 170],
+ "mediumblue": [0, 0, 205],
+ "mediumorchid": [186, 85, 211],
+ "mediumpurple": [147, 112, 219],
+ "mediumseagreen": [60, 179, 113],
+ "mediumslateblue": [123, 104, 238],
+ "mediumspringgreen": [0, 250, 154],
+ "mediumturquoise": [72, 209, 204],
+ "mediumvioletred": [199, 21, 133],
+ "midnightblue": [25, 25, 112],
+ "mintcream": [245, 255, 250],
+ "mistyrose": [255, 228, 225],
+ "moccasin": [255, 228, 181],
+ "navajowhite": [255, 222, 173],
+ "navy": [0, 0, 128],
+ "oldlace": [253, 245, 230],
+ "olive": [128, 128, 0],
+ "olivedrab": [107, 142, 35],
+ "orange": [255, 165, 0],
+ "orangered": [255, 69, 0],
+ "orchid": [218, 112, 214],
+ "palegoldenrod": [238, 232, 170],
+ "palegreen": [152, 251, 152],
+ "paleturquoise": [175, 238, 238],
+ "palevioletred": [219, 112, 147],
+ "papayawhip": [255, 239, 213],
+ "peachpuff": [255, 218, 185],
+ "peru": [205, 133, 63],
+ "pink": [255, 192, 203],
+ "plum": [221, 160, 221],
+ "powderblue": [176, 224, 230],
+ "purple": [128, 0, 128],
+ "rebeccapurple": [102, 51, 153],
+ "red": [255, 0, 0],
+ "rosybrown": [188, 143, 143],
+ "royalblue": [65, 105, 225],
+ "saddlebrown": [139, 69, 19],
+ "salmon": [250, 128, 114],
+ "sandybrown": [244, 164, 96],
+ "seagreen": [46, 139, 87],
+ "seashell": [255, 245, 238],
+ "sienna": [160, 82, 45],
+ "silver": [192, 192, 192],
+ "skyblue": [135, 206, 235],
+ "slateblue": [106, 90, 205],
+ "slategray": [112, 128, 144],
+ "slategrey": [112, 128, 144],
+ "snow": [255, 250, 250],
+ "springgreen": [0, 255, 127],
+ "steelblue": [70, 130, 180],
+ "tan": [210, 180, 140],
+ "teal": [0, 128, 128],
+ "thistle": [216, 191, 216],
+ "tomato": [255, 99, 71],
+ "turquoise": [64, 224, 208],
+ "violet": [238, 130, 238],
+ "wheat": [245, 222, 179],
+ "white": [255, 255, 255],
+ "whitesmoke": [245, 245, 245],
+ "yellow": [255, 255, 0],
+ "yellowgreen": [154, 205, 50]
+};
diff --git a/MistyCore/node_modules/color-name/package.json b/MistyCore/node_modules/color-name/package.json
new file mode 100644
index 0000000..782dd82
--- /dev/null
+++ b/MistyCore/node_modules/color-name/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "color-name",
+ "version": "1.1.4",
+ "description": "A list of color names and its values",
+ "main": "index.js",
+ "files": [
+ "index.js"
+ ],
+ "scripts": {
+ "test": "node test.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:colorjs/color-name.git"
+ },
+ "keywords": [
+ "color-name",
+ "color",
+ "color-keyword",
+ "keyword"
+ ],
+ "author": "DY <dfcreative@gmail.com>",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/colorjs/color-name/issues"
+ },
+ "homepage": "https://github.com/colorjs/color-name"
+}
diff --git a/MistyCore/node_modules/has-flag/index.d.ts b/MistyCore/node_modules/has-flag/index.d.ts
new file mode 100644
index 0000000..a0a48c8
--- /dev/null
+++ b/MistyCore/node_modules/has-flag/index.d.ts
@@ -0,0 +1,39 @@
+/**
+Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag.
+
+@param flag - CLI flag to look for. The `--` prefix is optional.
+@param argv - CLI arguments. Default: `process.argv`.
+@returns Whether the flag exists.
+
+@example
+```
+// $ ts-node foo.ts -f --unicorn --foo=bar -- --rainbow
+
+// foo.ts
+import hasFlag = require('has-flag');
+
+hasFlag('unicorn');
+//=> true
+
+hasFlag('--unicorn');
+//=> true
+
+hasFlag('f');
+//=> true
+
+hasFlag('-f');
+//=> true
+
+hasFlag('foo=bar');
+//=> true
+
+hasFlag('foo');
+//=> false
+
+hasFlag('rainbow');
+//=> false
+```
+*/
+declare function hasFlag(flag: string, argv?: string[]): boolean;
+
+export = hasFlag;
diff --git a/MistyCore/node_modules/has-flag/index.js b/MistyCore/node_modules/has-flag/index.js
new file mode 100644
index 0000000..b6f80b1
--- /dev/null
+++ b/MistyCore/node_modules/has-flag/index.js
@@ -0,0 +1,8 @@
+'use strict';
+
+module.exports = (flag, argv = process.argv) => {
+ const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
+ const position = argv.indexOf(prefix + flag);
+ const terminatorPosition = argv.indexOf('--');
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
+};
diff --git a/MistyCore/node_modules/has-flag/license b/MistyCore/node_modules/has-flag/license
new file mode 100644
index 0000000..e7af2f7
--- /dev/null
+++ b/MistyCore/node_modules/has-flag/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MistyCore/node_modules/has-flag/package.json b/MistyCore/node_modules/has-flag/package.json
new file mode 100644
index 0000000..a9cba4b
--- /dev/null
+++ b/MistyCore/node_modules/has-flag/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "has-flag",
+ "version": "4.0.0",
+ "description": "Check if argv has a specific flag",
+ "license": "MIT",
+ "repository": "sindresorhus/has-flag",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "scripts": {
+ "test": "xo && ava && tsd"
+ },
+ "files": [
+ "index.js",
+ "index.d.ts"
+ ],
+ "keywords": [
+ "has",
+ "check",
+ "detect",
+ "contains",
+ "find",
+ "flag",
+ "cli",
+ "command-line",
+ "argv",
+ "process",
+ "arg",
+ "args",
+ "argument",
+ "arguments",
+ "getopt",
+ "minimist",
+ "optimist"
+ ],
+ "devDependencies": {
+ "ava": "^1.4.1",
+ "tsd": "^0.7.2",
+ "xo": "^0.24.0"
+ }
+}
diff --git a/MistyCore/node_modules/has-flag/readme.md b/MistyCore/node_modules/has-flag/readme.md
new file mode 100644
index 0000000..3f72dff
--- /dev/null
+++ b/MistyCore/node_modules/has-flag/readme.md
@@ -0,0 +1,89 @@
+# has-flag [![Build Status](https://travis-ci.org/sindresorhus/has-flag.svg?branch=master)](https://travis-ci.org/sindresorhus/has-flag)
+
+> Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag
+
+Correctly stops looking after an `--` argument terminator.
+
+---
+
+<div align="center">
+ <b>
+ <a href="https://tidelift.com/subscription/pkg/npm-has-flag?utm_source=npm-has-flag&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
+ </b>
+ <br>
+ <sub>
+ Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
+ </sub>
+</div>
+
+---
+
+
+## Install
+
+```
+$ npm install has-flag
+```
+
+
+## Usage
+
+```js
+// foo.js
+const hasFlag = require('has-flag');
+
+hasFlag('unicorn');
+//=> true
+
+hasFlag('--unicorn');
+//=> true
+
+hasFlag('f');
+//=> true
+
+hasFlag('-f');
+//=> true
+
+hasFlag('foo=bar');
+//=> true
+
+hasFlag('foo');
+//=> false
+
+hasFlag('rainbow');
+//=> false
+```
+
+```
+$ node foo.js -f --unicorn --foo=bar -- --rainbow
+```
+
+
+## API
+
+### hasFlag(flag, [argv])
+
+Returns a boolean for whether the flag exists.
+
+#### flag
+
+Type: `string`
+
+CLI flag to look for. The `--` prefix is optional.
+
+#### argv
+
+Type: `string[]`<br>
+Default: `process.argv`
+
+CLI arguments.
+
+
+## Security
+
+To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/MistyCore/node_modules/lru-cache/LICENSE b/MistyCore/node_modules/lru-cache/LICENSE
new file mode 100644
index 0000000..19129e3
--- /dev/null
+++ b/MistyCore/node_modules/lru-cache/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/MistyCore/node_modules/lru-cache/README.md b/MistyCore/node_modules/lru-cache/README.md
new file mode 100644
index 0000000..435dfeb
--- /dev/null
+++ b/MistyCore/node_modules/lru-cache/README.md
@@ -0,0 +1,166 @@
+# lru cache
+
+A cache object that deletes the least-recently-used items.
+
+[![Build Status](https://travis-ci.org/isaacs/node-lru-cache.svg?branch=master)](https://travis-ci.org/isaacs/node-lru-cache) [![Coverage Status](https://coveralls.io/repos/isaacs/node-lru-cache/badge.svg?service=github)](https://coveralls.io/github/isaacs/node-lru-cache)
+
+## Installation:
+
+```javascript
+npm install lru-cache --save
+```
+
+## Usage:
+
+```javascript
+var LRU = require("lru-cache")
+ , options = { max: 500
+ , length: function (n, key) { return n * 2 + key.length }
+ , dispose: function (key, n) { n.close() }
+ , maxAge: 1000 * 60 * 60 }
+ , cache = new LRU(options)
+ , otherCache = new LRU(50) // sets just the max size
+
+cache.set("key", "value")
+cache.get("key") // "value"
+
+// non-string keys ARE fully supported
+// but note that it must be THE SAME object, not
+// just a JSON-equivalent object.
+var someObject = { a: 1 }
+cache.set(someObject, 'a value')
+// Object keys are not toString()-ed
+cache.set('[object Object]', 'a different value')
+assert.equal(cache.get(someObject), 'a value')
+// A similar object with same keys/values won't work,
+// because it's a different object identity
+assert.equal(cache.get({ a: 1 }), undefined)
+
+cache.reset() // empty the cache
+```
+
+If you put more stuff in it, then items will fall out.
+
+If you try to put an oversized thing in it, then it'll fall out right
+away.
+
+## Options
+
+* `max` The maximum size of the cache, checked by applying the length
+ function to all values in the cache. Not setting this is kind of
+ silly, since that's the whole purpose of this lib, but it defaults
+ to `Infinity`. Setting it to a non-number or negative number will
+ throw a `TypeError`. Setting it to 0 makes it be `Infinity`.
+* `maxAge` Maximum age in ms. Items are not pro-actively pruned out
+ as they age, but if you try to get an item that is too old, it'll
+ drop it and return undefined instead of giving it to you.
+ Setting this to a negative value will make everything seem old!
+ Setting it to a non-number will throw a `TypeError`.
+* `length` Function that is used to calculate the length of stored
+ items. If you're storing strings or buffers, then you probably want
+ to do something like `function(n, key){return n.length}`. The default is
+ `function(){return 1}`, which is fine if you want to store `max`
+ like-sized things. The item is passed as the first argument, and
+ the key is passed as the second argumnet.
+* `dispose` Function that is called on items when they are dropped
+ from the cache. This can be handy if you want to close file
+ descriptors or do other cleanup tasks when items are no longer
+ accessible. Called with `key, value`. It's called *before*
+ actually removing the item from the internal cache, so if you want
+ to immediately put it back in, you'll have to do that in a
+ `nextTick` or `setTimeout` callback or it won't do anything.
+* `stale` By default, if you set a `maxAge`, it'll only actually pull
+ stale items out of the cache when you `get(key)`. (That is, it's
+ not pre-emptively doing a `setTimeout` or anything.) If you set
+ `stale:true`, it'll return the stale value before deleting it. If
+ you don't set this, then it'll return `undefined` when you try to
+ get a stale entry, as if it had already been deleted.
+* `noDisposeOnSet` By default, if you set a `dispose()` method, then
+ it'll be called whenever a `set()` operation overwrites an existing
+ key. If you set this option, `dispose()` will only be called when a
+ key falls out of the cache, not when it is overwritten.
+* `updateAgeOnGet` When using time-expiring entries with `maxAge`,
+ setting this to `true` will make each item's effective time update
+ to the current time whenever it is retrieved from cache, causing it
+ to not expire. (It can still fall out of cache based on recency of
+ use, of course.)
+
+## API
+
+* `set(key, value, maxAge)`
+* `get(key) => value`
+
+ Both of these will update the "recently used"-ness of the key.
+ They do what you think. `maxAge` is optional and overrides the
+ cache `maxAge` option if provided.
+
+ If the key is not found, `get()` will return `undefined`.
+
+ The key and val can be any value.
+
+* `peek(key)`
+
+ Returns the key value (or `undefined` if not found) without
+ updating the "recently used"-ness of the key.
+
+ (If you find yourself using this a lot, you *might* be using the
+ wrong sort of data structure, but there are some use cases where
+ it's handy.)
+
+* `del(key)`
+
+ Deletes a key out of the cache.
+
+* `reset()`
+
+ Clear the cache entirely, throwing away all values.
+
+* `has(key)`
+
+ Check if a key is in the cache, without updating the recent-ness
+ or deleting it for being stale.
+
+* `forEach(function(value,key,cache), [thisp])`
+
+ Just like `Array.prototype.forEach`. Iterates over all the keys
+ in the cache, in order of recent-ness. (Ie, more recently used
+ items are iterated over first.)
+
+* `rforEach(function(value,key,cache), [thisp])`
+
+ The same as `cache.forEach(...)` but items are iterated over in
+ reverse order. (ie, less recently used items are iterated over
+ first.)
+
+* `keys()`
+
+ Return an array of the keys in the cache.
+
+* `values()`
+
+ Return an array of the values in the cache.
+
+* `length`
+
+ Return total length of objects in cache taking into account
+ `length` options function.
+
+* `itemCount`
+
+ Return total quantity of objects currently in cache. Note, that
+ `stale` (see options) items are returned as part of this item
+ count.
+
+* `dump()`
+
+ Return an array of the cache entries ready for serialization and usage
+ with 'destinationCache.load(arr)`.
+
+* `load(cacheEntriesArray)`
+
+ Loads another cache entries array, obtained with `sourceCache.dump()`,
+ into the cache. The destination cache is reset before loading new entries
+
+* `prune()`
+
+ Manually iterates over the entire cache proactively pruning old entries
diff --git a/MistyCore/node_modules/lru-cache/index.js b/MistyCore/node_modules/lru-cache/index.js
new file mode 100644
index 0000000..573b6b8
--- /dev/null
+++ b/MistyCore/node_modules/lru-cache/index.js
@@ -0,0 +1,334 @@
+'use strict'
+
+// A linked list to keep track of recently-used-ness
+const Yallist = require('yallist')
+
+const MAX = Symbol('max')
+const LENGTH = Symbol('length')
+const LENGTH_CALCULATOR = Symbol('lengthCalculator')
+const ALLOW_STALE = Symbol('allowStale')
+const MAX_AGE = Symbol('maxAge')
+const DISPOSE = Symbol('dispose')
+const NO_DISPOSE_ON_SET = Symbol('noDisposeOnSet')
+const LRU_LIST = Symbol('lruList')
+const CACHE = Symbol('cache')
+const UPDATE_AGE_ON_GET = Symbol('updateAgeOnGet')
+
+const naiveLength = () => 1
+
+// lruList is a yallist where the head is the youngest
+// item, and the tail is the oldest. the list contains the Hit
+// objects as the entries.
+// Each Hit object has a reference to its Yallist.Node. This
+// never changes.
+//
+// cache is a Map (or PseudoMap) that matches the keys to
+// the Yallist.Node object.
+class LRUCache {
+ constructor (options) {
+ if (typeof options === 'number')
+ options = { max: options }
+
+ if (!options)
+ options = {}
+
+ if (options.max && (typeof options.max !== 'number' || options.max < 0))
+ throw new TypeError('max must be a non-negative number')
+ // Kind of weird to have a default max of Infinity, but oh well.
+ const max = this[MAX] = options.max || Infinity
+
+ const lc = options.length || naiveLength
+ this[LENGTH_CALCULATOR] = (typeof lc !== 'function') ? naiveLength : lc
+ this[ALLOW_STALE] = options.stale || false
+ if (options.maxAge && typeof options.maxAge !== 'number')
+ throw new TypeError('maxAge must be a number')
+ this[MAX_AGE] = options.maxAge || 0
+ this[DISPOSE] = options.dispose
+ this[NO_DISPOSE_ON_SET] = options.noDisposeOnSet || false
+ this[UPDATE_AGE_ON_GET] = options.updateAgeOnGet || false
+ this.reset()
+ }
+
+ // resize the cache when the max changes.
+ set max (mL) {
+ if (typeof mL !== 'number' || mL < 0)
+ throw new TypeError('max must be a non-negative number')
+
+ this[MAX] = mL || Infinity
+ trim(this)
+ }
+ get max () {
+ return this[MAX]
+ }
+
+ set allowStale (allowStale) {
+ this[ALLOW_STALE] = !!allowStale
+ }
+ get allowStale () {
+ return this[ALLOW_STALE]
+ }
+
+ set maxAge (mA) {
+ if (typeof mA !== 'number')
+ throw new TypeError('maxAge must be a non-negative number')
+
+ this[MAX_AGE] = mA
+ trim(this)
+ }
+ get maxAge () {
+ return this[MAX_AGE]
+ }
+
+ // resize the cache when the lengthCalculator changes.
+ set lengthCalculator (lC) {
+ if (typeof lC !== 'function')
+ lC = naiveLength
+
+ if (lC !== this[LENGTH_CALCULATOR]) {
+ this[LENGTH_CALCULATOR] = lC
+ this[LENGTH] = 0
+ this[LRU_LIST].forEach(hit => {
+ hit.length = this[LENGTH_CALCULATOR](hit.value, hit.key)
+ this[LENGTH] += hit.length
+ })
+ }
+ trim(this)
+ }
+ get lengthCalculator () { return this[LENGTH_CALCULATOR] }
+
+ get length () { return this[LENGTH] }
+ get itemCount () { return this[LRU_LIST].length }
+
+ rforEach (fn, thisp) {
+ thisp = thisp || this
+ for (let walker = this[LRU_LIST].tail; walker !== null;) {
+ const prev = walker.prev
+ forEachStep(this, fn, walker, thisp)
+ walker = prev
+ }
+ }
+
+ forEach (fn, thisp) {
+ thisp = thisp || this
+ for (let walker = this[LRU_LIST].head; walker !== null;) {
+ const next = walker.next
+ forEachStep(this, fn, walker, thisp)
+ walker = next
+ }
+ }
+
+ keys () {
+ return this[LRU_LIST].toArray().map(k => k.key)
+ }
+
+ values () {
+ return this[LRU_LIST].toArray().map(k => k.value)
+ }
+
+ reset () {
+ if (this[DISPOSE] &&
+ this[LRU_LIST] &&
+ this[LRU_LIST].length) {
+ this[LRU_LIST].forEach(hit => this[DISPOSE](hit.key, hit.value))
+ }
+
+ this[CACHE] = new Map() // hash of items by key
+ this[LRU_LIST] = new Yallist() // list of items in order of use recency
+ this[LENGTH] = 0 // length of items in the list
+ }
+
+ dump () {
+ return this[LRU_LIST].map(hit =>
+ isStale(this, hit) ? false : {
+ k: hit.key,
+ v: hit.value,
+ e: hit.now + (hit.maxAge || 0)
+ }).toArray().filter(h => h)
+ }
+
+ dumpLru () {
+ return this[LRU_LIST]
+ }
+
+ set (key, value, maxAge) {
+ maxAge = maxAge || this[MAX_AGE]
+
+ if (maxAge && typeof maxAge !== 'number')
+ throw new TypeError('maxAge must be a number')
+
+ const now = maxAge ? Date.now() : 0
+ const len = this[LENGTH_CALCULATOR](value, key)
+
+ if (this[CACHE].has(key)) {
+ if (len > this[MAX]) {
+ del(this, this[CACHE].get(key))
+ return false
+ }
+
+ const node = this[CACHE].get(key)
+ const item = node.value
+
+ // dispose of the old one before overwriting
+ // split out into 2 ifs for better coverage tracking
+ if (this[DISPOSE]) {
+ if (!this[NO_DISPOSE_ON_SET])
+ this[DISPOSE](key, item.value)
+ }
+
+ item.now = now
+ item.maxAge = maxAge
+ item.value = value
+ this[LENGTH] += len - item.length
+ item.length = len
+ this.get(key)
+ trim(this)
+ return true
+ }
+
+ const hit = new Entry(key, value, len, now, maxAge)
+
+ // oversized objects fall out of cache automatically.
+ if (hit.length > this[MAX]) {
+ if (this[DISPOSE])
+ this[DISPOSE](key, value)
+
+ return false
+ }
+
+ this[LENGTH] += hit.length
+ this[LRU_LIST].unshift(hit)
+ this[CACHE].set(key, this[LRU_LIST].head)
+ trim(this)
+ return true
+ }
+
+ has (key) {
+ if (!this[CACHE].has(key)) return false
+ const hit = this[CACHE].get(key).value
+ return !isStale(this, hit)
+ }
+
+ get (key) {
+ return get(this, key, true)
+ }
+
+ peek (key) {
+ return get(this, key, false)
+ }
+
+ pop () {
+ const node = this[LRU_LIST].tail
+ if (!node)
+ return null
+
+ del(this, node)
+ return node.value
+ }
+
+ del (key) {
+ del(this, this[CACHE].get(key))
+ }
+
+ load (arr) {
+ // reset the cache
+ this.reset()
+
+ const now = Date.now()
+ // A previous serialized cache has the most recent items first
+ for (let l = arr.length - 1; l >= 0; l--) {
+ const hit = arr[l]
+ const expiresAt = hit.e || 0
+ if (expiresAt === 0)
+ // the item was created without expiration in a non aged cache
+ this.set(hit.k, hit.v)
+ else {
+ const maxAge = expiresAt - now
+ // dont add already expired items
+ if (maxAge > 0) {
+ this.set(hit.k, hit.v, maxAge)
+ }
+ }
+ }
+ }
+
+ prune () {
+ this[CACHE].forEach((value, key) => get(this, key, false))
+ }
+}
+
+const get = (self, key, doUse) => {
+ const node = self[CACHE].get(key)
+ if (node) {
+ const hit = node.value
+ if (isStale(self, hit)) {
+ del(self, node)
+ if (!self[ALLOW_STALE])
+ return undefined
+ } else {
+ if (doUse) {
+ if (self[UPDATE_AGE_ON_GET])
+ node.value.now = Date.now()
+ self[LRU_LIST].unshiftNode(node)
+ }
+ }
+ return hit.value
+ }
+}
+
+const isStale = (self, hit) => {
+ if (!hit || (!hit.maxAge && !self[MAX_AGE]))
+ return false
+
+ const diff = Date.now() - hit.now
+ return hit.maxAge ? diff > hit.maxAge
+ : self[MAX_AGE] && (diff > self[MAX_AGE])
+}
+
+const trim = self => {
+ if (self[LENGTH] > self[MAX]) {
+ for (let walker = self[LRU_LIST].tail;
+ self[LENGTH] > self[MAX] && walker !== null;) {
+ // We know that we're about to delete this one, and also
+ // what the next least recently used key will be, so just
+ // go ahead and set it now.
+ const prev = walker.prev
+ del(self, walker)
+ walker = prev
+ }
+ }
+}
+
+const del = (self, node) => {
+ if (node) {
+ const hit = node.value
+ if (self[DISPOSE])
+ self[DISPOSE](hit.key, hit.value)
+
+ self[LENGTH] -= hit.length
+ self[CACHE].delete(hit.key)
+ self[LRU_LIST].removeNode(node)
+ }
+}
+
+class Entry {
+ constructor (key, value, length, now, maxAge) {
+ this.key = key
+ this.value = value
+ this.length = length
+ this.now = now
+ this.maxAge = maxAge || 0
+ }
+}
+
+const forEachStep = (self, fn, node, thisp) => {
+ let hit = node.value
+ if (isStale(self, hit)) {
+ del(self, node)
+ if (!self[ALLOW_STALE])
+ hit = undefined
+ }
+ if (hit)
+ fn.call(thisp, hit.value, hit.key, self)
+}
+
+module.exports = LRUCache
diff --git a/MistyCore/node_modules/lru-cache/package.json b/MistyCore/node_modules/lru-cache/package.json
new file mode 100644
index 0000000..43b7502
--- /dev/null
+++ b/MistyCore/node_modules/lru-cache/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "lru-cache",
+ "description": "A cache object that deletes the least-recently-used items.",
+ "version": "6.0.0",
+ "author": "Isaac Z. Schlueter <i@izs.me>",
+ "keywords": [
+ "mru",
+ "lru",
+ "cache"
+ ],
+ "scripts": {
+ "test": "tap",
+ "snap": "tap",
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "prepublishOnly": "git push origin --follow-tags"
+ },
+ "main": "index.js",
+ "repository": "git://github.com/isaacs/node-lru-cache.git",
+ "devDependencies": {
+ "benchmark": "^2.1.4",
+ "tap": "^14.10.7"
+ },
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "files": [
+ "index.js"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+}
diff --git a/MistyCore/node_modules/semver/LICENSE b/MistyCore/node_modules/semver/LICENSE
new file mode 100644
index 0000000..19129e3
--- /dev/null
+++ b/MistyCore/node_modules/semver/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/MistyCore/node_modules/semver/README.md b/MistyCore/node_modules/semver/README.md
new file mode 100644
index 0000000..df54e7a
--- /dev/null
+++ b/MistyCore/node_modules/semver/README.md
@@ -0,0 +1,568 @@
+semver(1) -- The semantic versioner for npm
+===========================================
+
+## Install
+
+```bash
+npm install semver
+````
+
+## Usage
+
+As a node module:
+
+```js
+const semver = require('semver')
+
+semver.valid('1.2.3') // '1.2.3'
+semver.valid('a.b.c') // null
+semver.clean(' =v1.2.3 ') // '1.2.3'
+semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
+semver.gt('1.2.3', '9.8.7') // false
+semver.lt('1.2.3', '9.8.7') // true
+semver.minVersion('>=1.0.0') // '1.0.0'
+semver.valid(semver.coerce('v2')) // '2.0.0'
+semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
+```
+
+You can also just load the module for the function that you care about, if
+you'd like to minimize your footprint.
+
+```js
+// load the whole API at once in a single object
+const semver = require('semver')
+
+// or just load the bits you need
+// all of them listed here, just pick and choose what you want
+
+// classes
+const SemVer = require('semver/classes/semver')
+const Comparator = require('semver/classes/comparator')
+const Range = require('semver/classes/range')
+
+// functions for working with versions
+const semverParse = require('semver/functions/parse')
+const semverValid = require('semver/functions/valid')
+const semverClean = require('semver/functions/clean')
+const semverInc = require('semver/functions/inc')
+const semverDiff = require('semver/functions/diff')
+const semverMajor = require('semver/functions/major')
+const semverMinor = require('semver/functions/minor')
+const semverPatch = require('semver/functions/patch')
+const semverPrerelease = require('semver/functions/prerelease')
+const semverCompare = require('semver/functions/compare')
+const semverRcompare = require('semver/functions/rcompare')
+const semverCompareLoose = require('semver/functions/compare-loose')
+const semverCompareBuild = require('semver/functions/compare-build')
+const semverSort = require('semver/functions/sort')
+const semverRsort = require('semver/functions/rsort')
+
+// low-level comparators between versions
+const semverGt = require('semver/functions/gt')
+const semverLt = require('semver/functions/lt')
+const semverEq = require('semver/functions/eq')
+const semverNeq = require('semver/functions/neq')
+const semverGte = require('semver/functions/gte')
+const semverLte = require('semver/functions/lte')
+const semverCmp = require('semver/functions/cmp')
+const semverCoerce = require('semver/functions/coerce')
+
+// working with ranges
+const semverSatisfies = require('semver/functions/satisfies')
+const semverMaxSatisfying = require('semver/ranges/max-satisfying')
+const semverMinSatisfying = require('semver/ranges/min-satisfying')
+const semverToComparators = require('semver/ranges/to-comparators')
+const semverMinVersion = require('semver/ranges/min-version')
+const semverValidRange = require('semver/ranges/valid')
+const semverOutside = require('semver/ranges/outside')
+const semverGtr = require('semver/ranges/gtr')
+const semverLtr = require('semver/ranges/ltr')
+const semverIntersects = require('semver/ranges/intersects')
+const simplifyRange = require('semver/ranges/simplify')
+const rangeSubset = require('semver/ranges/subset')
+```
+
+As a command-line utility:
+
+```
+$ semver -h
+
+A JavaScript implementation of the https://semver.org/ specification
+Copyright Isaac Z. Schlueter
+
+Usage: semver [options] <version> [<version> [...]]
+Prints valid versions sorted by SemVer precedence
+
+Options:
+-r --range <range>
+ Print versions that match the specified range.
+
+-i --increment [<level>]
+ Increment a version by the specified level. Level can
+ be one of: major, minor, patch, premajor, preminor,
+ prepatch, or prerelease. Default level is 'patch'.
+ Only one version may be specified.
+
+--preid <identifier>
+ Identifier to be used to prefix premajor, preminor,
+ prepatch or prerelease version increments.
+
+-l --loose
+ Interpret versions and ranges loosely
+
+-p --include-prerelease
+ Always include prerelease versions in range matching
+
+-c --coerce
+ Coerce a string into SemVer if possible
+ (does not imply --loose)
+
+--rtl
+ Coerce version strings right to left
+
+--ltr
+ Coerce version strings left to right (default)
+
+Program exits successfully if any valid version satisfies
+all supplied ranges, and prints all satisfying versions.
+
+If no satisfying versions are found, then exits failure.
+
+Versions are printed in ascending order, so supplying
+multiple versions to the utility will just sort them.
+```
+
+## Versions
+
+A "version" is described by the `v2.0.0` specification found at
+<https://semver.org/>.
+
+A leading `"="` or `"v"` character is stripped off and ignored.
+
+## Ranges
+
+A `version range` is a set of `comparators` which specify versions
+that satisfy the range.
+
+A `comparator` is composed of an `operator` and a `version`. The set
+of primitive `operators` is:
+
+* `<` Less than
+* `<=` Less than or equal to
+* `>` Greater than
+* `>=` Greater than or equal to
+* `=` Equal. If no operator is specified, then equality is assumed,
+ so this operator is optional, but MAY be included.
+
+For example, the comparator `>=1.2.7` would match the versions
+`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6`
+or `1.1.0`.
+
+Comparators can be joined by whitespace to form a `comparator set`,
+which is satisfied by the **intersection** of all of the comparators
+it includes.
+
+A range is composed of one or more comparator sets, joined by `||`. A
+version matches a range if and only if every comparator in at least
+one of the `||`-separated comparator sets is satisfied by the version.
+
+For example, the range `>=1.2.7 <1.3.0` would match the versions
+`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`,
+or `1.1.0`.
+
+The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`,
+`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`.
+
+### Prerelease Tags
+
+If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then
+it will only be allowed to satisfy comparator sets if at least one
+comparator with the same `[major, minor, patch]` tuple also has a
+prerelease tag.
+
+For example, the range `>1.2.3-alpha.3` would be allowed to match the
+version `1.2.3-alpha.7`, but it would *not* be satisfied by
+`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater
+than" `1.2.3-alpha.3` according to the SemVer sort rules. The version
+range only accepts prerelease tags on the `1.2.3` version. The
+version `3.4.5` *would* satisfy the range, because it does not have a
+prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`.
+
+The purpose for this behavior is twofold. First, prerelease versions
+frequently are updated very quickly, and contain many breaking changes
+that are (by the author's design) not yet fit for public consumption.
+Therefore, by default, they are excluded from range matching
+semantics.
+
+Second, a user who has opted into using a prerelease version has
+clearly indicated the intent to use *that specific* set of
+alpha/beta/rc versions. By including a prerelease tag in the range,
+the user is indicating that they are aware of the risk. However, it
+is still not appropriate to assume that they have opted into taking a
+similar risk on the *next* set of prerelease versions.
+
+Note that this behavior can be suppressed (treating all prerelease
+versions as if they were normal versions, for the purpose of range
+matching) by setting the `includePrerelease` flag on the options
+object to any
+[functions](https://github.com/npm/node-semver#functions) that do
+range matching.
+
+#### Prerelease Identifiers
+
+The method `.inc` takes an additional `identifier` string argument that
+will append the value of the string as a prerelease identifier:
+
+```javascript
+semver.inc('1.2.3', 'prerelease', 'beta')
+// '1.2.4-beta.0'
+```
+
+command-line example:
+
+```bash
+$ semver 1.2.3 -i prerelease --preid beta
+1.2.4-beta.0
+```
+
+Which then can be used to increment further:
+
+```bash
+$ semver 1.2.4-beta.0 -i prerelease
+1.2.4-beta.1
+```
+
+### Advanced Range Syntax
+
+Advanced range syntax desugars to primitive comparators in
+deterministic ways.
+
+Advanced ranges may be combined in the same way as primitive
+comparators using white space or `||`.
+
+#### Hyphen Ranges `X.Y.Z - A.B.C`
+
+Specifies an inclusive set.
+
+* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`
+
+If a partial version is provided as the first version in the inclusive
+range, then the missing pieces are replaced with zeroes.
+
+* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4`
+
+If a partial version is provided as the second version in the
+inclusive range, then all versions that start with the supplied parts
+of the tuple are accepted, but nothing that would be greater than the
+provided tuple parts.
+
+* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0-0`
+* `1.2.3 - 2` := `>=1.2.3 <3.0.0-0`
+
+#### X-Ranges `1.2.x` `1.X` `1.2.*` `*`
+
+Any of `X`, `x`, or `*` may be used to "stand in" for one of the
+numeric values in the `[major, minor, patch]` tuple.
+
+* `*` := `>=0.0.0` (Any non-prerelease version satisfies, unless
+ `includePrerelease` is specified, in which case any version at all
+ satisfies)
+* `1.x` := `>=1.0.0 <2.0.0-0` (Matching major version)
+* `1.2.x` := `>=1.2.0 <1.3.0-0` (Matching major and minor versions)
+
+A partial version range is treated as an X-Range, so the special
+character is in fact optional.
+
+* `""` (empty string) := `*` := `>=0.0.0`
+* `1` := `1.x.x` := `>=1.0.0 <2.0.0-0`
+* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0-0`
+
+#### Tilde Ranges `~1.2.3` `~1.2` `~1`
+
+Allows patch-level changes if a minor version is specified on the
+comparator. Allows minor-level changes if not.
+
+* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0-0`
+* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0-0` (Same as `1.2.x`)
+* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0-0` (Same as `1.x`)
+* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0-0`
+* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0-0` (Same as `0.2.x`)
+* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0-0` (Same as `0.x`)
+* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0-0` Note that prereleases in
+ the `1.2.3` version will be allowed, if they are greater than or
+ equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
+ `1.2.4-beta.2` would not, because it is a prerelease of a
+ different `[major, minor, patch]` tuple.
+
+#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4`
+
+Allows changes that do not modify the left-most non-zero element in the
+`[major, minor, patch]` tuple. In other words, this allows patch and
+minor updates for versions `1.0.0` and above, patch updates for
+versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`.
+
+Many authors treat a `0.x` version as if the `x` were the major
+"breaking-change" indicator.
+
+Caret ranges are ideal when an author may make breaking changes
+between `0.2.4` and `0.3.0` releases, which is a common practice.
+However, it presumes that there will *not* be breaking changes between
+`0.2.4` and `0.2.5`. It allows for changes that are presumed to be
+additive (but non-breaking), according to commonly observed practices.
+
+* `^1.2.3` := `>=1.2.3 <2.0.0-0`
+* `^0.2.3` := `>=0.2.3 <0.3.0-0`
+* `^0.0.3` := `>=0.0.3 <0.0.4-0`
+* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0-0` Note that prereleases in
+ the `1.2.3` version will be allowed, if they are greater than or
+ equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
+ `1.2.4-beta.2` would not, because it is a prerelease of a
+ different `[major, minor, patch]` tuple.
+* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4-0` Note that prereleases in the
+ `0.0.3` version *only* will be allowed, if they are greater than or
+ equal to `beta`. So, `0.0.3-pr.2` would be allowed.
+
+When parsing caret ranges, a missing `patch` value desugars to the
+number `0`, but will allow flexibility within that value, even if the
+major and minor versions are both `0`.
+
+* `^1.2.x` := `>=1.2.0 <2.0.0-0`
+* `^0.0.x` := `>=0.0.0 <0.1.0-0`
+* `^0.0` := `>=0.0.0 <0.1.0-0`
+
+A missing `minor` and `patch` values will desugar to zero, but also
+allow flexibility within those values, even if the major version is
+zero.
+
+* `^1.x` := `>=1.0.0 <2.0.0-0`
+* `^0.x` := `>=0.0.0 <1.0.0-0`
+
+### Range Grammar
+
+Putting all this together, here is a Backus-Naur grammar for ranges,
+for the benefit of parser authors:
+
+```bnf
+range-set ::= range ( logical-or range ) *
+logical-or ::= ( ' ' ) * '||' ( ' ' ) *
+range ::= hyphen | simple ( ' ' simple ) * | ''
+hyphen ::= partial ' - ' partial
+simple ::= primitive | partial | tilde | caret
+primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
+partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
+xr ::= 'x' | 'X' | '*' | nr
+nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) *
+tilde ::= '~' partial
+caret ::= '^' partial
+qualifier ::= ( '-' pre )? ( '+' build )?
+pre ::= parts
+build ::= parts
+parts ::= part ( '.' part ) *
+part ::= nr | [-0-9A-Za-z]+
+```
+
+## Functions
+
+All methods and classes take a final `options` object argument. All
+options in this object are `false` by default. The options supported
+are:
+
+- `loose` Be more forgiving about not-quite-valid semver strings.
+ (Any resulting output will always be 100% strict compliant, of
+ course.) For backwards compatibility reasons, if the `options`
+ argument is a boolean value instead of an object, it is interpreted
+ to be the `loose` param.
+- `includePrerelease` Set to suppress the [default
+ behavior](https://github.com/npm/node-semver#prerelease-tags) of
+ excluding prerelease tagged versions from ranges unless they are
+ explicitly opted into.
+
+Strict-mode Comparators and Ranges will be strict about the SemVer
+strings that they parse.
+
+* `valid(v)`: Return the parsed version, or null if it's not valid.
+* `inc(v, release)`: Return the version incremented by the release
+ type (`major`, `premajor`, `minor`, `preminor`, `patch`,
+ `prepatch`, or `prerelease`), or null if it's not valid
+ * `premajor` in one call will bump the version up to the next major
+ version and down to a prerelease of that major version.
+ `preminor`, and `prepatch` work the same way.
+ * If called from a non-prerelease version, the `prerelease` will work the
+ same as `prepatch`. It increments the patch version, then makes a
+ prerelease. If the input version is already a prerelease it simply
+ increments it.
+* `prerelease(v)`: Returns an array of prerelease components, or null
+ if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]`
+* `major(v)`: Return the major version number.
+* `minor(v)`: Return the minor version number.
+* `patch(v)`: Return the patch version number.
+* `intersects(r1, r2, loose)`: Return true if the two supplied ranges
+ or comparators intersect.
+* `parse(v)`: Attempt to parse a string as a semantic version, returning either
+ a `SemVer` object or `null`.
+
+### Comparison
+
+* `gt(v1, v2)`: `v1 > v2`
+* `gte(v1, v2)`: `v1 >= v2`
+* `lt(v1, v2)`: `v1 < v2`
+* `lte(v1, v2)`: `v1 <= v2`
+* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,
+ even if they're not the exact same string. You already know how to
+ compare strings.
+* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.
+* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call
+ the corresponding function above. `"==="` and `"!=="` do simple
+ string comparison, but are included for completeness. Throws if an
+ invalid comparison string is provided.
+* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if
+ `v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
+* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions
+ in descending order when passed to `Array.sort()`.
+* `compareBuild(v1, v2)`: The same as `compare` but considers `build` when two versions
+ are equal. Sorts in ascending order if passed to `Array.sort()`.
+ `v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
+* `diff(v1, v2)`: Returns difference between two versions by the release type
+ (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`),
+ or null if the versions are the same.
+
+### Comparators
+
+* `intersects(comparator)`: Return true if the comparators intersect
+
+### Ranges
+
+* `validRange(range)`: Return the valid range or null if it's not valid
+* `satisfies(version, range)`: Return true if the version satisfies the
+ range.
+* `maxSatisfying(versions, range)`: Return the highest version in the list
+ that satisfies the range, or `null` if none of them do.
+* `minSatisfying(versions, range)`: Return the lowest version in the list
+ that satisfies the range, or `null` if none of them do.
+* `minVersion(range)`: Return the lowest version that can possibly match
+ the given range.
+* `gtr(version, range)`: Return `true` if version is greater than all the
+ versions possible in the range.
+* `ltr(version, range)`: Return `true` if version is less than all the
+ versions possible in the range.
+* `outside(version, range, hilo)`: Return true if the version is outside
+ the bounds of the range in either the high or low direction. The
+ `hilo` argument must be either the string `'>'` or `'<'`. (This is
+ the function called by `gtr` and `ltr`.)
+* `intersects(range)`: Return true if any of the ranges comparators intersect
+* `simplifyRange(versions, range)`: Return a "simplified" range that
+ matches the same items in `versions` list as the range specified. Note
+ that it does *not* guarantee that it would match the same versions in all
+ cases, only for the set of versions provided. This is useful when
+ generating ranges by joining together multiple versions with `||`
+ programmatically, to provide the user with something a bit more
+ ergonomic. If the provided range is shorter in string-length than the
+ generated range, then that is returned.
+* `subset(subRange, superRange)`: Return `true` if the `subRange` range is
+ entirely contained by the `superRange` range.
+
+Note that, since ranges may be non-contiguous, a version might not be
+greater than a range, less than a range, *or* satisfy a range! For
+example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`
+until `2.0.0`, so the version `1.2.10` would not be greater than the
+range (because `2.0.1` satisfies, which is higher), nor less than the
+range (since `1.2.8` satisfies, which is lower), and it also does not
+satisfy the range.
+
+If you want to know if a version satisfies or does not satisfy a
+range, use the `satisfies(version, range)` function.
+
+### Coercion
+
+* `coerce(version, options)`: Coerces a string to semver if possible
+
+This aims to provide a very forgiving translation of a non-semver string to
+semver. It looks for the first digit in a string, and consumes all
+remaining characters which satisfy at least a partial semver (e.g., `1`,
+`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer
+versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All
+surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes
+`3.4.0`). Only text which lacks digits will fail coercion (`version one`
+is not valid). The maximum length for any semver component considered for
+coercion is 16 characters; longer components will be ignored
+(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any
+semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value
+components are invalid (`9999999999999999.4.7.4` is likely invalid).
+
+If the `options.rtl` flag is set, then `coerce` will return the right-most
+coercible tuple that does not share an ending index with a longer coercible
+tuple. For example, `1.2.3.4` will return `2.3.4` in rtl mode, not
+`4.0.0`. `1.2.3/4` will return `4.0.0`, because the `4` is not a part of
+any other overlapping SemVer tuple.
+
+### Clean
+
+* `clean(version)`: Clean a string to be a valid semver if possible
+
+This will return a cleaned and trimmed semver version. If the provided
+version is not valid a null will be returned. This does not work for
+ranges.
+
+ex.
+* `s.clean(' = v 2.1.5foo')`: `null`
+* `s.clean(' = v 2.1.5foo', { loose: true })`: `'2.1.5-foo'`
+* `s.clean(' = v 2.1.5-foo')`: `null`
+* `s.clean(' = v 2.1.5-foo', { loose: true })`: `'2.1.5-foo'`
+* `s.clean('=v2.1.5')`: `'2.1.5'`
+* `s.clean(' =v2.1.5')`: `2.1.5`
+* `s.clean(' 2.1.5 ')`: `'2.1.5'`
+* `s.clean('~1.0.0')`: `null`
+
+## Exported Modules
+
+<!--
+TODO: Make sure that all of these items are documented (classes aren't,
+eg), and then pull the module name into the documentation for that specific
+thing.
+-->
+
+You may pull in just the part of this semver utility that you need, if you
+are sensitive to packing and tree-shaking concerns. The main
+`require('semver')` export uses getter functions to lazily load the parts
+of the API that are used.
+
+The following modules are available:
+
+* `require('semver')`
+* `require('semver/classes')`
+* `require('semver/classes/comparator')`
+* `require('semver/classes/range')`
+* `require('semver/classes/semver')`
+* `require('semver/functions/clean')`
+* `require('semver/functions/cmp')`
+* `require('semver/functions/coerce')`
+* `require('semver/functions/compare')`
+* `require('semver/functions/compare-build')`
+* `require('semver/functions/compare-loose')`
+* `require('semver/functions/diff')`
+* `require('semver/functions/eq')`
+* `require('semver/functions/gt')`
+* `require('semver/functions/gte')`
+* `require('semver/functions/inc')`
+* `require('semver/functions/lt')`
+* `require('semver/functions/lte')`
+* `require('semver/functions/major')`
+* `require('semver/functions/minor')`
+* `require('semver/functions/neq')`
+* `require('semver/functions/parse')`
+* `require('semver/functions/patch')`
+* `require('semver/functions/prerelease')`
+* `require('semver/functions/rcompare')`
+* `require('semver/functions/rsort')`
+* `require('semver/functions/satisfies')`
+* `require('semver/functions/sort')`
+* `require('semver/functions/valid')`
+* `require('semver/ranges/gtr')`
+* `require('semver/ranges/intersects')`
+* `require('semver/ranges/ltr')`
+* `require('semver/ranges/max-satisfying')`
+* `require('semver/ranges/min-satisfying')`
+* `require('semver/ranges/min-version')`
+* `require('semver/ranges/outside')`
+* `require('semver/ranges/to-comparators')`
+* `require('semver/ranges/valid')`
diff --git a/MistyCore/node_modules/semver/bin/semver.js b/MistyCore/node_modules/semver/bin/semver.js
new file mode 100755
index 0000000..8d1b557
--- /dev/null
+++ b/MistyCore/node_modules/semver/bin/semver.js
@@ -0,0 +1,183 @@
+#!/usr/bin/env node
+// Standalone semver comparison program.
+// Exits successfully and prints matching version(s) if
+// any supplied version is valid and passes all tests.
+
+const argv = process.argv.slice(2)
+
+let versions = []
+
+const range = []
+
+let inc = null
+
+const version = require('../package.json').version
+
+let loose = false
+
+let includePrerelease = false
+
+let coerce = false
+
+let rtl = false
+
+let identifier
+
+const semver = require('../')
+
+let reverse = false
+
+let options = {}
+
+const main = () => {
+ if (!argv.length) {
+ return help()
+ }
+ while (argv.length) {
+ let a = argv.shift()
+ const indexOfEqualSign = a.indexOf('=')
+ if (indexOfEqualSign !== -1) {
+ const value = a.slice(indexOfEqualSign + 1)
+ a = a.slice(0, indexOfEqualSign)
+ argv.unshift(value)
+ }
+ switch (a) {
+ case '-rv': case '-rev': case '--rev': case '--reverse':
+ reverse = true
+ break
+ case '-l': case '--loose':
+ loose = true
+ break
+ case '-p': case '--include-prerelease':
+ includePrerelease = true
+ break
+ case '-v': case '--version':
+ versions.push(argv.shift())
+ break
+ case '-i': case '--inc': case '--increment':
+ switch (argv[0]) {
+ case 'major': case 'minor': case 'patch': case 'prerelease':
+ case 'premajor': case 'preminor': case 'prepatch':
+ inc = argv.shift()
+ break
+ default:
+ inc = 'patch'
+ break
+ }
+ break
+ case '--preid':
+ identifier = argv.shift()
+ break
+ case '-r': case '--range':
+ range.push(argv.shift())
+ break
+ case '-c': case '--coerce':
+ coerce = true
+ break
+ case '--rtl':
+ rtl = true
+ break
+ case '--ltr':
+ rtl = false
+ break
+ case '-h': case '--help': case '-?':
+ return help()
+ default:
+ versions.push(a)
+ break
+ }
+ }
+
+ options = { loose: loose, includePrerelease: includePrerelease, rtl: rtl }
+
+ versions = versions.map((v) => {
+ return coerce ? (semver.coerce(v, options) || { version: v }).version : v
+ }).filter((v) => {
+ return semver.valid(v)
+ })
+ if (!versions.length) {
+ return fail()
+ }
+ if (inc && (versions.length !== 1 || range.length)) {
+ return failInc()
+ }
+
+ for (let i = 0, l = range.length; i < l; i++) {
+ versions = versions.filter((v) => {
+ return semver.satisfies(v, range[i], options)
+ })
+ if (!versions.length) {
+ return fail()
+ }
+ }
+ return success(versions)
+}
+
+const failInc = () => {
+ console.error('--inc can only be used on a single version with no range')
+ fail()
+}
+
+const fail = () => process.exit(1)
+
+const success = () => {
+ const compare = reverse ? 'rcompare' : 'compare'
+ versions.sort((a, b) => {
+ return semver[compare](a, b, options)
+ }).map((v) => {
+ return semver.clean(v, options)
+ }).map((v) => {
+ return inc ? semver.inc(v, inc, options, identifier) : v
+ }).forEach((v, i, _) => {
+ console.log(v)
+ })
+}
+
+const help = () => console.log(
+`SemVer ${version}
+
+A JavaScript implementation of the https://semver.org/ specification
+Copyright Isaac Z. Schlueter
+
+Usage: semver [options] <version> [<version> [...]]
+Prints valid versions sorted by SemVer precedence
+
+Options:
+-r --range <range>
+ Print versions that match the specified range.
+
+-i --increment [<level>]
+ Increment a version by the specified level. Level can
+ be one of: major, minor, patch, premajor, preminor,
+ prepatch, or prerelease. Default level is 'patch'.
+ Only one version may be specified.
+
+--preid <identifier>
+ Identifier to be used to prefix premajor, preminor,
+ prepatch or prerelease version increments.
+
+-l --loose
+ Interpret versions and ranges loosely
+
+-p --include-prerelease
+ Always include prerelease versions in range matching
+
+-c --coerce
+ Coerce a string into SemVer if possible
+ (does not imply --loose)
+
+--rtl
+ Coerce version strings right to left
+
+--ltr
+ Coerce version strings left to right (default)
+
+Program exits successfully if any valid version satisfies
+all supplied ranges, and prints all satisfying versions.
+
+If no satisfying versions are found, then exits failure.
+
+Versions are printed in ascending order, so supplying
+multiple versions to the utility will just sort them.`)
+
+main()
diff --git a/MistyCore/node_modules/semver/classes/comparator.js b/MistyCore/node_modules/semver/classes/comparator.js
new file mode 100644
index 0000000..62cd204
--- /dev/null
+++ b/MistyCore/node_modules/semver/classes/comparator.js
@@ -0,0 +1,136 @@
+const ANY = Symbol('SemVer ANY')
+// hoisted class for cyclic dependency
+class Comparator {
+ static get ANY () {
+ return ANY
+ }
+
+ constructor (comp, options) {
+ options = parseOptions(options)
+
+ if (comp instanceof Comparator) {
+ if (comp.loose === !!options.loose) {
+ return comp
+ } else {
+ comp = comp.value
+ }
+ }
+
+ debug('comparator', comp, options)
+ this.options = options
+ this.loose = !!options.loose
+ this.parse(comp)
+
+ if (this.semver === ANY) {
+ this.value = ''
+ } else {
+ this.value = this.operator + this.semver.version
+ }
+
+ debug('comp', this)
+ }
+
+ parse (comp) {
+ const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
+ const m = comp.match(r)
+
+ if (!m) {
+ throw new TypeError(`Invalid comparator: ${comp}`)
+ }
+
+ this.operator = m[1] !== undefined ? m[1] : ''
+ if (this.operator === '=') {
+ this.operator = ''
+ }
+
+ // if it literally is just '>' or '' then allow anything.
+ if (!m[2]) {
+ this.semver = ANY
+ } else {
+ this.semver = new SemVer(m[2], this.options.loose)
+ }
+ }
+
+ toString () {
+ return this.value
+ }
+
+ test (version) {
+ debug('Comparator.test', version, this.options.loose)
+
+ if (this.semver === ANY || version === ANY) {
+ return true
+ }
+
+ if (typeof version === 'string') {
+ try {
+ version = new SemVer(version, this.options)
+ } catch (er) {
+ return false
+ }
+ }
+
+ return cmp(version, this.operator, this.semver, this.options)
+ }
+
+ intersects (comp, options) {
+ if (!(comp instanceof Comparator)) {
+ throw new TypeError('a Comparator is required')
+ }
+
+ if (!options || typeof options !== 'object') {
+ options = {
+ loose: !!options,
+ includePrerelease: false,
+ }
+ }
+
+ if (this.operator === '') {
+ if (this.value === '') {
+ return true
+ }
+ return new Range(comp.value, options).test(this.value)
+ } else if (comp.operator === '') {
+ if (comp.value === '') {
+ return true
+ }
+ return new Range(this.value, options).test(comp.semver)
+ }
+
+ const sameDirectionIncreasing =
+ (this.operator === '>=' || this.operator === '>') &&
+ (comp.operator === '>=' || comp.operator === '>')
+ const sameDirectionDecreasing =
+ (this.operator === '<=' || this.operator === '<') &&
+ (comp.operator === '<=' || comp.operator === '<')
+ const sameSemVer = this.semver.version === comp.semver.version
+ const differentDirectionsInclusive =
+ (this.operator === '>=' || this.operator === '<=') &&
+ (comp.operator === '>=' || comp.operator === '<=')
+ const oppositeDirectionsLessThan =
+ cmp(this.semver, '<', comp.semver, options) &&
+ (this.operator === '>=' || this.operator === '>') &&
+ (comp.operator === '<=' || comp.operator === '<')
+ const oppositeDirectionsGreaterThan =
+ cmp(this.semver, '>', comp.semver, options) &&
+ (this.operator === '<=' || this.operator === '<') &&
+ (comp.operator === '>=' || comp.operator === '>')
+
+ return (
+ sameDirectionIncreasing ||
+ sameDirectionDecreasing ||
+ (sameSemVer && differentDirectionsInclusive) ||
+ oppositeDirectionsLessThan ||
+ oppositeDirectionsGreaterThan
+ )
+ }
+}
+
+module.exports = Comparator
+
+const parseOptions = require('../internal/parse-options')
+const { re, t } = require('../internal/re')
+const cmp = require('../functions/cmp')
+const debug = require('../internal/debug')
+const SemVer = require('./semver')
+const Range = require('./range')
diff --git a/MistyCore/node_modules/semver/classes/index.js b/MistyCore/node_modules/semver/classes/index.js
new file mode 100644
index 0000000..5e3f5c9
--- /dev/null
+++ b/MistyCore/node_modules/semver/classes/index.js
@@ -0,0 +1,5 @@
+module.exports = {
+ SemVer: require('./semver.js'),
+ Range: require('./range.js'),
+ Comparator: require('./comparator.js'),
+}
diff --git a/MistyCore/node_modules/semver/classes/range.js b/MistyCore/node_modules/semver/classes/range.js
new file mode 100644
index 0000000..a791d91
--- /dev/null
+++ b/MistyCore/node_modules/semver/classes/range.js
@@ -0,0 +1,522 @@
+// hoisted class for cyclic dependency
+class Range {
+ constructor (range, options) {
+ options = parseOptions(options)
+
+ if (range instanceof Range) {
+ if (
+ range.loose === !!options.loose &&
+ range.includePrerelease === !!options.includePrerelease
+ ) {
+ return range
+ } else {
+ return new Range(range.raw, options)
+ }
+ }
+
+ if (range instanceof Comparator) {
+ // just put it in the set and return
+ this.raw = range.value
+ this.set = [[range]]
+ this.format()
+ return this
+ }
+
+ this.options = options
+ this.loose = !!options.loose
+ this.includePrerelease = !!options.includePrerelease
+
+ // First, split based on boolean or ||
+ this.raw = range
+ this.set = range
+ .split('||')
+ // map the range to a 2d array of comparators
+ .map(r => this.parseRange(r.trim()))
+ // throw out any comparator lists that are empty
+ // this generally means that it was not a valid range, which is allowed
+ // in loose mode, but will still throw if the WHOLE range is invalid.
+ .filter(c => c.length)
+
+ if (!this.set.length) {
+ throw new TypeError(`Invalid SemVer Range: ${range}`)
+ }
+
+ // if we have any that are not the null set, throw out null sets.
+ if (this.set.length > 1) {
+ // keep the first one, in case they're all null sets
+ const first = this.set[0]
+ this.set = this.set.filter(c => !isNullSet(c[0]))
+ if (this.set.length === 0) {
+ this.set = [first]
+ } else if (this.set.length > 1) {
+ // if we have any that are *, then the range is just *
+ for (const c of this.set) {
+ if (c.length === 1 && isAny(c[0])) {
+ this.set = [c]
+ break
+ }
+ }
+ }
+ }
+
+ this.format()
+ }
+
+ format () {
+ this.range = this.set
+ .map((comps) => {
+ return comps.join(' ').trim()
+ })
+ .join('||')
+ .trim()
+ return this.range
+ }
+
+ toString () {
+ return this.range
+ }
+
+ parseRange (range) {
+ range = range.trim()
+
+ // memoize range parsing for performance.
+ // this is a very hot path, and fully deterministic.
+ const memoOpts = Object.keys(this.options).join(',')
+ const memoKey = `parseRange:${memoOpts}:${range}`
+ const cached = cache.get(memoKey)
+ if (cached) {
+ return cached
+ }
+
+ const loose = this.options.loose
+ // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
+ const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]
+ range = range.replace(hr, hyphenReplace(this.options.includePrerelease))
+ debug('hyphen replace', range)
+ // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
+ range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace)
+ debug('comparator trim', range)
+
+ // `~ 1.2.3` => `~1.2.3`
+ range = range.replace(re[t.TILDETRIM], tildeTrimReplace)
+
+ // `^ 1.2.3` => `^1.2.3`
+ range = range.replace(re[t.CARETTRIM], caretTrimReplace)
+
+ // normalize spaces
+ range = range.split(/\s+/).join(' ')
+
+ // At this point, the range is completely trimmed and
+ // ready to be split into comparators.
+
+ let rangeList = range
+ .split(' ')
+ .map(comp => parseComparator(comp, this.options))
+ .join(' ')
+ .split(/\s+/)
+ // >=0.0.0 is equivalent to *
+ .map(comp => replaceGTE0(comp, this.options))
+
+ if (loose) {
+ // in loose mode, throw out any that are not valid comparators
+ rangeList = rangeList.filter(comp => {
+ debug('loose invalid filter', comp, this.options)
+ return !!comp.match(re[t.COMPARATORLOOSE])
+ })
+ }
+ debug('range list', rangeList)
+
+ // if any comparators are the null set, then replace with JUST null set
+ // if more than one comparator, remove any * comparators
+ // also, don't include the same comparator more than once
+ const rangeMap = new Map()
+ const comparators = rangeList.map(comp => new Comparator(comp, this.options))
+ for (const comp of comparators) {
+ if (isNullSet(comp)) {
+ return [comp]
+ }
+ rangeMap.set(comp.value, comp)
+ }
+ if (rangeMap.size > 1 && rangeMap.has('')) {
+ rangeMap.delete('')
+ }
+
+ const result = [...rangeMap.values()]
+ cache.set(memoKey, result)
+ return result
+ }
+
+ intersects (range, options) {
+ if (!(range instanceof Range)) {
+ throw new TypeError('a Range is required')
+ }
+
+ return this.set.some((thisComparators) => {
+ return (
+ isSatisfiable(thisComparators, options) &&
+ range.set.some((rangeComparators) => {
+ return (
+ isSatisfiable(rangeComparators, options) &&
+ thisComparators.every((thisComparator) => {
+ return rangeComparators.every((rangeComparator) => {
+ return thisComparator.intersects(rangeComparator, options)
+ })
+ })
+ )
+ })
+ )
+ })
+ }
+
+ // if ANY of the sets match ALL of its comparators, then pass
+ test (version) {
+ if (!version) {
+ return false
+ }
+
+ if (typeof version === 'string') {
+ try {
+ version = new SemVer(version, this.options)
+ } catch (er) {
+ return false
+ }
+ }
+
+ for (let i = 0; i < this.set.length; i++) {
+ if (testSet(this.set[i], version, this.options)) {
+ return true
+ }
+ }
+ return false
+ }
+}
+module.exports = Range
+
+const LRU = require('lru-cache')
+const cache = new LRU({ max: 1000 })
+
+const parseOptions = require('../internal/parse-options')
+const Comparator = require('./comparator')
+const debug = require('../internal/debug')
+const SemVer = require('./semver')
+const {
+ re,
+ t,
+ comparatorTrimReplace,
+ tildeTrimReplace,
+ caretTrimReplace,
+} = require('../internal/re')
+
+const isNullSet = c => c.value === '<0.0.0-0'
+const isAny = c => c.value === ''
+
+// take a set of comparators and determine whether there
+// exists a version which can satisfy it
+const isSatisfiable = (comparators, options) => {
+ let result = true
+ const remainingComparators = comparators.slice()
+ let testComparator = remainingComparators.pop()
+
+ while (result && remainingComparators.length) {
+ result = remainingComparators.every((otherComparator) => {
+ return testComparator.intersects(otherComparator, options)
+ })
+
+ testComparator = remainingComparators.pop()
+ }
+
+ return result
+}
+
+// comprised of xranges, tildes, stars, and gtlt's at this point.
+// already replaced the hyphen ranges
+// turn into a set of JUST comparators.
+const parseComparator = (comp, options) => {
+ debug('comp', comp, options)
+ comp = replaceCarets(comp, options)
+ debug('caret', comp)
+ comp = replaceTildes(comp, options)
+ debug('tildes', comp)
+ comp = replaceXRanges(comp, options)
+ debug('xrange', comp)
+ comp = replaceStars(comp, options)
+ debug('stars', comp)
+ return comp
+}
+
+const isX = id => !id || id.toLowerCase() === 'x' || id === '*'
+
+// ~, ~> --> * (any, kinda silly)
+// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0
+// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0
+// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0
+// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0
+// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0
+// ~0.0.1 --> >=0.0.1 <0.1.0-0
+const replaceTildes = (comp, options) =>
+ comp.trim().split(/\s+/).map((c) => {
+ return replaceTilde(c, options)
+ }).join(' ')
+
+const replaceTilde = (comp, options) => {
+ const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]
+ return comp.replace(r, (_, M, m, p, pr) => {
+ debug('tilde', comp, _, M, m, p, pr)
+ let ret
+
+ if (isX(M)) {
+ ret = ''
+ } else if (isX(m)) {
+ ret = `>=${M}.0.0 <${+M + 1}.0.0-0`
+ } else if (isX(p)) {
+ // ~1.2 == >=1.2.0 <1.3.0-0
+ ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`
+ } else if (pr) {
+ debug('replaceTilde pr', pr)
+ ret = `>=${M}.${m}.${p}-${pr
+ } <${M}.${+m + 1}.0-0`
+ } else {
+ // ~1.2.3 == >=1.2.3 <1.3.0-0
+ ret = `>=${M}.${m}.${p
+ } <${M}.${+m + 1}.0-0`
+ }
+
+ debug('tilde return', ret)
+ return ret
+ })
+}
+
+// ^ --> * (any, kinda silly)
+// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0
+// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0
+// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0
+// ^1.2.3 --> >=1.2.3 <2.0.0-0
+// ^1.2.0 --> >=1.2.0 <2.0.0-0
+// ^0.0.1 --> >=0.0.1 <0.0.2-0
+// ^0.1.0 --> >=0.1.0 <0.2.0-0
+const replaceCarets = (comp, options) =>
+ comp.trim().split(/\s+/).map((c) => {
+ return replaceCaret(c, options)
+ }).join(' ')
+
+const replaceCaret = (comp, options) => {
+ debug('caret', comp, options)
+ const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]
+ const z = options.includePrerelease ? '-0' : ''
+ return comp.replace(r, (_, M, m, p, pr) => {
+ debug('caret', comp, _, M, m, p, pr)
+ let ret
+
+ if (isX(M)) {
+ ret = ''
+ } else if (isX(m)) {
+ ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`
+ } else if (isX(p)) {
+ if (M === '0') {
+ ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`
+ } else {
+ ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`
+ }
+ } else if (pr) {
+ debug('replaceCaret pr', pr)
+ if (M === '0') {
+ if (m === '0') {
+ ret = `>=${M}.${m}.${p}-${pr
+ } <${M}.${m}.${+p + 1}-0`
+ } else {
+ ret = `>=${M}.${m}.${p}-${pr
+ } <${M}.${+m + 1}.0-0`
+ }
+ } else {
+ ret = `>=${M}.${m}.${p}-${pr
+ } <${+M + 1}.0.0-0`
+ }
+ } else {
+ debug('no pr')
+ if (M === '0') {
+ if (m === '0') {
+ ret = `>=${M}.${m}.${p
+ }${z} <${M}.${m}.${+p + 1}-0`
+ } else {
+ ret = `>=${M}.${m}.${p
+ }${z} <${M}.${+m + 1}.0-0`
+ }
+ } else {
+ ret = `>=${M}.${m}.${p
+ } <${+M + 1}.0.0-0`
+ }
+ }
+
+ debug('caret return', ret)
+ return ret
+ })
+}
+
+const replaceXRanges = (comp, options) => {
+ debug('replaceXRanges', comp, options)
+ return comp.split(/\s+/).map((c) => {
+ return replaceXRange(c, options)
+ }).join(' ')
+}
+
+const replaceXRange = (comp, options) => {
+ comp = comp.trim()
+ const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]
+ return comp.replace(r, (ret, gtlt, M, m, p, pr) => {
+ debug('xRange', comp, ret, gtlt, M, m, p, pr)
+ const xM = isX(M)
+ const xm = xM || isX(m)
+ const xp = xm || isX(p)
+ const anyX = xp
+
+ if (gtlt === '=' && anyX) {
+ gtlt = ''
+ }
+
+ // if we're including prereleases in the match, then we need
+ // to fix this to -0, the lowest possible prerelease value
+ pr = options.includePrerelease ? '-0' : ''
+
+ if (xM) {
+ if (gtlt === '>' || gtlt === '<') {
+ // nothing is allowed
+ ret = '<0.0.0-0'
+ } else {
+ // nothing is forbidden
+ ret = '*'
+ }
+ } else if (gtlt && anyX) {
+ // we know patch is an x, because we have any x at all.
+ // replace X with 0
+ if (xm) {
+ m = 0
+ }
+ p = 0
+
+ if (gtlt === '>') {
+ // >1 => >=2.0.0
+ // >1.2 => >=1.3.0
+ gtlt = '>='
+ if (xm) {
+ M = +M + 1
+ m = 0
+ p = 0
+ } else {
+ m = +m + 1
+ p = 0
+ }
+ } else if (gtlt === '<=') {
+ // <=0.7.x is actually <0.8.0, since any 0.7.x should
+ // pass. Similarly, <=7.x is actually <8.0.0, etc.
+ gtlt = '<'
+ if (xm) {
+ M = +M + 1
+ } else {
+ m = +m + 1
+ }
+ }
+
+ if (gtlt === '<') {
+ pr = '-0'
+ }
+
+ ret = `${gtlt + M}.${m}.${p}${pr}`
+ } else if (xm) {
+ ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`
+ } else if (xp) {
+ ret = `>=${M}.${m}.0${pr
+ } <${M}.${+m + 1}.0-0`
+ }
+
+ debug('xRange return', ret)
+
+ return ret
+ })
+}
+
+// Because * is AND-ed with everything else in the comparator,
+// and '' means "any version", just remove the *s entirely.
+const replaceStars = (comp, options) => {
+ debug('replaceStars', comp, options)
+ // Looseness is ignored here. star is always as loose as it gets!
+ return comp.trim().replace(re[t.STAR], '')
+}
+
+const replaceGTE0 = (comp, options) => {
+ debug('replaceGTE0', comp, options)
+ return comp.trim()
+ .replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '')
+}
+
+// This function is passed to string.replace(re[t.HYPHENRANGE])
+// M, m, patch, prerelease, build
+// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
+// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do
+// 1.2 - 3.4 => >=1.2.0 <3.5.0-0
+const hyphenReplace = incPr => ($0,
+ from, fM, fm, fp, fpr, fb,
+ to, tM, tm, tp, tpr, tb) => {
+ if (isX(fM)) {
+ from = ''
+ } else if (isX(fm)) {
+ from = `>=${fM}.0.0${incPr ? '-0' : ''}`
+ } else if (isX(fp)) {
+ from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}`
+ } else if (fpr) {
+ from = `>=${from}`
+ } else {
+ from = `>=${from}${incPr ? '-0' : ''}`
+ }
+
+ if (isX(tM)) {
+ to = ''
+ } else if (isX(tm)) {
+ to = `<${+tM + 1}.0.0-0`
+ } else if (isX(tp)) {
+ to = `<${tM}.${+tm + 1}.0-0`
+ } else if (tpr) {
+ to = `<=${tM}.${tm}.${tp}-${tpr}`
+ } else if (incPr) {
+ to = `<${tM}.${tm}.${+tp + 1}-0`
+ } else {
+ to = `<=${to}`
+ }
+
+ return (`${from} ${to}`).trim()
+}
+
+const testSet = (set, version, options) => {
+ for (let i = 0; i < set.length; i++) {
+ if (!set[i].test(version)) {
+ return false
+ }
+ }
+
+ if (version.prerelease.length && !options.includePrerelease) {
+ // Find the set of versions that are allowed to have prereleases
+ // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
+ // That should allow `1.2.3-pr.2` to pass.
+ // However, `1.2.4-alpha.notready` should NOT be allowed,
+ // even though it's within the range set by the comparators.
+ for (let i = 0; i < set.length; i++) {
+ debug(set[i].semver)
+ if (set[i].semver === Comparator.ANY) {
+ continue
+ }
+
+ if (set[i].semver.prerelease.length > 0) {
+ const allowed = set[i].semver
+ if (allowed.major === version.major &&
+ allowed.minor === version.minor &&
+ allowed.patch === version.patch) {
+ return true
+ }
+ }
+ }
+
+ // Version has a -pre, but it's not one of the ones we like.
+ return false
+ }
+
+ return true
+}
diff --git a/MistyCore/node_modules/semver/classes/semver.js b/MistyCore/node_modules/semver/classes/semver.js
new file mode 100644
index 0000000..af62955
--- /dev/null
+++ b/MistyCore/node_modules/semver/classes/semver.js
@@ -0,0 +1,287 @@
+const debug = require('../internal/debug')
+const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants')
+const { re, t } = require('../internal/re')
+
+const parseOptions = require('../internal/parse-options')
+const { compareIdentifiers } = require('../internal/identifiers')
+class SemVer {
+ constructor (version, options) {
+ options = parseOptions(options)
+
+ if (version instanceof SemVer) {
+ if (version.loose === !!options.loose &&
+ version.includePrerelease === !!options.includePrerelease) {
+ return version
+ } else {
+ version = version.version
+ }
+ } else if (typeof version !== 'string') {
+ throw new TypeError(`Invalid Version: ${version}`)
+ }
+
+ if (version.length > MAX_LENGTH) {
+ throw new TypeError(
+ `version is longer than ${MAX_LENGTH} characters`
+ )
+ }
+
+ debug('SemVer', version, options)
+ this.options = options
+ this.loose = !!options.loose
+ // this isn't actually relevant for versions, but keep it so that we
+ // don't run into trouble passing this.options around.
+ this.includePrerelease = !!options.includePrerelease
+
+ const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])
+
+ if (!m) {
+ throw new TypeError(`Invalid Version: ${version}`)
+ }
+
+ this.raw = version
+
+ // these are actually numbers
+ this.major = +m[1]
+ this.minor = +m[2]
+ this.patch = +m[3]
+
+ if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
+ throw new TypeError('Invalid major version')
+ }
+
+ if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
+ throw new TypeError('Invalid minor version')
+ }
+
+ if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
+ throw new TypeError('Invalid patch version')
+ }
+
+ // numberify any prerelease numeric ids
+ if (!m[4]) {
+ this.prerelease = []
+ } else {
+ this.prerelease = m[4].split('.').map((id) => {
+ if (/^[0-9]+$/.test(id)) {
+ const num = +id
+ if (num >= 0 && num < MAX_SAFE_INTEGER) {
+ return num
+ }
+ }
+ return id
+ })
+ }
+
+ this.build = m[5] ? m[5].split('.') : []
+ this.format()
+ }
+
+ format () {
+ this.version = `${this.major}.${this.minor}.${this.patch}`
+ if (this.prerelease.length) {
+ this.version += `-${this.prerelease.join('.')}`
+ }
+ return this.version
+ }
+
+ toString () {
+ return this.version
+ }
+
+ compare (other) {
+ debug('SemVer.compare', this.version, this.options, other)
+ if (!(other instanceof SemVer)) {
+ if (typeof other === 'string' && other === this.version) {
+ return 0
+ }
+ other = new SemVer(other, this.options)
+ }
+
+ if (other.version === this.version) {
+ return 0
+ }
+
+ return this.compareMain(other) || this.comparePre(other)
+ }
+
+ compareMain (other) {
+ if (!(other instanceof SemVer)) {
+ other = new SemVer(other, this.options)
+ }
+
+ return (
+ compareIdentifiers(this.major, other.major) ||
+ compareIdentifiers(this.minor, other.minor) ||
+ compareIdentifiers(this.patch, other.patch)
+ )
+ }
+
+ comparePre (other) {
+ if (!(other instanceof SemVer)) {
+ other = new SemVer(other, this.options)
+ }
+
+ // NOT having a prerelease is > having one
+ if (this.prerelease.length && !other.prerelease.length) {
+ return -1
+ } else if (!this.prerelease.length && other.prerelease.length) {
+ return 1
+ } else if (!this.prerelease.length && !other.prerelease.length) {
+ return 0
+ }
+
+ let i = 0
+ do {
+ const a = this.prerelease[i]
+ const b = other.prerelease[i]
+ debug('prerelease compare', i, a, b)
+ if (a === undefined && b === undefined) {
+ return 0
+ } else if (b === undefined) {
+ return 1
+ } else if (a === undefined) {
+ return -1
+ } else if (a === b) {
+ continue
+ } else {
+ return compareIdentifiers(a, b)
+ }
+ } while (++i)
+ }
+
+ compareBuild (other) {
+ if (!(other instanceof SemVer)) {
+ other = new SemVer(other, this.options)
+ }
+
+ let i = 0
+ do {
+ const a = this.build[i]
+ const b = other.build[i]
+ debug('prerelease compare', i, a, b)
+ if (a === undefined && b === undefined) {
+ return 0
+ } else if (b === undefined) {
+ return 1
+ } else if (a === undefined) {
+ return -1
+ } else if (a === b) {
+ continue
+ } else {
+ return compareIdentifiers(a, b)
+ }
+ } while (++i)
+ }
+
+ // preminor will bump the version up to the next minor release, and immediately
+ // down to pre-release. premajor and prepatch work the same way.
+ inc (release, identifier) {
+ switch (release) {
+ case 'premajor':
+ this.prerelease.length = 0
+ this.patch = 0
+ this.minor = 0
+ this.major++
+ this.inc('pre', identifier)
+ break
+ case 'preminor':
+ this.prerelease.length = 0
+ this.patch = 0
+ this.minor++
+ this.inc('pre', identifier)
+ break
+ case 'prepatch':
+ // If this is already a prerelease, it will bump to the next version
+ // drop any prereleases that might already exist, since they are not
+ // relevant at this point.
+ this.prerelease.length = 0
+ this.inc('patch', identifier)
+ this.inc('pre', identifier)
+ break
+ // If the input is a non-prerelease version, this acts the same as
+ // prepatch.
+ case 'prerelease':
+ if (this.prerelease.length === 0) {
+ this.inc('patch', identifier)
+ }
+ this.inc('pre', identifier)
+ break
+
+ case 'major':
+ // If this is a pre-major version, bump up to the same major version.
+ // Otherwise increment major.
+ // 1.0.0-5 bumps to 1.0.0
+ // 1.1.0 bumps to 2.0.0
+ if (
+ this.minor !== 0 ||
+ this.patch !== 0 ||
+ this.prerelease.length === 0
+ ) {
+ this.major++
+ }
+ this.minor = 0
+ this.patch = 0
+ this.prerelease = []
+ break
+ case 'minor':
+ // If this is a pre-minor version, bump up to the same minor version.
+ // Otherwise increment minor.
+ // 1.2.0-5 bumps to 1.2.0
+ // 1.2.1 bumps to 1.3.0
+ if (this.patch !== 0 || this.prerelease.length === 0) {
+ this.minor++
+ }
+ this.patch = 0
+ this.prerelease = []
+ break
+ case 'patch':
+ // If this is not a pre-release version, it will increment the patch.
+ // If it is a pre-release it will bump up to the same patch version.
+ // 1.2.0-5 patches to 1.2.0
+ // 1.2.0 patches to 1.2.1
+ if (this.prerelease.length === 0) {
+ this.patch++
+ }
+ this.prerelease = []
+ break
+ // This probably shouldn't be used publicly.
+ // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
+ case 'pre':
+ if (this.prerelease.length === 0) {
+ this.prerelease = [0]
+ } else {
+ let i = this.prerelease.length
+ while (--i >= 0) {
+ if (typeof this.prerelease[i] === 'number') {
+ this.prerelease[i]++
+ i = -2
+ }
+ }
+ if (i === -1) {
+ // didn't increment anything
+ this.prerelease.push(0)
+ }
+ }
+ if (identifier) {
+ // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
+ // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
+ if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
+ if (isNaN(this.prerelease[1])) {
+ this.prerelease = [identifier, 0]
+ }
+ } else {
+ this.prerelease = [identifier, 0]
+ }
+ }
+ break
+
+ default:
+ throw new Error(`invalid increment argument: ${release}`)
+ }
+ this.format()
+ this.raw = this.version
+ return this
+ }
+}
+
+module.exports = SemVer
diff --git a/MistyCore/node_modules/semver/functions/clean.js b/MistyCore/node_modules/semver/functions/clean.js
new file mode 100644
index 0000000..811fe6b
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/clean.js
@@ -0,0 +1,6 @@
+const parse = require('./parse')
+const clean = (version, options) => {
+ const s = parse(version.trim().replace(/^[=v]+/, ''), options)
+ return s ? s.version : null
+}
+module.exports = clean
diff --git a/MistyCore/node_modules/semver/functions/cmp.js b/MistyCore/node_modules/semver/functions/cmp.js
new file mode 100644
index 0000000..4011909
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/cmp.js
@@ -0,0 +1,52 @@
+const eq = require('./eq')
+const neq = require('./neq')
+const gt = require('./gt')
+const gte = require('./gte')
+const lt = require('./lt')
+const lte = require('./lte')
+
+const cmp = (a, op, b, loose) => {
+ switch (op) {
+ case '===':
+ if (typeof a === 'object') {
+ a = a.version
+ }
+ if (typeof b === 'object') {
+ b = b.version
+ }
+ return a === b
+
+ case '!==':
+ if (typeof a === 'object') {
+ a = a.version
+ }
+ if (typeof b === 'object') {
+ b = b.version
+ }
+ return a !== b
+
+ case '':
+ case '=':
+ case '==':
+ return eq(a, b, loose)
+
+ case '!=':
+ return neq(a, b, loose)
+
+ case '>':
+ return gt(a, b, loose)
+
+ case '>=':
+ return gte(a, b, loose)
+
+ case '<':
+ return lt(a, b, loose)
+
+ case '<=':
+ return lte(a, b, loose)
+
+ default:
+ throw new TypeError(`Invalid operator: ${op}`)
+ }
+}
+module.exports = cmp
diff --git a/MistyCore/node_modules/semver/functions/coerce.js b/MistyCore/node_modules/semver/functions/coerce.js
new file mode 100644
index 0000000..2e01452
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/coerce.js
@@ -0,0 +1,52 @@
+const SemVer = require('../classes/semver')
+const parse = require('./parse')
+const { re, t } = require('../internal/re')
+
+const coerce = (version, options) => {
+ if (version instanceof SemVer) {
+ return version
+ }
+
+ if (typeof version === 'number') {
+ version = String(version)
+ }
+
+ if (typeof version !== 'string') {
+ return null
+ }
+
+ options = options || {}
+
+ let match = null
+ if (!options.rtl) {
+ match = version.match(re[t.COERCE])
+ } else {
+ // Find the right-most coercible string that does not share
+ // a terminus with a more left-ward coercible string.
+ // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4'
+ //
+ // Walk through the string checking with a /g regexp
+ // Manually set the index so as to pick up overlapping matches.
+ // Stop when we get a match that ends at the string end, since no
+ // coercible string can be more right-ward without the same terminus.
+ let next
+ while ((next = re[t.COERCERTL].exec(version)) &&
+ (!match || match.index + match[0].length !== version.length)
+ ) {
+ if (!match ||
+ next.index + next[0].length !== match.index + match[0].length) {
+ match = next
+ }
+ re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length
+ }
+ // leave it in a clean state
+ re[t.COERCERTL].lastIndex = -1
+ }
+
+ if (match === null) {
+ return null
+ }
+
+ return parse(`${match[2]}.${match[3] || '0'}.${match[4] || '0'}`, options)
+}
+module.exports = coerce
diff --git a/MistyCore/node_modules/semver/functions/compare-build.js b/MistyCore/node_modules/semver/functions/compare-build.js
new file mode 100644
index 0000000..9eb881b
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/compare-build.js
@@ -0,0 +1,7 @@
+const SemVer = require('../classes/semver')
+const compareBuild = (a, b, loose) => {
+ const versionA = new SemVer(a, loose)
+ const versionB = new SemVer(b, loose)
+ return versionA.compare(versionB) || versionA.compareBuild(versionB)
+}
+module.exports = compareBuild
diff --git a/MistyCore/node_modules/semver/functions/compare-loose.js b/MistyCore/node_modules/semver/functions/compare-loose.js
new file mode 100644
index 0000000..4881fbe
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/compare-loose.js
@@ -0,0 +1,3 @@
+const compare = require('./compare')
+const compareLoose = (a, b) => compare(a, b, true)
+module.exports = compareLoose
diff --git a/MistyCore/node_modules/semver/functions/compare.js b/MistyCore/node_modules/semver/functions/compare.js
new file mode 100644
index 0000000..748b7af
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/compare.js
@@ -0,0 +1,5 @@
+const SemVer = require('../classes/semver')
+const compare = (a, b, loose) =>
+ new SemVer(a, loose).compare(new SemVer(b, loose))
+
+module.exports = compare
diff --git a/MistyCore/node_modules/semver/functions/diff.js b/MistyCore/node_modules/semver/functions/diff.js
new file mode 100644
index 0000000..87200ef
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/diff.js
@@ -0,0 +1,23 @@
+const parse = require('./parse')
+const eq = require('./eq')
+
+const diff = (version1, version2) => {
+ if (eq(version1, version2)) {
+ return null
+ } else {
+ const v1 = parse(version1)
+ const v2 = parse(version2)
+ const hasPre = v1.prerelease.length || v2.prerelease.length
+ const prefix = hasPre ? 'pre' : ''
+ const defaultResult = hasPre ? 'prerelease' : ''
+ for (const key in v1) {
+ if (key === 'major' || key === 'minor' || key === 'patch') {
+ if (v1[key] !== v2[key]) {
+ return prefix + key
+ }
+ }
+ }
+ return defaultResult // may be undefined
+ }
+}
+module.exports = diff
diff --git a/MistyCore/node_modules/semver/functions/eq.js b/MistyCore/node_modules/semver/functions/eq.js
new file mode 100644
index 0000000..271fed9
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/eq.js
@@ -0,0 +1,3 @@
+const compare = require('./compare')
+const eq = (a, b, loose) => compare(a, b, loose) === 0
+module.exports = eq
diff --git a/MistyCore/node_modules/semver/functions/gt.js b/MistyCore/node_modules/semver/functions/gt.js
new file mode 100644
index 0000000..d9b2156
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/gt.js
@@ -0,0 +1,3 @@
+const compare = require('./compare')
+const gt = (a, b, loose) => compare(a, b, loose) > 0
+module.exports = gt
diff --git a/MistyCore/node_modules/semver/functions/gte.js b/MistyCore/node_modules/semver/functions/gte.js
new file mode 100644
index 0000000..5aeaa63
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/gte.js
@@ -0,0 +1,3 @@
+const compare = require('./compare')
+const gte = (a, b, loose) => compare(a, b, loose) >= 0
+module.exports = gte
diff --git a/MistyCore/node_modules/semver/functions/inc.js b/MistyCore/node_modules/semver/functions/inc.js
new file mode 100644
index 0000000..62d1da2
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/inc.js
@@ -0,0 +1,18 @@
+const SemVer = require('../classes/semver')
+
+const inc = (version, release, options, identifier) => {
+ if (typeof (options) === 'string') {
+ identifier = options
+ options = undefined
+ }
+
+ try {
+ return new SemVer(
+ version instanceof SemVer ? version.version : version,
+ options
+ ).inc(release, identifier).version
+ } catch (er) {
+ return null
+ }
+}
+module.exports = inc
diff --git a/MistyCore/node_modules/semver/functions/lt.js b/MistyCore/node_modules/semver/functions/lt.js
new file mode 100644
index 0000000..b440ab7
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/lt.js
@@ -0,0 +1,3 @@
+const compare = require('./compare')
+const lt = (a, b, loose) => compare(a, b, loose) < 0
+module.exports = lt
diff --git a/MistyCore/node_modules/semver/functions/lte.js b/MistyCore/node_modules/semver/functions/lte.js
new file mode 100644
index 0000000..6dcc956
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/lte.js
@@ -0,0 +1,3 @@
+const compare = require('./compare')
+const lte = (a, b, loose) => compare(a, b, loose) <= 0
+module.exports = lte
diff --git a/MistyCore/node_modules/semver/functions/major.js b/MistyCore/node_modules/semver/functions/major.js
new file mode 100644
index 0000000..4283165
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/major.js
@@ -0,0 +1,3 @@
+const SemVer = require('../classes/semver')
+const major = (a, loose) => new SemVer(a, loose).major
+module.exports = major
diff --git a/MistyCore/node_modules/semver/functions/minor.js b/MistyCore/node_modules/semver/functions/minor.js
new file mode 100644
index 0000000..57b3455
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/minor.js
@@ -0,0 +1,3 @@
+const SemVer = require('../classes/semver')
+const minor = (a, loose) => new SemVer(a, loose).minor
+module.exports = minor
diff --git a/MistyCore/node_modules/semver/functions/neq.js b/MistyCore/node_modules/semver/functions/neq.js
new file mode 100644
index 0000000..f944c01
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/neq.js
@@ -0,0 +1,3 @@
+const compare = require('./compare')
+const neq = (a, b, loose) => compare(a, b, loose) !== 0
+module.exports = neq
diff --git a/MistyCore/node_modules/semver/functions/parse.js b/MistyCore/node_modules/semver/functions/parse.js
new file mode 100644
index 0000000..a66663a
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/parse.js
@@ -0,0 +1,33 @@
+const { MAX_LENGTH } = require('../internal/constants')
+const { re, t } = require('../internal/re')
+const SemVer = require('../classes/semver')
+
+const parseOptions = require('../internal/parse-options')
+const parse = (version, options) => {
+ options = parseOptions(options)
+
+ if (version instanceof SemVer) {
+ return version
+ }
+
+ if (typeof version !== 'string') {
+ return null
+ }
+
+ if (version.length > MAX_LENGTH) {
+ return null
+ }
+
+ const r = options.loose ? re[t.LOOSE] : re[t.FULL]
+ if (!r.test(version)) {
+ return null
+ }
+
+ try {
+ return new SemVer(version, options)
+ } catch (er) {
+ return null
+ }
+}
+
+module.exports = parse
diff --git a/MistyCore/node_modules/semver/functions/patch.js b/MistyCore/node_modules/semver/functions/patch.js
new file mode 100644
index 0000000..63afca2
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/patch.js
@@ -0,0 +1,3 @@
+const SemVer = require('../classes/semver')
+const patch = (a, loose) => new SemVer(a, loose).patch
+module.exports = patch
diff --git a/MistyCore/node_modules/semver/functions/prerelease.js b/MistyCore/node_modules/semver/functions/prerelease.js
new file mode 100644
index 0000000..06aa132
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/prerelease.js
@@ -0,0 +1,6 @@
+const parse = require('./parse')
+const prerelease = (version, options) => {
+ const parsed = parse(version, options)
+ return (parsed && parsed.prerelease.length) ? parsed.prerelease : null
+}
+module.exports = prerelease
diff --git a/MistyCore/node_modules/semver/functions/rcompare.js b/MistyCore/node_modules/semver/functions/rcompare.js
new file mode 100644
index 0000000..0ac509e
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/rcompare.js
@@ -0,0 +1,3 @@
+const compare = require('./compare')
+const rcompare = (a, b, loose) => compare(b, a, loose)
+module.exports = rcompare
diff --git a/MistyCore/node_modules/semver/functions/rsort.js b/MistyCore/node_modules/semver/functions/rsort.js
new file mode 100644
index 0000000..82404c5
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/rsort.js
@@ -0,0 +1,3 @@
+const compareBuild = require('./compare-build')
+const rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose))
+module.exports = rsort
diff --git a/MistyCore/node_modules/semver/functions/satisfies.js b/MistyCore/node_modules/semver/functions/satisfies.js
new file mode 100644
index 0000000..50af1c1
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/satisfies.js
@@ -0,0 +1,10 @@
+const Range = require('../classes/range')
+const satisfies = (version, range, options) => {
+ try {
+ range = new Range(range, options)
+ } catch (er) {
+ return false
+ }
+ return range.test(version)
+}
+module.exports = satisfies
diff --git a/MistyCore/node_modules/semver/functions/sort.js b/MistyCore/node_modules/semver/functions/sort.js
new file mode 100644
index 0000000..4d10917
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/sort.js
@@ -0,0 +1,3 @@
+const compareBuild = require('./compare-build')
+const sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose))
+module.exports = sort
diff --git a/MistyCore/node_modules/semver/functions/valid.js b/MistyCore/node_modules/semver/functions/valid.js
new file mode 100644
index 0000000..f27bae1
--- /dev/null
+++ b/MistyCore/node_modules/semver/functions/valid.js
@@ -0,0 +1,6 @@
+const parse = require('./parse')
+const valid = (version, options) => {
+ const v = parse(version, options)
+ return v ? v.version : null
+}
+module.exports = valid
diff --git a/MistyCore/node_modules/semver/index.js b/MistyCore/node_modules/semver/index.js
new file mode 100644
index 0000000..4a342c6
--- /dev/null
+++ b/MistyCore/node_modules/semver/index.js
@@ -0,0 +1,88 @@
+// just pre-load all the stuff that index.js lazily exports
+const internalRe = require('./internal/re')
+const constants = require('./internal/constants')
+const SemVer = require('./classes/semver')
+const identifiers = require('./internal/identifiers')
+const parse = require('./functions/parse')
+const valid = require('./functions/valid')
+const clean = require('./functions/clean')
+const inc = require('./functions/inc')
+const diff = require('./functions/diff')
+const major = require('./functions/major')
+const minor = require('./functions/minor')
+const patch = require('./functions/patch')
+const prerelease = require('./functions/prerelease')
+const compare = require('./functions/compare')
+const rcompare = require('./functions/rcompare')
+const compareLoose = require('./functions/compare-loose')
+const compareBuild = require('./functions/compare-build')
+const sort = require('./functions/sort')
+const rsort = require('./functions/rsort')
+const gt = require('./functions/gt')
+const lt = require('./functions/lt')
+const eq = require('./functions/eq')
+const neq = require('./functions/neq')
+const gte = require('./functions/gte')
+const lte = require('./functions/lte')
+const cmp = require('./functions/cmp')
+const coerce = require('./functions/coerce')
+const Comparator = require('./classes/comparator')
+const Range = require('./classes/range')
+const satisfies = require('./functions/satisfies')
+const toComparators = require('./ranges/to-comparators')
+const maxSatisfying = require('./ranges/max-satisfying')
+const minSatisfying = require('./ranges/min-satisfying')
+const minVersion = require('./ranges/min-version')
+const validRange = require('./ranges/valid')
+const outside = require('./ranges/outside')
+const gtr = require('./ranges/gtr')
+const ltr = require('./ranges/ltr')
+const intersects = require('./ranges/intersects')
+const simplifyRange = require('./ranges/simplify')
+const subset = require('./ranges/subset')
+module.exports = {
+ parse,
+ valid,
+ clean,
+ inc,
+ diff,
+ major,
+ minor,
+ patch,
+ prerelease,
+ compare,
+ rcompare,
+ compareLoose,
+ compareBuild,
+ sort,
+ rsort,
+ gt,
+ lt,
+ eq,
+ neq,
+ gte,
+ lte,
+ cmp,
+ coerce,
+ Comparator,
+ Range,
+ satisfies,
+ toComparators,
+ maxSatisfying,
+ minSatisfying,
+ minVersion,
+ validRange,
+ outside,
+ gtr,
+ ltr,
+ intersects,
+ simplifyRange,
+ subset,
+ SemVer,
+ re: internalRe.re,
+ src: internalRe.src,
+ tokens: internalRe.t,
+ SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION,
+ compareIdentifiers: identifiers.compareIdentifiers,
+ rcompareIdentifiers: identifiers.rcompareIdentifiers,
+}
diff --git a/MistyCore/node_modules/semver/internal/constants.js b/MistyCore/node_modules/semver/internal/constants.js
new file mode 100644
index 0000000..4f0de59
--- /dev/null
+++ b/MistyCore/node_modules/semver/internal/constants.js
@@ -0,0 +1,17 @@
+// Note: this is the semver.org version of the spec that it implements
+// Not necessarily the package version of this code.
+const SEMVER_SPEC_VERSION = '2.0.0'
+
+const MAX_LENGTH = 256
+const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
+/* istanbul ignore next */ 9007199254740991
+
+// Max safe segment length for coercion.
+const MAX_SAFE_COMPONENT_LENGTH = 16
+
+module.exports = {
+ SEMVER_SPEC_VERSION,
+ MAX_LENGTH,
+ MAX_SAFE_INTEGER,
+ MAX_SAFE_COMPONENT_LENGTH,
+}
diff --git a/MistyCore/node_modules/semver/internal/debug.js b/MistyCore/node_modules/semver/internal/debug.js
new file mode 100644
index 0000000..1c00e13
--- /dev/null
+++ b/MistyCore/node_modules/semver/internal/debug.js
@@ -0,0 +1,9 @@
+const debug = (
+ typeof process === 'object' &&
+ process.env &&
+ process.env.NODE_DEBUG &&
+ /\bsemver\b/i.test(process.env.NODE_DEBUG)
+) ? (...args) => console.error('SEMVER', ...args)
+ : () => {}
+
+module.exports = debug
diff --git a/MistyCore/node_modules/semver/internal/identifiers.js b/MistyCore/node_modules/semver/internal/identifiers.js
new file mode 100644
index 0000000..e612d0a
--- /dev/null
+++ b/MistyCore/node_modules/semver/internal/identifiers.js
@@ -0,0 +1,23 @@
+const numeric = /^[0-9]+$/
+const compareIdentifiers = (a, b) => {
+ const anum = numeric.test(a)
+ const bnum = numeric.test(b)
+
+ if (anum && bnum) {
+ a = +a
+ b = +b
+ }
+
+ return a === b ? 0
+ : (anum && !bnum) ? -1
+ : (bnum && !anum) ? 1
+ : a < b ? -1
+ : 1
+}
+
+const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a)
+
+module.exports = {
+ compareIdentifiers,
+ rcompareIdentifiers,
+}
diff --git a/MistyCore/node_modules/semver/internal/parse-options.js b/MistyCore/node_modules/semver/internal/parse-options.js
new file mode 100644
index 0000000..bbd9ec7
--- /dev/null
+++ b/MistyCore/node_modules/semver/internal/parse-options.js
@@ -0,0 +1,11 @@
+// parse out just the options we care about so we always get a consistent
+// obj with keys in a consistent order.
+const opts = ['includePrerelease', 'loose', 'rtl']
+const parseOptions = options =>
+ !options ? {}
+ : typeof options !== 'object' ? { loose: true }
+ : opts.filter(k => options[k]).reduce((o, k) => {
+ o[k] = true
+ return o
+ }, {})
+module.exports = parseOptions
diff --git a/MistyCore/node_modules/semver/internal/re.js b/MistyCore/node_modules/semver/internal/re.js
new file mode 100644
index 0000000..ed88398
--- /dev/null
+++ b/MistyCore/node_modules/semver/internal/re.js
@@ -0,0 +1,182 @@
+const { MAX_SAFE_COMPONENT_LENGTH } = require('./constants')
+const debug = require('./debug')
+exports = module.exports = {}
+
+// The actual regexps go on exports.re
+const re = exports.re = []
+const src = exports.src = []
+const t = exports.t = {}
+let R = 0
+
+const createToken = (name, value, isGlobal) => {
+ const index = R++
+ debug(name, index, value)
+ t[name] = index
+ src[index] = value
+ re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
+}
+
+// The following Regular Expressions can be used for tokenizing,
+// validating, and parsing SemVer version strings.
+
+// ## Numeric Identifier
+// A single `0`, or a non-zero digit followed by zero or more digits.
+
+createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*')
+createToken('NUMERICIDENTIFIERLOOSE', '[0-9]+')
+
+// ## Non-numeric Identifier
+// Zero or more digits, followed by a letter or hyphen, and then zero or
+// more letters, digits, or hyphens.
+
+createToken('NONNUMERICIDENTIFIER', '\\d*[a-zA-Z-][a-zA-Z0-9-]*')
+
+// ## Main Version
+// Three dot-separated numeric identifiers.
+
+createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
+ `(${src[t.NUMERICIDENTIFIER]})\\.` +
+ `(${src[t.NUMERICIDENTIFIER]})`)
+
+createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
+ `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
+ `(${src[t.NUMERICIDENTIFIERLOOSE]})`)
+
+// ## Pre-release Version Identifier
+// A numeric identifier, or a non-numeric identifier.
+
+createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER]
+}|${src[t.NONNUMERICIDENTIFIER]})`)
+
+createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE]
+}|${src[t.NONNUMERICIDENTIFIER]})`)
+
+// ## Pre-release Version
+// Hyphen, followed by one or more dot-separated pre-release version
+// identifiers.
+
+createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
+}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`)
+
+createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
+}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`)
+
+// ## Build Metadata Identifier
+// Any combination of digits, letters, or hyphens.
+
+createToken('BUILDIDENTIFIER', '[0-9A-Za-z-]+')
+
+// ## Build Metadata
+// Plus sign, followed by one or more period-separated build metadata
+// identifiers.
+
+createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
+}(?:\\.${src[t.BUILDIDENTIFIER]})*))`)
+
+// ## Full Version String
+// A main version, followed optionally by a pre-release version and
+// build metadata.
+
+// Note that the only major, minor, patch, and pre-release sections of
+// the version string are capturing groups. The build metadata is not a
+// capturing group, because it should not ever be used in version
+// comparison.
+
+createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
+}${src[t.PRERELEASE]}?${
+ src[t.BUILD]}?`)
+
+createToken('FULL', `^${src[t.FULLPLAIN]}$`)
+
+// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
+// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
+// common in the npm registry.
+createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
+}${src[t.PRERELEASELOOSE]}?${
+ src[t.BUILD]}?`)
+
+createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`)
+
+createToken('GTLT', '((?:<|>)?=?)')
+
+// Something like "2.*" or "1.2.x".
+// Note that "x.x" is a valid xRange identifer, meaning "any version"
+// Only the first item is strictly required.
+createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`)
+createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`)
+
+createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
+ `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
+ `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
+ `(?:${src[t.PRERELEASE]})?${
+ src[t.BUILD]}?` +
+ `)?)?`)
+
+createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
+ `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
+ `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
+ `(?:${src[t.PRERELEASELOOSE]})?${
+ src[t.BUILD]}?` +
+ `)?)?`)
+
+createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`)
+createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`)
+
+// Coercion.
+// Extract anything that could conceivably be a part of a valid semver
+createToken('COERCE', `${'(^|[^\\d])' +
+ '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
+ `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
+ `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
+ `(?:$|[^\\d])`)
+createToken('COERCERTL', src[t.COERCE], true)
+
+// Tilde ranges.
+// Meaning is "reasonably at or greater than"
+createToken('LONETILDE', '(?:~>?)')
+
+createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true)
+exports.tildeTrimReplace = '$1~'
+
+createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`)
+createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`)
+
+// Caret ranges.
+// Meaning is "at least and backwards compatible with"
+createToken('LONECARET', '(?:\\^)')
+
+createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true)
+exports.caretTrimReplace = '$1^'
+
+createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`)
+createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`)
+
+// A simple gt/lt/eq thing, or just "" to indicate "any version"
+createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`)
+createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`)
+
+// An expression to strip any whitespace between the gtlt and the thing
+// it modifies, so that `> 1.2.3` ==> `>1.2.3`
+createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
+}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true)
+exports.comparatorTrimReplace = '$1$2$3'
+
+// Something like `1.2.3 - 1.2.4`
+// Note that these all use the loose form, because they'll be
+// checked against either the strict or loose comparator form
+// later.
+createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
+ `\\s+-\\s+` +
+ `(${src[t.XRANGEPLAIN]})` +
+ `\\s*$`)
+
+createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
+ `\\s+-\\s+` +
+ `(${src[t.XRANGEPLAINLOOSE]})` +
+ `\\s*$`)
+
+// Star ranges basically just allow anything at all.
+createToken('STAR', '(<|>)?=?\\s*\\*')
+// >=0.0.0 is like a star
+createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$')
+createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$')
diff --git a/MistyCore/node_modules/semver/package.json b/MistyCore/node_modules/semver/package.json
new file mode 100644
index 0000000..72d3f66
--- /dev/null
+++ b/MistyCore/node_modules/semver/package.json
@@ -0,0 +1,86 @@
+{
+ "name": "semver",
+ "version": "7.3.8",
+ "description": "The semantic version parser used by npm.",
+ "main": "index.js",
+ "scripts": {
+ "test": "tap",
+ "snap": "tap",
+ "lint": "eslint \"**/*.js\"",
+ "postlint": "template-oss-check",
+ "lintfix": "npm run lint -- --fix",
+ "posttest": "npm run lint",
+ "template-oss-apply": "template-oss-apply --force"
+ },
+ "devDependencies": {
+ "@npmcli/eslint-config": "^3.0.1",
+ "@npmcli/template-oss": "4.4.4",
+ "tap": "^16.0.0"
+ },
+ "license": "ISC",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/npm/node-semver.git"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "files": [
+ "bin/",
+ "lib/",
+ "classes/",
+ "functions/",
+ "internal/",
+ "ranges/",
+ "index.js",
+ "preload.js",
+ "range.bnf"
+ ],
+ "tap": {
+ "check-coverage": true,
+ "coverage-map": "map.js",
+ "nyc-arg": [
+ "--exclude",
+ "tap-snapshots/**"
+ ]
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "author": "GitHub Inc.",
+ "templateOSS": {
+ "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
+ "version": "4.4.4",
+ "engines": ">=10",
+ "content": "./scripts",
+ "ciVersions": [
+ "10.0.0",
+ "10.x",
+ "12.x",
+ "14.x",
+ "16.x",
+ "18.x"
+ ],
+ "distPaths": [
+ "classes/",
+ "functions/",
+ "internal/",
+ "ranges/",
+ "index.js",
+ "preload.js",
+ "range.bnf"
+ ],
+ "allowPaths": [
+ "/classes/",
+ "/functions/",
+ "/internal/",
+ "/ranges/",
+ "/index.js",
+ "/preload.js",
+ "/range.bnf"
+ ]
+ }
+}
diff --git a/MistyCore/node_modules/semver/preload.js b/MistyCore/node_modules/semver/preload.js
new file mode 100644
index 0000000..947cd4f
--- /dev/null
+++ b/MistyCore/node_modules/semver/preload.js
@@ -0,0 +1,2 @@
+// XXX remove in v8 or beyond
+module.exports = require('./index.js')
diff --git a/MistyCore/node_modules/semver/range.bnf b/MistyCore/node_modules/semver/range.bnf
new file mode 100644
index 0000000..d4c6ae0
--- /dev/null
+++ b/MistyCore/node_modules/semver/range.bnf
@@ -0,0 +1,16 @@
+range-set ::= range ( logical-or range ) *
+logical-or ::= ( ' ' ) * '||' ( ' ' ) *
+range ::= hyphen | simple ( ' ' simple ) * | ''
+hyphen ::= partial ' - ' partial
+simple ::= primitive | partial | tilde | caret
+primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
+partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
+xr ::= 'x' | 'X' | '*' | nr
+nr ::= '0' | [1-9] ( [0-9] ) *
+tilde ::= '~' partial
+caret ::= '^' partial
+qualifier ::= ( '-' pre )? ( '+' build )?
+pre ::= parts
+build ::= parts
+parts ::= part ( '.' part ) *
+part ::= nr | [-0-9A-Za-z]+
diff --git a/MistyCore/node_modules/semver/ranges/gtr.js b/MistyCore/node_modules/semver/ranges/gtr.js
new file mode 100644
index 0000000..db7e355
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/gtr.js
@@ -0,0 +1,4 @@
+// Determine if version is greater than all the versions possible in the range.
+const outside = require('./outside')
+const gtr = (version, range, options) => outside(version, range, '>', options)
+module.exports = gtr
diff --git a/MistyCore/node_modules/semver/ranges/intersects.js b/MistyCore/node_modules/semver/ranges/intersects.js
new file mode 100644
index 0000000..3d1a6f3
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/intersects.js
@@ -0,0 +1,7 @@
+const Range = require('../classes/range')
+const intersects = (r1, r2, options) => {
+ r1 = new Range(r1, options)
+ r2 = new Range(r2, options)
+ return r1.intersects(r2)
+}
+module.exports = intersects
diff --git a/MistyCore/node_modules/semver/ranges/ltr.js b/MistyCore/node_modules/semver/ranges/ltr.js
new file mode 100644
index 0000000..528a885
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/ltr.js
@@ -0,0 +1,4 @@
+const outside = require('./outside')
+// Determine if version is less than all the versions possible in the range
+const ltr = (version, range, options) => outside(version, range, '<', options)
+module.exports = ltr
diff --git a/MistyCore/node_modules/semver/ranges/max-satisfying.js b/MistyCore/node_modules/semver/ranges/max-satisfying.js
new file mode 100644
index 0000000..6e3d993
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/max-satisfying.js
@@ -0,0 +1,25 @@
+const SemVer = require('../classes/semver')
+const Range = require('../classes/range')
+
+const maxSatisfying = (versions, range, options) => {
+ let max = null
+ let maxSV = null
+ let rangeObj = null
+ try {
+ rangeObj = new Range(range, options)
+ } catch (er) {
+ return null
+ }
+ versions.forEach((v) => {
+ if (rangeObj.test(v)) {
+ // satisfies(v, range, options)
+ if (!max || maxSV.compare(v) === -1) {
+ // compare(max, v, true)
+ max = v
+ maxSV = new SemVer(max, options)
+ }
+ }
+ })
+ return max
+}
+module.exports = maxSatisfying
diff --git a/MistyCore/node_modules/semver/ranges/min-satisfying.js b/MistyCore/node_modules/semver/ranges/min-satisfying.js
new file mode 100644
index 0000000..9b60974
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/min-satisfying.js
@@ -0,0 +1,24 @@
+const SemVer = require('../classes/semver')
+const Range = require('../classes/range')
+const minSatisfying = (versions, range, options) => {
+ let min = null
+ let minSV = null
+ let rangeObj = null
+ try {
+ rangeObj = new Range(range, options)
+ } catch (er) {
+ return null
+ }
+ versions.forEach((v) => {
+ if (rangeObj.test(v)) {
+ // satisfies(v, range, options)
+ if (!min || minSV.compare(v) === 1) {
+ // compare(min, v, true)
+ min = v
+ minSV = new SemVer(min, options)
+ }
+ }
+ })
+ return min
+}
+module.exports = minSatisfying
diff --git a/MistyCore/node_modules/semver/ranges/min-version.js b/MistyCore/node_modules/semver/ranges/min-version.js
new file mode 100644
index 0000000..350e1f7
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/min-version.js
@@ -0,0 +1,61 @@
+const SemVer = require('../classes/semver')
+const Range = require('../classes/range')
+const gt = require('../functions/gt')
+
+const minVersion = (range, loose) => {
+ range = new Range(range, loose)
+
+ let minver = new SemVer('0.0.0')
+ if (range.test(minver)) {
+ return minver
+ }
+
+ minver = new SemVer('0.0.0-0')
+ if (range.test(minver)) {
+ return minver
+ }
+
+ minver = null
+ for (let i = 0; i < range.set.length; ++i) {
+ const comparators = range.set[i]
+
+ let setMin = null
+ comparators.forEach((comparator) => {
+ // Clone to avoid manipulating the comparator's semver object.
+ const compver = new SemVer(comparator.semver.version)
+ switch (comparator.operator) {
+ case '>':
+ if (compver.prerelease.length === 0) {
+ compver.patch++
+ } else {
+ compver.prerelease.push(0)
+ }
+ compver.raw = compver.format()
+ /* fallthrough */
+ case '':
+ case '>=':
+ if (!setMin || gt(compver, setMin)) {
+ setMin = compver
+ }
+ break
+ case '<':
+ case '<=':
+ /* Ignore maximum versions */
+ break
+ /* istanbul ignore next */
+ default:
+ throw new Error(`Unexpected operation: ${comparator.operator}`)
+ }
+ })
+ if (setMin && (!minver || gt(minver, setMin))) {
+ minver = setMin
+ }
+ }
+
+ if (minver && range.test(minver)) {
+ return minver
+ }
+
+ return null
+}
+module.exports = minVersion
diff --git a/MistyCore/node_modules/semver/ranges/outside.js b/MistyCore/node_modules/semver/ranges/outside.js
new file mode 100644
index 0000000..ae99b10
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/outside.js
@@ -0,0 +1,80 @@
+const SemVer = require('../classes/semver')
+const Comparator = require('../classes/comparator')
+const { ANY } = Comparator
+const Range = require('../classes/range')
+const satisfies = require('../functions/satisfies')
+const gt = require('../functions/gt')
+const lt = require('../functions/lt')
+const lte = require('../functions/lte')
+const gte = require('../functions/gte')
+
+const outside = (version, range, hilo, options) => {
+ version = new SemVer(version, options)
+ range = new Range(range, options)
+
+ let gtfn, ltefn, ltfn, comp, ecomp
+ switch (hilo) {
+ case '>':
+ gtfn = gt
+ ltefn = lte
+ ltfn = lt
+ comp = '>'
+ ecomp = '>='
+ break
+ case '<':
+ gtfn = lt
+ ltefn = gte
+ ltfn = gt
+ comp = '<'
+ ecomp = '<='
+ break
+ default:
+ throw new TypeError('Must provide a hilo val of "<" or ">"')
+ }
+
+ // If it satisfies the range it is not outside
+ if (satisfies(version, range, options)) {
+ return false
+ }
+
+ // From now on, variable terms are as if we're in "gtr" mode.
+ // but note that everything is flipped for the "ltr" function.
+
+ for (let i = 0; i < range.set.length; ++i) {
+ const comparators = range.set[i]
+
+ let high = null
+ let low = null
+
+ comparators.forEach((comparator) => {
+ if (comparator.semver === ANY) {
+ comparator = new Comparator('>=0.0.0')
+ }
+ high = high || comparator
+ low = low || comparator
+ if (gtfn(comparator.semver, high.semver, options)) {
+ high = comparator
+ } else if (ltfn(comparator.semver, low.semver, options)) {
+ low = comparator
+ }
+ })
+
+ // If the edge version comparator has a operator then our version
+ // isn't outside it
+ if (high.operator === comp || high.operator === ecomp) {
+ return false
+ }
+
+ // If the lowest version comparator has an operator and our version
+ // is less than it then it isn't higher than the range
+ if ((!low.operator || low.operator === comp) &&
+ ltefn(version, low.semver)) {
+ return false
+ } else if (low.operator === ecomp && ltfn(version, low.semver)) {
+ return false
+ }
+ }
+ return true
+}
+
+module.exports = outside
diff --git a/MistyCore/node_modules/semver/ranges/simplify.js b/MistyCore/node_modules/semver/ranges/simplify.js
new file mode 100644
index 0000000..618d5b6
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/simplify.js
@@ -0,0 +1,47 @@
+// given a set of versions and a range, create a "simplified" range
+// that includes the same versions that the original range does
+// If the original range is shorter than the simplified one, return that.
+const satisfies = require('../functions/satisfies.js')
+const compare = require('../functions/compare.js')
+module.exports = (versions, range, options) => {
+ const set = []
+ let first = null
+ let prev = null
+ const v = versions.sort((a, b) => compare(a, b, options))
+ for (const version of v) {
+ const included = satisfies(version, range, options)
+ if (included) {
+ prev = version
+ if (!first) {
+ first = version
+ }
+ } else {
+ if (prev) {
+ set.push([first, prev])
+ }
+ prev = null
+ first = null
+ }
+ }
+ if (first) {
+ set.push([first, null])
+ }
+
+ const ranges = []
+ for (const [min, max] of set) {
+ if (min === max) {
+ ranges.push(min)
+ } else if (!max && min === v[0]) {
+ ranges.push('*')
+ } else if (!max) {
+ ranges.push(`>=${min}`)
+ } else if (min === v[0]) {
+ ranges.push(`<=${max}`)
+ } else {
+ ranges.push(`${min} - ${max}`)
+ }
+ }
+ const simplified = ranges.join(' || ')
+ const original = typeof range.raw === 'string' ? range.raw : String(range)
+ return simplified.length < original.length ? simplified : range
+}
diff --git a/MistyCore/node_modules/semver/ranges/subset.js b/MistyCore/node_modules/semver/ranges/subset.js
new file mode 100644
index 0000000..e0dea43
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/subset.js
@@ -0,0 +1,244 @@
+const Range = require('../classes/range.js')
+const Comparator = require('../classes/comparator.js')
+const { ANY } = Comparator
+const satisfies = require('../functions/satisfies.js')
+const compare = require('../functions/compare.js')
+
+// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff:
+// - Every simple range `r1, r2, ...` is a null set, OR
+// - Every simple range `r1, r2, ...` which is not a null set is a subset of
+// some `R1, R2, ...`
+//
+// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff:
+// - If c is only the ANY comparator
+// - If C is only the ANY comparator, return true
+// - Else if in prerelease mode, return false
+// - else replace c with `[>=0.0.0]`
+// - If C is only the ANY comparator
+// - if in prerelease mode, return true
+// - else replace C with `[>=0.0.0]`
+// - Let EQ be the set of = comparators in c
+// - If EQ is more than one, return true (null set)
+// - Let GT be the highest > or >= comparator in c
+// - Let LT be the lowest < or <= comparator in c
+// - If GT and LT, and GT.semver > LT.semver, return true (null set)
+// - If any C is a = range, and GT or LT are set, return false
+// - If EQ
+// - If GT, and EQ does not satisfy GT, return true (null set)
+// - If LT, and EQ does not satisfy LT, return true (null set)
+// - If EQ satisfies every C, return true
+// - Else return false
+// - If GT
+// - If GT.semver is lower than any > or >= comp in C, return false
+// - If GT is >=, and GT.semver does not satisfy every C, return false
+// - If GT.semver has a prerelease, and not in prerelease mode
+// - If no C has a prerelease and the GT.semver tuple, return false
+// - If LT
+// - If LT.semver is greater than any < or <= comp in C, return false
+// - If LT is <=, and LT.semver does not satisfy every C, return false
+// - If GT.semver has a prerelease, and not in prerelease mode
+// - If no C has a prerelease and the LT.semver tuple, return false
+// - Else return true
+
+const subset = (sub, dom, options = {}) => {
+ if (sub === dom) {
+ return true
+ }
+
+ sub = new Range(sub, options)
+ dom = new Range(dom, options)
+ let sawNonNull = false
+
+ OUTER: for (const simpleSub of sub.set) {
+ for (const simpleDom of dom.set) {
+ const isSub = simpleSubset(simpleSub, simpleDom, options)
+ sawNonNull = sawNonNull || isSub !== null
+ if (isSub) {
+ continue OUTER
+ }
+ }
+ // the null set is a subset of everything, but null simple ranges in
+ // a complex range should be ignored. so if we saw a non-null range,
+ // then we know this isn't a subset, but if EVERY simple range was null,
+ // then it is a subset.
+ if (sawNonNull) {
+ return false
+ }
+ }
+ return true
+}
+
+const simpleSubset = (sub, dom, options) => {
+ if (sub === dom) {
+ return true
+ }
+
+ if (sub.length === 1 && sub[0].semver === ANY) {
+ if (dom.length === 1 && dom[0].semver === ANY) {
+ return true
+ } else if (options.includePrerelease) {
+ sub = [new Comparator('>=0.0.0-0')]
+ } else {
+ sub = [new Comparator('>=0.0.0')]
+ }
+ }
+
+ if (dom.length === 1 && dom[0].semver === ANY) {
+ if (options.includePrerelease) {
+ return true
+ } else {
+ dom = [new Comparator('>=0.0.0')]
+ }
+ }
+
+ const eqSet = new Set()
+ let gt, lt
+ for (const c of sub) {
+ if (c.operator === '>' || c.operator === '>=') {
+ gt = higherGT(gt, c, options)
+ } else if (c.operator === '<' || c.operator === '<=') {
+ lt = lowerLT(lt, c, options)
+ } else {
+ eqSet.add(c.semver)
+ }
+ }
+
+ if (eqSet.size > 1) {
+ return null
+ }
+
+ let gtltComp
+ if (gt && lt) {
+ gtltComp = compare(gt.semver, lt.semver, options)
+ if (gtltComp > 0) {
+ return null
+ } else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) {
+ return null
+ }
+ }
+
+ // will iterate one or zero times
+ for (const eq of eqSet) {
+ if (gt && !satisfies(eq, String(gt), options)) {
+ return null
+ }
+
+ if (lt && !satisfies(eq, String(lt), options)) {
+ return null
+ }
+
+ for (const c of dom) {
+ if (!satisfies(eq, String(c), options)) {
+ return false
+ }
+ }
+
+ return true
+ }
+
+ let higher, lower
+ let hasDomLT, hasDomGT
+ // if the subset has a prerelease, we need a comparator in the superset
+ // with the same tuple and a prerelease, or it's not a subset
+ let needDomLTPre = lt &&
+ !options.includePrerelease &&
+ lt.semver.prerelease.length ? lt.semver : false
+ let needDomGTPre = gt &&
+ !options.includePrerelease &&
+ gt.semver.prerelease.length ? gt.semver : false
+ // exception: <1.2.3-0 is the same as <1.2.3
+ if (needDomLTPre && needDomLTPre.prerelease.length === 1 &&
+ lt.operator === '<' && needDomLTPre.prerelease[0] === 0) {
+ needDomLTPre = false
+ }
+
+ for (const c of dom) {
+ hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='
+ hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='
+ if (gt) {
+ if (needDomGTPre) {
+ if (c.semver.prerelease && c.semver.prerelease.length &&
+ c.semver.major === needDomGTPre.major &&
+ c.semver.minor === needDomGTPre.minor &&
+ c.semver.patch === needDomGTPre.patch) {
+ needDomGTPre = false
+ }
+ }
+ if (c.operator === '>' || c.operator === '>=') {
+ higher = higherGT(gt, c, options)
+ if (higher === c && higher !== gt) {
+ return false
+ }
+ } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) {
+ return false
+ }
+ }
+ if (lt) {
+ if (needDomLTPre) {
+ if (c.semver.prerelease && c.semver.prerelease.length &&
+ c.semver.major === needDomLTPre.major &&
+ c.semver.minor === needDomLTPre.minor &&
+ c.semver.patch === needDomLTPre.patch) {
+ needDomLTPre = false
+ }
+ }
+ if (c.operator === '<' || c.operator === '<=') {
+ lower = lowerLT(lt, c, options)
+ if (lower === c && lower !== lt) {
+ return false
+ }
+ } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) {
+ return false
+ }
+ }
+ if (!c.operator && (lt || gt) && gtltComp !== 0) {
+ return false
+ }
+ }
+
+ // if there was a < or >, and nothing in the dom, then must be false
+ // UNLESS it was limited by another range in the other direction.
+ // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0
+ if (gt && hasDomLT && !lt && gtltComp !== 0) {
+ return false
+ }
+
+ if (lt && hasDomGT && !gt && gtltComp !== 0) {
+ return false
+ }
+
+ // we needed a prerelease range in a specific tuple, but didn't get one
+ // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0,
+ // because it includes prereleases in the 1.2.3 tuple
+ if (needDomGTPre || needDomLTPre) {
+ return false
+ }
+
+ return true
+}
+
+// >=1.2.3 is lower than >1.2.3
+const higherGT = (a, b, options) => {
+ if (!a) {
+ return b
+ }
+ const comp = compare(a.semver, b.semver, options)
+ return comp > 0 ? a
+ : comp < 0 ? b
+ : b.operator === '>' && a.operator === '>=' ? b
+ : a
+}
+
+// <=1.2.3 is higher than <1.2.3
+const lowerLT = (a, b, options) => {
+ if (!a) {
+ return b
+ }
+ const comp = compare(a.semver, b.semver, options)
+ return comp < 0 ? a
+ : comp > 0 ? b
+ : b.operator === '<' && a.operator === '<=' ? b
+ : a
+}
+
+module.exports = subset
diff --git a/MistyCore/node_modules/semver/ranges/to-comparators.js b/MistyCore/node_modules/semver/ranges/to-comparators.js
new file mode 100644
index 0000000..6c8bc7e
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/to-comparators.js
@@ -0,0 +1,8 @@
+const Range = require('../classes/range')
+
+// Mostly just for testing and legacy API reasons
+const toComparators = (range, options) =>
+ new Range(range, options).set
+ .map(comp => comp.map(c => c.value).join(' ').trim().split(' '))
+
+module.exports = toComparators
diff --git a/MistyCore/node_modules/semver/ranges/valid.js b/MistyCore/node_modules/semver/ranges/valid.js
new file mode 100644
index 0000000..365f356
--- /dev/null
+++ b/MistyCore/node_modules/semver/ranges/valid.js
@@ -0,0 +1,11 @@
+const Range = require('../classes/range')
+const validRange = (range, options) => {
+ try {
+ // Return '*' instead of '' so that truthiness works.
+ // This will throw if it's invalid anyway
+ return new Range(range, options).range || '*'
+ } catch (er) {
+ return null
+ }
+}
+module.exports = validRange
diff --git a/MistyCore/node_modules/supports-color/browser.js b/MistyCore/node_modules/supports-color/browser.js
new file mode 100644
index 0000000..62afa3a
--- /dev/null
+++ b/MistyCore/node_modules/supports-color/browser.js
@@ -0,0 +1,5 @@
+'use strict';
+module.exports = {
+ stdout: false,
+ stderr: false
+};
diff --git a/MistyCore/node_modules/supports-color/index.js b/MistyCore/node_modules/supports-color/index.js
new file mode 100644
index 0000000..6fada39
--- /dev/null
+++ b/MistyCore/node_modules/supports-color/index.js
@@ -0,0 +1,135 @@
+'use strict';
+const os = require('os');
+const tty = require('tty');
+const hasFlag = require('has-flag');
+
+const {env} = process;
+
+let forceColor;
+if (hasFlag('no-color') ||
+ hasFlag('no-colors') ||
+ hasFlag('color=false') ||
+ hasFlag('color=never')) {
+ forceColor = 0;
+} else if (hasFlag('color') ||
+ hasFlag('colors') ||
+ hasFlag('color=true') ||
+ hasFlag('color=always')) {
+ forceColor = 1;
+}
+
+if ('FORCE_COLOR' in env) {
+ if (env.FORCE_COLOR === 'true') {
+ forceColor = 1;
+ } else if (env.FORCE_COLOR === 'false') {
+ forceColor = 0;
+ } else {
+ forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
+ }
+}
+
+function translateLevel(level) {
+ if (level === 0) {
+ return false;
+ }
+
+ return {
+ level,
+ hasBasic: true,
+ has256: level >= 2,
+ has16m: level >= 3
+ };
+}
+
+function supportsColor(haveStream, streamIsTTY) {
+ if (forceColor === 0) {
+ return 0;
+ }
+
+ if (hasFlag('color=16m') ||
+ hasFlag('color=full') ||
+ hasFlag('color=truecolor')) {
+ return 3;
+ }
+
+ if (hasFlag('color=256')) {
+ return 2;
+ }
+
+ if (haveStream && !streamIsTTY && forceColor === undefined) {
+ return 0;
+ }
+
+ const min = forceColor || 0;
+
+ if (env.TERM === 'dumb') {
+ return min;
+ }
+
+ if (process.platform === 'win32') {
+ // Windows 10 build 10586 is the first Windows release that supports 256 colors.
+ // Windows 10 build 14931 is the first release that supports 16m/TrueColor.
+ const osRelease = os.release().split('.');
+ if (
+ Number(osRelease[0]) >= 10 &&
+ Number(osRelease[2]) >= 10586
+ ) {
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
+ }
+
+ return 1;
+ }
+
+ if ('CI' in env) {
+ if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
+ return 1;
+ }
+
+ return min;
+ }
+
+ if ('TEAMCITY_VERSION' in env) {
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
+ }
+
+ if (env.COLORTERM === 'truecolor') {
+ return 3;
+ }
+
+ if ('TERM_PROGRAM' in env) {
+ const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
+
+ switch (env.TERM_PROGRAM) {
+ case 'iTerm.app':
+ return version >= 3 ? 3 : 2;
+ case 'Apple_Terminal':
+ return 2;
+ // No default
+ }
+ }
+
+ if (/-256(color)?$/i.test(env.TERM)) {
+ return 2;
+ }
+
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
+ return 1;
+ }
+
+ if ('COLORTERM' in env) {
+ return 1;
+ }
+
+ return min;
+}
+
+function getSupportLevel(stream) {
+ const level = supportsColor(stream, stream && stream.isTTY);
+ return translateLevel(level);
+}
+
+module.exports = {
+ supportsColor: getSupportLevel,
+ stdout: translateLevel(supportsColor(true, tty.isatty(1))),
+ stderr: translateLevel(supportsColor(true, tty.isatty(2)))
+};
diff --git a/MistyCore/node_modules/supports-color/license b/MistyCore/node_modules/supports-color/license
new file mode 100644
index 0000000..e7af2f7
--- /dev/null
+++ b/MistyCore/node_modules/supports-color/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MistyCore/node_modules/supports-color/package.json b/MistyCore/node_modules/supports-color/package.json
new file mode 100644
index 0000000..f7182ed
--- /dev/null
+++ b/MistyCore/node_modules/supports-color/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "supports-color",
+ "version": "7.2.0",
+ "description": "Detect whether a terminal supports color",
+ "license": "MIT",
+ "repository": "chalk/supports-color",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "scripts": {
+ "test": "xo && ava"
+ },
+ "files": [
+ "index.js",
+ "browser.js"
+ ],
+ "keywords": [
+ "color",
+ "colour",
+ "colors",
+ "terminal",
+ "console",
+ "cli",
+ "ansi",
+ "styles",
+ "tty",
+ "rgb",
+ "256",
+ "shell",
+ "xterm",
+ "command-line",
+ "support",
+ "supports",
+ "capability",
+ "detect",
+ "truecolor",
+ "16m"
+ ],
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "devDependencies": {
+ "ava": "^1.4.1",
+ "import-fresh": "^3.0.0",
+ "xo": "^0.24.0"
+ },
+ "browser": "browser.js"
+}
diff --git a/MistyCore/node_modules/supports-color/readme.md b/MistyCore/node_modules/supports-color/readme.md
new file mode 100644
index 0000000..3654228
--- /dev/null
+++ b/MistyCore/node_modules/supports-color/readme.md
@@ -0,0 +1,76 @@
+# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color)
+
+> Detect whether a terminal supports color
+
+
+## Install
+
+```
+$ npm install supports-color
+```
+
+
+## Usage
+
+```js
+const supportsColor = require('supports-color');
+
+if (supportsColor.stdout) {
+ console.log('Terminal stdout supports color');
+}
+
+if (supportsColor.stdout.has256) {
+ console.log('Terminal stdout supports 256 colors');
+}
+
+if (supportsColor.stderr.has16m) {
+ console.log('Terminal stderr supports 16 million colors (truecolor)');
+}
+```
+
+
+## API
+
+Returns an `Object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported.
+
+The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag:
+
+- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors)
+- `.level = 2` and `.has256 = true`: 256 color support
+- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors)
+
+
+## Info
+
+It obeys the `--color` and `--no-color` CLI flags.
+
+For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
+
+Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
+
+
+## Related
+
+- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module
+- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
+
+
+## Maintainers
+
+- [Sindre Sorhus](https://github.com/sindresorhus)
+- [Josh Junon](https://github.com/qix-)
+
+
+---
+
+<div align="center">
+ <b>
+ <a href="https://tidelift.com/subscription/pkg/npm-supports-color?utm_source=npm-supports-color&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
+ </b>
+ <br>
+ <sub>
+ Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
+ </sub>
+</div>
+
+---
diff --git a/MistyCore/node_modules/systeminformation/LICENSE b/MistyCore/node_modules/systeminformation/LICENSE
new file mode 100644
index 0000000..1ef622c
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2022 Sebastian Hildebrandt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MistyCore/node_modules/systeminformation/README.md b/MistyCore/node_modules/systeminformation/README.md
new file mode 100644
index 0000000..13e9008
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/README.md
@@ -0,0 +1,1088 @@
+<p align="center">
+ <a href="https://systeminformation.io/">
+ <img src="https://systeminformation.io/assets/logo_inv.png" alt="systeminformation logo" width="102" height="72">
+ </a>
+</p>
+
+<h3 align="center">systeminformation</h3>
+
+<p align="center">
+ System and OS information library for node.js
+ <br>
+ <a href="https://systeminformation.io/"><strong>Explore Systeminformation docs »</strong></a>
+ <br>
+ <br>
+ <a href="https://github.com/sebhildebrandt/systeminformation/issues/new?template=bug_report.md">Report bug</a>
+ ·
+ <a href="https://github.com/sebhildebrandt/systeminformation/issues/new?template=feature_request.md&labels=feature">Request feature</a>
+ ·
+ <a href="https://github.com/sebhildebrandt/systeminformation/blob/master/CHANGELOG.md">Changelog</a>
+</p>
+
+ [![NPM Version][npm-image]][npm-url]
+ [![NPM Downloads][downloads-image]][downloads-url]
+ [![Git Issues][issues-img]][issues-url]
+ [![Closed Issues][closed-issues-img]][closed-issues-url]
+ <img src="docs/assets/no-dependencies.svg" alt="no dependencies">
+ [![Code Quality: Javascript][lgtm-badge]][lgtm-badge-url]
+ [![Total alerts][lgtm-alerts]][lgtm-alerts-url]
+ [![Caretaker][caretaker-image]][caretaker-url]
+ [![Sponsoring][sponsor-badge]][sponsor-url]
+ [![MIT license][license-img]][license-url]
+
+This is amazing. Started as a small project just for myself, it now has > 15,000 lines of code, > 500 versions published, up to 5 mio downloads per month, > 100 mio downloads overall. #1 NPM ranking for backend packages. Thank you to all who contributed to this project!
+
+## New Version 5.0
+
+The new Version 5 is here - I spend several weeks finalizing this new version. Any support is highly appreciated - [Buy me a coffee](https://www.buymeacoffee.com/systeminfo)
+
+This next major version release 5.0 comes with new functionality and several improvements and changes (some of them are breaking changes!):
+
+- added audio: get detailed audio device information
+- added bluetooth: get detailed bluetooth device information
+- added dockerImages, dockerVolumes: get detailed information about docker images and volumes
+- added printer: get information from detected printers
+- added usb: get detailed usb controller and device information
+- added wifi interfaces ans connections: extended wifi information
+- better uuid function to get unique hardware and OS UUIDs
+- better/extended cpu info detection
+- better/extended system info detection
+- Apple Silicon M1 support
+- better Raspberry-PI detection
+- systeminformation website updated and extendet with full documentation and examples [systeminformation.io][systeminformation-url]
+- lot of minor improvements
+
+Breaking Changes in version 5: you will see several breaking changes for the sake of a more consistent API interface and to be future proof. Read the [detailed version 5 changes][changes5-url].
+
+I did a lot of testing on different platforms and machines but of course there might be some issues that I am not aware of. I would be happy if you inform me when you discover any issues. Issues can be [opened here][new-issue].
+
+## Quick Start
+
+Lightweight collection of 50+ functions to retrieve detailed hardware, system and OS information.
+
+- simple to use
+- get detailed information about system, cpu, baseboard, battery, memory, disks/filesystem, network, docker, software, services and processes
+- supports Linux, macOS, partial Windows, FreeBSD, OpenBSD, NetBSD, SunOS and Android support
+- no npm dependencies
+
+**Attention**: this is a `node.js` library. It is supposed to be used as a backend/server-side library and will definitely not work within a browser.
+
+### Installation
+
+```bash
+npm install systeminformation --save
+```
+
+or simpler
+
+```bash
+npm install systeminformation
+```
+
+#### Still need Version 4?
+
+If you need version 4 (for compatibility reasons), you can install version 4 (latest release) like this
+
+```bash
+npm install systeminformation@4 —save
+```
+
+or simpler
+
+```bash
+npm install systeminformation@4
+```
+
+### Usage
+
+All functions (except `version` and `time`) are implemented as asynchronous functions. Here a small example how to use them:
+
+```js
+const si = require('systeminformation');
+
+// promises style - new since version 3
+si.cpu()
+ .then(data => console.log(data))
+ .catch(error => console.error(error));
+```
+
+## News and Changes
+
+### Latest Activity
+
+(last 7 major and minor version releases)
+
+- Version 5.12.0: `cpu()` added performance and efficiency cores
+- Version 5.11.0: `networkInterfaces()` added default property and default parameter
+- Version 5.10.0: basic `android` support
+- Version 5.9.0: `graphics()` added properties (macOS)
+- Version 5.8.0: `disksIO()` added waitTime, waitPercent (linux)
+- Version 5.7.0: `diskLayout()` added S.M.A.R.T for Windows (if installed)
+- Version 5.6.0: `cpuTemperature()` added added socket and chipset temp (linux)
+- Version 5.5.0: `dockerVolumes()` added
+- Version 5.4.0: `dockerImages()` added
+- Version 5.3.0: `osInfo()` added remoteSession (win only)
+- Version 5.2.0: `wifiInterfaces()` and `wifiConnections()` added
+- Version 5.1.0: `memLayout()` added ECC flag, `bios()` added language, features (linux)
+- Version 5.0.0: new version 5 - attention there are some breaking changes. See [detailed version 5 changes here][changes5-url].
+- ...
+
+You can find all changes here: [detailed changelog][changelog-url]
+
+## Core concept
+
+[Node.js][nodejs-url] comes with some basic OS information, but I always wanted a little more. So I came up to write this little library. This library is still work in progress. It is supposed to be used as a backend/server-side library (will definitely not work within a browser). It requires node.js version 4.0 and above.
+
+I was able to test it on several Debian, Raspbian, Ubuntu distributions as well as macOS (Mavericks, Yosemite, El Captain, Sierra, High Sierra, Mojave, Catalina, Big Sur) and some Windows 7, Windows 8, Windows 10, FreeBSD, OpenBSD, NetBSD and SunOS machines. Not all functions are supported on all operating systems. Have a look at the function reference in the docs to get further details.
+
+If you have comments, suggestions & reports, please feel free to contact me!
+
+
+I also created a nice little command line tool called [mmon][mmon-github-url] (micro-monitor) for Linux and macOS, also available via [github][mmon-github-url] and [npm][mmon-npm-url]
+
+
+## Reference
+
+### Function Reference and OS Support
+
+Full function reference with examples can be found at [https://systeminformation.io][systeminformation-url].
+
+#### 1. General
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.version() | : string | X | X | X | X | X | lib version (no callback/promise) |
+| si.time() | {...} | X | X | X | X | X | (no callback/promise) |
+| | current | X | X | X | X | X | local (server) time |
+| | uptime | X | X | X | X | X | uptime in number of seconds |
+| | timezone | X | X | X | X | X | e.g. GMT+0200 |
+| | timezoneName | X | X | X | X | X | e.g. CEST |
+
+#### 2. System (HW)
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.system(cb) | {...} | X | X | X | X | | hardware information |
+| | manufacturer | X | X | X | X | | e.g. 'MSI' |
+| | model | X | X | X | X | | model/product e.g. 'MS-7823' |
+| | version | X | X | X | X | | version e.g. '1.0' |
+| | serial | X | X | X | X | | serial number |
+| | uuid | X | X | X | X | | UUID |
+| | sku | X | X | X | X | | SKU number |
+| | virtual | X | X | | X | | is virtual machine |
+| | virtualHost | X | X | | X | | virtual host (if virtual) |
+| | raspberry | X | | | | | optional raspberry revision data |
+| si.bios(cb) | {...} | X | X | X | X | | bios information |
+| | vendor | X | X | X | X | | e.g. 'AMI' |
+| | version | X | X | X | X | | version |
+| | releaseDate | X | X | | X | | release date |
+| | revision | X | X | | X | | revision |
+| | serial | X | | | X | | serial |
+| si.baseboard(cb) | {...} | X | X | X | X | | baseboard information |
+| | manufacturer | X | X | X | X | | e.g. 'ASUS' |
+| | model | X | X | X | X | | model / product name |
+| | version | X | X | X | X | | version |
+| | serial | X | X | X | X | | serial number |
+| | assetTag | X | X | X | X | | asset tag |
+| | memMax | X | | X | X | | max memory in bytes |
+| | memSlots | X | | X | X | | memory slots on baseboard |
+| si.chassis(cb) | {...} | X | X | X | X | | chassis information |
+| | manufacturer | X | X | X | X | | e.g. 'MSI' |
+| | model | X | X | X | X | | model / product name |
+| | type | X | X | X | X | | model / product name |
+| | version | X | X | X | X | | version |
+| | serial | X | X | X | X | | serial number |
+| | assetTag | X | X | X | X | | asset tag |
+| | sku | | | | X | | SKU number |
+
+#### 3. CPU
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.cpu(cb) | {...} | X | X | X | X | | CPU information|
+| | manufacturer | X | X | X | X | | e.g. 'Intel(R)' |
+| | brand | X | X | X | X | | e.g. 'Core(TM)2 Duo' |
+| | speed | X | X | X | X | | in GHz e.g. '3.40' |
+| | speedMin | X | | X | X | | in GHz e.g. '0.80' |
+| | speedMax | X | X | X | X | | in GHz e.g. '3.90' |
+| | governor | X | | | | | e.g. 'powersave' |
+| | cores | X | X | X | X | | # cores |
+| | physicalCores | X | X | X | X | | # physical cores |
+| | efficiencyCores | X | | X | | | # efficiency cores |
+| | performanceCores | X | | X | | | # performance cores |
+| | processors | X | X | X | X | | # processors |
+| | socket | X | X | | X | | socket type e.g. "LGA1356" |
+| | vendor | X | X | X | X | | vendor ID |
+| | family | X | X | X | X | | processor family |
+| | model | X | X | X | X | | processor model |
+| | stepping | X | X | X | X | | processor stepping |
+| | revision | X | | X | X | | revision |
+| | voltage | | X | | | | voltage |
+| | flags | X | X | X | X | | CPU flags |
+| | virtualization | X | X | X | X | | virtualization supported |
+| | cache | X | X | X | X | | cache in bytes (object) |
+| | cache.l1d | X | X | X | X | | L1D (data) size |
+| | cache.l1i | X | X | X | X | | L1I (instruction) size |
+| | cache.l2 | X | X | X | X | | L2 size |
+| | cache.l3 | X | X | X | X | | L3 size |
+| si.cpuFlags(cb) | : string | X | X | X | X | | CPU flags|
+| si.cpuCache(cb) | {...} | X | X | X | X | | CPU cache sizes |
+| | l1d | X | X | X | X | | L1D size |
+| | l1i | X | X | X | X | | L1I size |
+| | l2 | X | X | X | X | | L2 size |
+| | l3 | X | X | X | X | | L3 size |
+| si.cpuCurrentSpeed(cb) | {...} | X | X | X | X | X | current CPU speed (in GHz)|
+| | avg | X | X | X | X | X | avg CPU speed (all cores) |
+| | min | X | X | X | X | X | min CPU speed (all cores) |
+| | max | X | X | X | X | X | max CPU speed (all cores) |
+| | cores | X | X | X | X | X | CPU speed per core (array) |
+| si.cpuTemperature(cb) | {...} | X | X | X* | X | | CPU temperature in C (if supported) |
+| | main | X | X | X | X | | main temperature (avg) |
+| | cores | X | X | X | X | | array of temperatures |
+| | max | X | X | X | X | | max temperature |
+| | socket | X | | | | | array socket temperatures |
+| | chipset | X | | | | | chipset temperature |
+
+#### 4. Memory
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.mem(cb) | {...} | X | X | X | X | X | Memory information (in bytes)|
+| | total | X | X | X | X | X | total memory in bytes |
+| | free | X | X | X | X | X | not used in bytes |
+| | used | X | X | X | X | X | used (incl. buffers/cache) |
+| | active | X | X | X | X | X | used actively (excl. buffers/cache) |
+| | buffcache | X | X | X | | X | used by buffers+cache |
+| | buffers | X | | | | | used by buffers |
+| | cached | X | | | | | used by cache |
+| | slab | X | | | | | used by slab |
+| | available | X | X | X | X | X | potentially available (total - active) |
+| | swaptotal | X | X | X | X | X | |
+| | swapused | X | X | X | X | X | |
+| | swapfree | X | X | X | X | X | |
+| si.memLayout(cb) | [{...}] | X | X | X | X | | Memory Layout (array) |
+| | [0].size | X | X | X | X | | size in bytes |
+| | [0].bank | X | X | | X | | memory bank |
+| | [0].type | X | X | X | X | | memory type |
+| | [0].clockSpeed | X | X | X | X | | clock speed |
+| | [0].formFactor | X | X | | X | | form factor |
+| | [0].manufacturer | X | X | X | X | | manufacturer |
+| | [0].partNum | X | X | X | X | | part number |
+| | [0].serialNum | X | X | X | X | | serial number |
+| | [0].voltageConfigured | X | X | | X | | voltage conf. |
+| | [0].voltageMin | X | X | | X | | voltage min |
+| | [0].voltageMax | X | X | | X | | voltage max |
+
+#### 5. Battery
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.battery(cb) | {...} | X | X | X | X | | battery information |
+| | hasBattery | X | X | X | X | | indicates presence of battery |
+| | cycleCount | X | | X | | | numbers of recharges |
+| | isCharging | X | X | X | X | | indicates if battery is charging |
+| | designedCapacity | X | | X | X | | max capacity of battery (mWh) |
+| | maxCapacity | X | | X | X | | max capacity of battery (mWh) |
+| | currentCapacity | X | | X | X | | current capacity of battery (mWh) |
+| | capacityUnit | X | | X | X | | capacity unit (mWh) |
+| | voltage | X | | X | X | | current voltage of battery (V) |
+| | percent | X | X | X | X | | charging level in percent |
+| | timeRemaining | X | | X | | | minutes left (if discharging) |
+| | acConnected | X | X | X | X | | AC connected |
+| | type | X | | X | | | battery type |
+| | model | X | | X | | | model |
+| | manufacturer | X | | X | | | manufacturer |
+| | serial | X | | X | | | battery serial |
+
+* See known issues if you have problem with macOS temperature or windows temperature
+
+#### 6. Graphics
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.graphics(cb) | {...} | X | | X | X | | arrays of graphics controllers and displays |
+| | controllers[]| X | | X | X | | graphics controllers array |
+| | ...[0].vendor | X | | X | X | | e.g. ATI |
+| | ...[0].vendorId | | | X | | | vendor ID |
+| | ...[0].model | X | | X | X | | graphics controller model |
+| | ...[0].deviceId | | | X | | | device ID |
+| | ...[0].bus | X | | X | X | | on which bus (e.g. PCIe) |
+| | ...[0].vram | X | | X | X | | VRAM size (in MB) |
+| | ...[0].vramDynamic | X | | X | X | | true if dynamicly allocated ram |
+| | ...[0].external | | | X | | | is external GPU |
+| | ...[0].cores | | | X | | | Apple silicon only |
+| | ...[0].metalVersion | | | X | | | Apple Metal Version |
+| | displays[] | X | | X | X | | monitor/display array |
+| | ...[0].vendor | | | | X | | monitor/display vendor |
+| | ...[0].vendorId | | | X | | | vendor ID |
+| | ...[0].deviceName | | | | X | | e.g. \\\\.\\DISPLAY1 |
+| | ...[0].model | X | | X | X | | monitor/display model |
+| | ...[0].productionYear | | | X | | | production year |
+| | ...[0].serial | | | X | | | serial number |
+| | ...[0].displayId | | | X | | | display ID |
+| | ...[0].main | X | | X | X| | true if main monitor |
+| | ...[0].builtin | X | | X | | | true if built in monitor |
+| | ...[0].connection | X | | X | X | | e.g. DisplayPort or HDMI |
+| | ...[0].sizeX | X | | | X | | size in mm horizontal |
+| | ...[0].sizeY | X | | | X | | size in mm vertical |
+| | ...[0].pixelDepth | X | | X | X | | color depth in bits |
+| | ...[0].resolutionX | X | | X | X | | pixel horizontal |
+| | ...[0].resolutionY | X | | X | X | | pixel vertical |
+| | ...[0].currentResX | X | | X | X | | current pixel horizontal |
+| | ...[0].currentResY | X | | X | X | | current pixel vertical |
+| | ...[0].positionX | | | | X | | display position X |
+| | ...[0].positionY | | | | X | | display position Y |
+| | ...[0].currentRefreshRate | X | | X | X | | current screen refresh rate |
+
+#### 7. Operating System
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.osInfo(cb) | {...} | X | X | X | X | X | OS information |
+| | platform | X | X | X | X | X | 'linux', 'darwin', 'win32', ... |
+| | distro | X | X | X | X | X | |
+| | release | X | X | X | X | X | |
+| | codename | | | X | | | |
+| | kernel | X | X | X | X | X | kernel release - same as os.release() |
+| | arch | X | X | X | X | X | same as os.arch() |
+| | hostname | X | X | X | X | X | same as os.hostname() |
+| | fqdn | X | X | X | X | X | FQDN fully qualified domain name |
+| | codepage | X | X | X | X | | OS build version |
+| | logofile | X | X | X | X | X | e.g. 'apple', 'debian', 'fedora', ... |
+| | serial | X | X | X | X | | OS/Host serial number |
+| | build | X | | X | X | | OS build version |
+| | servicepack | | | | X | | service pack version |
+| | uefi | X | X | X | X | | OS started via UEFI |
+| | hypervisor | | | | X | | hyper-v enabled? (win only) |
+| | remoteSession | | | | X | | runs in remote session (win only) |
+| si.uuid(cb) | {...} | X | X | X | X | X | object of several UUIDs |
+| | os | X | X | X | X | | os specific UUID |
+| | hardware | X | X | X | X | | hardware specific UUID |
+| | macs | X | X | X | X | | MAC addresses |
+| si.versions(apps, cb) | {...} | X | X | X | X | X | version information (kernel, ssl, node, ...)<br />apps param is optional for detecting<br />only specific apps/libs<br />(string, comma separated) |
+| si.shell(cb) | : string | X | X | X | X | | standard shell |
+| si.users(cb) | [{...}] | X | X | X | X | X | array of users online |
+| | [0].user | X | X | X | X | X | user name |
+| | [0].tty | X | X | X | X | X | terminal |
+| | [0].date | X | X | X | X | X | login date |
+| | [0].time | X | X | X | X | X | login time |
+| | [0].ip | X | X | X | | X | ip address (remote login) |
+| | [0].command | X | X | X | | X | last command or shell |
+
+#### 8. Current Load, Processes & Services
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.currentLoad(cb) | {...} | X | | X | X | X | CPU-Load |
+| | avgLoad | X | | X | | X | average load |
+| | currentLoad | X | | X | X | X | CPU load in % |
+| | currentLoadUser | X | | X | X | X | CPU load user in % |
+| | currentLoadSystem | X | | X | X | X | CPU load system in % |
+| | currentLoadNice | X | | X | X | X | CPU load nice in % |
+| | currentLoadIdle | X | | X | X | X | CPU load idle in % |
+| | currentLoadIrq | X | | X | X | X | CPU load system in % |
+| | rawCurrentLoad... | X | | X | X | X | CPU load raw values (ticks) |
+| | cpus[] | X | | X | X | X | current loads per CPU in % + raw ticks |
+| si.fullLoad(cb) | : integer | X | | X | X | | CPU full load since bootup in % |
+| si.processes(cb) | {...} | X | X | X | X | X | # running processes |
+| | all | X | X | X | X | X | # of all processes |
+| | running | X | X | X | | X | # of all processes running |
+| | blocked | X | X | X | | X | # of all processes blocked |
+| | sleeping | X | X | X | | X | # of all processes sleeping |
+| | unknown | | | | X | | # of all processes unknown status |
+| | list[] | X | X | X | X | X | list of all processes incl. details |
+| | ...[0].pid | X | X | X | X | X | process PID |
+| | ...[0].parentPid | X | X | X | X | X | parent process PID |
+| | ...[0].name | X | X | X | X | X | process name |
+| | ...[0].cpu | X | X | X | X | X | process % CPU usage |
+| | ...[0].cpuu | X | X | | X | | process % CPU usage (user) |
+| | ...[0].cpus | X | X | | X | | process % CPU usage (system) |
+| | ...[0].mem | X | X | X | X | X | process memory % |
+| | ...[0].priority | X | X | X | X | X | process priotity |
+| | ...[0].memVsz | X | X | X | X | X | process virtual memory size |
+| | ...[0].memRss | X | X | X | X | X | process mem resident set size |
+| | ...[0].nice | X | X | X | | X | process nice value |
+| | ...[0].started | X | X | X | X | X | process start time |
+| | ...[0].state | X | X | X | X | X | process state (e.g. sleeping) |
+| | ...[0].tty | X | X | X | | X | tty from which process was started |
+| | ...[0].user | X | X | X | | X | user who started process |
+| | ...[0].command | X | X | X | X | X | process starting command |
+| | ...[0].params | X | X | X | | X | process params |
+| | ...[0].path | X | X | X | X | X | process path |
+| | proc | X | X | X | X | | process name |
+| | pid | X | X | X | X | | PID |
+| | pids | X | X | X | X | | additional pids |
+| | cpu | X | X | X | X | | process % CPU |
+| | mem | X | X | X | X | | process % MEM |
+| si.services('mysql, apache2', cb) | [{...}] | X | X | X | X | | pass comma separated string of services<br>pass "*" for ALL services (linux/win only) |
+| | [0].name | X | X | X | X | | name of service |
+| | [0].running | X | X | X | X | | true / false |
+| | [0].startmode | | | | X | | manual, automatic, ... |
+| | [0].pids | X | X | X | X | | pids |
+| | [0].cpu | X | X | X | | | process % CPU |
+| | [0].mem | X | X | X | | | process % MEM |
+| si.processLoad('mysql, apache2', cb) | [{...}] | X | X | X | X | | pass comma separated string of processes<br>pass "*" for ALL processes (linux/win only) |
+| | [0].proc | X | X | X | X | | name of process |
+| | [0].pids | X | X | X | X | | pids |
+| | [0].cpu | X | X | X | | | process % CPU |
+| | [0].mem | X | X | X | | | process % MEM |
+
+#### 9. File System
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.diskLayout(cb) | [{...}] | X | | X | X | | physical disk layout (array) |
+| | [0].device | X | | X | | | e.g. /dev/sda |
+| | [0].type | X | | X | X | | HD, SSD, NVMe |
+| | [0].name | X | | X | X | | disk name |
+| | [0].vendor | X | | | X | | vendor/producer |
+| | [0].size | X | | X | X | | size in bytes |
+| | [0].bytesPerSector | | | | X | | bytes per sector |
+| | [0].totalCylinders | | | | X | | total cylinders |
+| | [0].totalHeads | | | | X | | total heads |
+| | [0].totalSectors | | | | X | | total sectors |
+| | [0].totalTracks | | | | X | | total tracks |
+| | [0].tracksPerCylinder | | | | X | | tracks per cylinder |
+| | [0].sectorsPerTrack | | | | X | | sectors per track |
+| | [0].firmwareRevision | X | | X | X | | firmware revision |
+| | [0].serialNum | X | | X | X | | serial number |
+| | [0].interfaceType | X | | | X | | SATA, PCIe, ... |
+| | [0].smartStatus | X | | X | X | | S.M.A.R.T Status (see Known Issues) |
+| | [0].temperature | X | | | | | S.M.A.R.T temperature |
+| | [0].smartData | X | | | X | | full S.M.A.R.T data from smartctl<br>requires at least smartmontools 7.0 |
+| si.blockDevices(cb) | [{...}] | X | | X | X | | returns array of disks, partitions,<br>raids and roms |
+| | [0].name | X | | X | X | | name |
+| | [0].type | X | | X | X | | type |
+| | [0].fstype | X | | X | X | | file system type (e.g. ext4) |
+| | [0].mount | X | | X | X | | mount point |
+| | [0].size | X | | X | X | | size in bytes |
+| | [0].physical | X | | X | X | | physical type (HDD, SSD, CD/DVD) |
+| | [0].uuid | X | | X | X | | UUID |
+| | [0].label | X | | X | X | | label |
+| | [0].model | X | | X | | | model |
+| | [0].serial | X | | | X | | serial |
+| | [0].removable | X | | X | X | | serial |
+| | [0].protocol | X | | X | | | protocol (SATA, PCI-Express, ...) |
+| si.disksIO(cb) | {...} | X | | X | | | current transfer stats |
+| | rIO | X | | X | | | read IOs on all mounted drives |
+| | wIO | X | | X | | | write IOs on all mounted drives |
+| | tIO | X | | X | | | write IOs on all mounted drives |
+| | rIO_sec | X | | X | | | read IO per sec (* see notes) |
+| | wIO_sec | X | | X | | | write IO per sec (* see notes) |
+| | tIO_sec | X | | X | | | total IO per sec (* see notes) |
+| | rWaitTime | X | | | | | read IO request time (* see notes) |
+| | wWaitTime | X | | | | | write IO request time (* see notes) |
+| | tWaitTime | X | | | | | total IO request time (* see notes) |
+| | rWaitPercent | X | | | | | read IO request time percent (* see notes) |
+| | wWaitPercent | X | | | | | write IO request time percent (* see notes) |
+| | tWaitPercent | X | | | | | total IO request time percent (* see notes) |
+| | ms | X | | X | | | interval length (for per second values) |
+| si.fsSize(cb) | [{...}] | X | X | X | X | | returns array of mounted file systems |
+| | [0].fs | X | X | X | X | | name of file system |
+| | [0].type | X | X | X | X | | type of file system |
+| | [0].size | X | X | X | X | | sizes in bytes |
+| | [0].used | X | X | X | X | | used in bytes |
+| | [0].available | X | X | X | X | | used in bytes |
+| | [0].use | X | X | X | X | | used in % |
+| | [0].mount | X | X | X | X | | mount point |
+| si.fsOpenFiles(cb) | {...} | X | X | X | | | count max/allocated file descriptors |
+| | max | X | X | X | | | max file descriptors |
+| | allocated | X | X | X | | | current open files count |
+| | available | X | X | X | | | count available |
+| si.fsStats(cb) | {...} | X | | X | | | current transfer stats |
+| | rx | X | | X | | | bytes read since startup |
+| | wx | X | | X | | | bytes written since startup |
+| | tx | X | | X | | | total bytes read + written since startup |
+| | rx_sec | X | | X | | | bytes read / second (* see notes) |
+| | wx_sec | X | | X | | | bytes written / second (* see notes) |
+| | tx_sec | X | | X | | | total bytes reads + written / second |
+| | ms | X | | X | | | interval length (for per second values) |
+
+#### 10. USB
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.usb(cb) | [{...}] | X | X | X | X | | get detected USB devices |
+| | [0].bus | X | | | | | USB bus |
+| | [0].deviceId | X | | | | | bus device id |
+| | [0].id | X | | X | X | | internal id |
+| | [0].name | X | | X | X | | name |
+| | [0].type | X | | X | X | | name |
+| | [0].removable | | | X | | | is removable |
+| | [0].vendor | X | | X | | | vendor |
+| | [0].manufacturer | X | | X | X | | manifacturer |
+| | [0].maxPower | X | | | | | max power |
+| | [0].default | X | | X | X | | is default printer |
+| | [0].serialNumber | | | X | | | serial number |
+
+#### 11. Printer
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.printer(cb) | [{...}] | X | X | X | X | | get printer information |
+| | [0].id | X | | X | X | | internal id |
+| | [0].name | X | | X | X | | name |
+| | [0].model | X | | X | X | | model |
+| | [0].uri | X | | X | | | printer URI |
+| | [0].uuid | X | | | | | printer UUID |
+| | [0].status | X | | X | X | | printer status (e.g. idle) |
+| | [0].local | X | | X | X | | is local printer |
+| | [0].default | | | X | X | | is default printer |
+| | [0].shared | X | | X | X | | is shared printer |
+
+#### 12. Audio
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.audio(cb) | [{...}] | X | X | X | X | | get printer information |
+| | [0].id | X | | X | X | | internal id |
+| | [0].name | X | | X | X | | name |
+| | [0].manufacturer | X | | X | X | | manufacturer |
+| | [0].revision | X | | | | | revision |
+| | [0].driver | X | | | | | driver |
+| | [0].default | | | X | X | | is default |
+| | [0].channel | X | | X | | | channel e.g. USB, HDMI, ... |
+| | [0].type | X | | X | X | | type e.g. Speaker |
+| | [0].in | | | X | X | | is input channel |
+| | [0].out | | | X | X | | is output channel |
+| | [0].interfaceType | X | | X | X | | interface type (PCIe, USB, HDMI, ...) |
+| | [0].status | X | | X | X | | printer status (e.g. idle) |
+
+#### 13. Network related functions
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.networkInterfaces(cb) | [{...}] | X | X | X | X | X | array of network interfaces<br>With the 'default' parameter it returns<br>only the default interface |
+| | [0].iface | X | X | X | X | X | interface |
+| | [0].ifaceName | X | X | X | X | X | interface name (differs on Windows) |
+| | [0].default | X | X | X | X | X | true if this is the default interface |
+| | [0].ip4 | X | X | X | X | X | ip4 address |
+| | [0].ip4subnet | X | X | X | X | X | ip4 subnet mask |
+| | [0].ip6 | X | X | X | X | X | ip6 address |
+| | [0].ip6subnet | X | X | X | X | X | ip6 subnet mask |
+| | [0].mac | X | X | X | X | X | MAC address |
+| | [0].internal | X | X | X | X | X | true if internal interface |
+| | [0].virtual | X | X | X | X | X | true if virtual interface |
+| | [0].operstate | X | | X | X | | up / down |
+| | [0].type | X | | X | X | | wireless / wired |
+| | [0].duplex | X | | X | | | duplex |
+| | [0].mtu | X | | X | | | maximum transmission unit |
+| | [0].speed | X | | X | X | | speed in MBit / s |
+| | [0].dhcp | X | | X | X | | IP address obtained by DHCP |
+| | [0].dnsSuffix | X | | | X | | DNS suffix |
+| | [0].ieee8021xAuth | X | | | X | | IEEE 802.1x auth |
+| | [0].ieee8021xState | X | | | X | | IEEE 802.1x state |
+| | [0].carrierChanges | X | | | | | # changes up/down |
+| si.networkInterfaceDefault(cb) | : string | X | X | X | X | X | get name of default network interface |
+| si.networkGatewayDefault(cb) | : string | X | X | X | X | X | get default network gateway |
+| si.networkStats(ifaces,cb) | [{...}] | X | X | X | X | | current network stats of given interfaces<br>iface list: space or comma separated<br>iface parameter is optional<br>defaults to first external network interface,<br />Pass '*' for all interfaces |
+| | [0].iface | X | X | X | X | | interface |
+| | [0].operstate | X | X | X | X | | up / down |
+| | [0].rx_bytes | X | X | X | X | | received bytes overall |
+| | [0].rx_dropped | X | X | X | X | | received dropped overall |
+| | [0].rx_errors | X | X | X | X | | received errors overall |
+| | [0].tx_bytes | X | X | X | X | | transferred bytes overall |
+| | [0].tx_dropped | X | X | X | X | | transferred dropped overall |
+| | [0].tx_errors | X | X | X | X | | transferred errors overall |
+| | [0].rx_sec | X | X | X | X | | received bytes / second (* see notes) |
+| | [0].tx_sec | X | X | X | X | | transferred bytes per second (* see notes) |
+| | [0].ms | X | X | X | X | | interval length (for per second values) |
+| si.networkConnections(cb) | [{...}] | X | X | X | X | | current network network connections<br>returns an array of all connections|
+| | [0].protocol | X | X | X | X | | tcp or udp |
+| | [0].localAddress | X | X | X | X | | local address |
+| | [0].localPort | X | X | X | X | | local port |
+| | [0].peerAddress | X | X | X | X | | peer address |
+| | [0].peerPort | X | X | X | X | | peer port |
+| | [0].state | X | X | X | X | | like ESTABLISHED, TIME_WAIT, ... |
+| | [0].pid | X | X | X | X | | process ID |
+| | [0].process | X | X | | | | process name |
+| si.inetChecksite(url, cb) | {...} | X | X | X | X | X | response-time (ms) to fetch given URL |
+| | url | X | X | X | X | X | given url |
+| | ok | X | X | X | X | X | status code OK (2xx, 3xx) |
+| | status | X | X | X | X | X | status code |
+| | ms | X | X | X | X | X | response time in ms |
+| si.inetLatency(host, cb) | : number | X | X | X | X | X | response-time (ms) to external resource<br>host parameter is optional (default 8.8.8.8)|
+
+#### 14. Wifi
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.wifiNetworks(cb) | [{...}] | X | | X | X | | array of available wifi networks |
+| | [0].ssid | X | | X | X | | Wifi network SSID |
+| | [0].bssid | X | | X | X | | BSSID (mac) |
+| | [0].mode | X | | | | | mode |
+| | [0].channel | X | | X | X | | channel |
+| | [0].frequency | X | | X | X | | frequengy in MHz |
+| | [0].signalLevel | X | | X | X | | signal level in dB |
+| | [0].quality | X | | X | X | | quaility in % |
+| | [0].security | X | | X | X | | array e.g. WPA, WPA-2 |
+| | [0].wpaFlags | X | | X | X | | array of WPA flags |
+| | [0].rsnFlags | X | | | | | array of RDN flags |
+| si.wifiInterfaces(cb) | [{...}] | X | | X | X | | array of detected wifi interfaces |
+| | [0].id | X | | X | X | | ID |
+| | [0].iface | X | | X | X | | interface |
+| | [0].model | X | | X | X | | model |
+| | [0].vendor | X | | X | X | | vendor |
+| | [0].mac | X | | X | X | | MAC address |
+| si.wifiConnections(cb) | [{...}] | X | | X | X | | array of active wifi connections |
+| | [0].id | X | | X | X | | ID |
+| | [0].iface | X | | X | X | | interface |
+| | [0].name | X | | X | X | | name |
+| | [0].mode | X | | X | X | | model |
+| | [0].bssid | X | | X | X | | BSSID (mac) |
+| | [0].mode | X | | | | | mode |
+| | [0].channel | X | | X | X | | channel |
+| | [0].frequency | X | | X | X | | frequengy in MHz |
+| | [0].signalLevel | X | | X | X | | signal level in dB |
+| | [0].quality | X | | X | X | | quaility in % |
+| | [0].security | X | | X | X | | array e.g. WPA, WPA-2 |
+| | [0].txRate | X | | X | X | | transfer rate MBit/s |
+
+#### 15. Bluetooth
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.bluetoothDevices(cb) | [{...}] | X | | X | X | | ... |
+| | [0].device | | | X | | | device name |
+| | [0].name | X | | X | X | | name |
+| | [0].macDevice | X | | X | | | MAC address device |
+| | [0].macHost | X | | X | | | MAC address host |
+| | [0].batteryPercent | | | X | | | battery level percent |
+| | [0].manufacturer | | | X | X | | manufacturer |
+| | [0].type | X | | X | X | | typoe of bluetooth device |
+| | [0].connected | X | | X | | | is connected |
+
+#### 16. Docker
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.dockerInfo(cb) | {...} | X | X | X | X | X | returns general docker info |
+| | id | X | X | X | X | X | Docker ID |
+| | containers | X | X | X | X | X | number of containers |
+| | containersRunning | X | X | X | X | X | number of running containers |
+| | containersPaused | X | X | X | X | X | number of paused containers |
+| | containersStopped | X | X | X | X | X | number of stopped containers |
+| | images | X | X | X | X | X | number of images |
+| | driver | X | X | X | X | X | driver (e.g. 'devicemapper', 'overlay2') |
+| | memoryLimit | X | X | X | X | X | has memory limit |
+| | swapLimit | X | X | X | X | X | has swap limit |
+| | kernelMemory | X | X | X | X | X | has kernal memory |
+| | cpuCfsPeriod | X | X | X | X | X | has CpuCfsPeriod |
+| | cpuCfsQuota | X | X | X | X | X | has CpuCfsQuota |
+| | cpuShares | X | X | X | X | X | has CPUShares |
+| | cpuSet | X | X | X | X | X | has CPUShares |
+| | ipv4Forwarding | X | X | X | X | X | has IPv4Forwarding |
+| | bridgeNfIptables | X | X | X | X | X | has BridgeNfIptables |
+| | bridgeNfIp6tables | X | X | X | X | X | has BridgeNfIp6tables |
+| | debug | X | X | X | X | X | Debug on |
+| | nfd | X | X | X | X | X | named data networking forwarding daemon |
+| | oomKillDisable | X | X | X | X | X | out-of-memory kill disabled |
+| | ngoroutines | X | X | X | X | X | number NGoroutines |
+| | systemTime | X | X | X | X | X | docker SystemTime |
+| | loggingDriver | X | X | X | X | X | logging driver e.g. 'json-file' |
+| | cgroupDriver | X | X | X | X | X | cgroup driver e.g. 'cgroupfs' |
+| | nEventsListener | X | X | X | X | X | number NEventsListeners |
+| | kernelVersion | X | X | X | X | X | docker kernel version |
+| | operatingSystem | X | X | X | X | X | docker OS e.g. 'Docker for Mac' |
+| | osType | X | X | X | X | X | OSType e.g. 'linux' |
+| | architecture | X | X | X | X | X | architecture e.g. x86_64 |
+| | ncpu | X | X | X | X | X | number of CPUs |
+| | memTotal | X | X | X | X | X | memory total |
+| | dockerRootDir | X | X | X | X | X | docker root directory |
+| | httpProxy | X | X | X | X | X | http proxy |
+| | httpsProxy | X | X | X | X | X | https proxy |
+| | noProxy | X | X | X | X | X | NoProxy |
+| | name | X | X | X | X | X | Name |
+| | labels | X | X | X | X | X | array of labels |
+| | experimentalBuild | X | X | X | X | X | is experimental build |
+| | serverVersion | X | X | X | X | X | server version |
+| | clusterStore | X | X | X | X | X | cluster store |
+| | clusterAdvertise | X | X | X | X | X | cluster advertise |
+| | defaultRuntime | X | X | X | X | X | default runtime e.g. 'runc' |
+| | liveRestoreEnabled | X | X | X | X | X | live store enabled |
+| | isolation | X | X | X | X | X | isolation |
+| | initBinary | X | X | X | X | X | init binary |
+| | productLicense | X | X | X | X | X | product license |
+| si.dockerImages(all, cb) | [{...}] | X | X | X | X | X | returns array of top level/all docker images |
+| | [0].id | X | X | X | X | X | image ID |
+| | [0].container | X | X | X | X | X | container ID |
+| | [0].comment | X | X | X | X | X | comment |
+| | [0].os | X | X | X | X | X | OS |
+| | [0].architecture | X | X | X | X | X | architecture |
+| | [0].parent | X | X | X | X | X | parent ID |
+| | [0].dockerVersion | X | X | X | X | X | docker version |
+| | [0].size | X | X | X | X | X | image size |
+| | [0].sharedSize | X | X | X | X | X | shared size |
+| | [0].virtualSize | X | X | X | X | X | virtual size |
+| | [0].author | X | X | X | X | X | author |
+| | [0].created | X | X | X | X | X | created date / time |
+| | [0].containerConfig | X | X | X | X | X | container config object |
+| | [0].graphDriver | X | X | X | X | X | graph driver object |
+| | [0].repoDigests | X | X | X | X | X | repo digests array |
+| | [0].repoTags | X | X | X | X | X | repo tags array |
+| | [0].config | X | X | X | X | X | config object |
+| | [0].rootFS | X | X | X | X | X | root fs object |
+| si.dockerContainers(all, cb) | [{...}] | X | X | X | X | X | returns array of active/all docker containers |
+| | [0].id | X | X | X | X | X | ID of container |
+| | [0].name | X | X | X | X | X | name of container |
+| | [0].image | X | X | X | X | X | name of image |
+| | [0].imageID | X | X | X | X | X | ID of image |
+| | [0].command | X | X | X | X | X | command |
+| | [0].created | X | X | X | X | X | creation time (unix) |
+| | [0].started | X | X | X | X | X | creation time (unix) |
+| | [0].finished | X | X | X | X | X | creation time (unix) |
+| | [0].createdAt | X | X | X | X | X | creation date time string |
+| | [0].startedAt | X | X | X | X | X | creation date time string |
+| | [0].finishedAt | X | X | X | X | X | creation date time string |
+| | [0].state | X | X | X | X | X | created, running, exited |
+| | [0].ports | X | X | X | X | X | array of ports |
+| | [0].mounts | X | X | X | X | X | array of mounts |
+| si.dockerContainerStats(ids, cb) | [{...}] | X | X | X | X | X | statistics for specific containers<br>container IDs: space or comma separated,<br>pass '*' for all containers|
+| | [0].id | X | X | X | X | X | Container ID |
+| | [0].memUsage | X | X | X | X | X | memory usage in bytes |
+| | [0].memLimit | X | X | X | X | X | memory limit (max mem) in bytes |
+| | [0].memPercent | X | X | X | X | X | memory usage in percent |
+| | [0].cpuPercent | X | X | X | X | X | cpu usage in percent |
+| | [0].pids | X | X | X | X | X | number of processes |
+| | [0].netIO.rx | X | X | X | X | X | received bytes via network |
+| | [0].netIO.wx | X | X | X | X | X | sent bytes via network |
+| | [0].blockIO.r | X | X | X | X | X | bytes read from BlockIO |
+| | [0].blockIO.w | X | X | X | X | X | bytes written to BlockIO |
+| | [0].cpuStats | X | X | X | X | X | detailed cpu stats |
+| | [0].percpuStats | X | X | X | X | X | detailed per cpu stats |
+| | [0].memoryStats | X | X | X | X | X | detailed memory stats |
+| | [0].networks | X | X | X | X | X | detailed network stats per interface |
+| si.dockerContainerProcesses(id, cb) | [{...}] | X | X | X | X | X | array of processes inside a container |
+| | [0].pidHost | X | X | X | X | X | process ID (host) |
+| | [0].ppid | X | X | X | X | X | parent process ID |
+| | [0].pgid | X | X | X | X | X | process group ID |
+| | [0].user | X | X | X | X | X | effective user name |
+| | [0].ruser | X | X | X | X | X | real user name |
+| | [0].group | X | X | X | X | X | effective group name |
+| | [0].rgroup | X | X | X | X | X | real group name |
+| | [0].stat | X | X | X | X | X | process state |
+| | [0].time | X | X | X | X | X | accumulated CPU time |
+| | [0].elapsed | X | X | X | X | X | elapsed running time |
+| | [0].nice | X | X | X | X | X | nice value |
+| | [0].rss | X | X | X | X | X | resident set size |
+| | [0].vsz | X | X | X | X | X | virtual size in Kbytes |
+| | [0].command | X | X | X | X | X | command and arguments |
+| si.dockerVolumes(cb) | [{...}] | returns array of all docker volumes |
+| | [0].name | X | X | X | X | X | volume name |
+| | [0].driver | X | X | X | X | X | driver |
+| | [0].labels | X | X | X | X | X | labels object |
+| | [0].mountpoint | X | X | X | X | X | mountpoint |
+| | [0].options | X | X | X | X | X | options |
+| | [0].scope | X | X | X | X | X | scope |
+| | [0].created | X | X | X | X | X | created at |
+| si.dockerAll(cb) | {...} | X | X | X | X | X | list of all containers including their stats<br>and processes in one single array |
+
+#### 17. Virtual Box
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.vboxInfo(cb) | [{...}] | X | X | X | X | X | returns array general virtual box info |
+| | [0].id | X | X | X | X | X | virtual box ID |
+| | [0].name | X | X | X | X | X | name |
+| | [0].running | X | X | X | X | X | vbox is running |
+| | [0].started | X | X | X | X | X | started date time |
+| | [0].runningSince | X | X | X | X | X | running since (secs) |
+| | [0].stopped | X | X | X | X | X | stopped date time |
+| | [0].stoppedSince | X | X | X | X | X | stopped since (secs) |
+| | [0].guestOS | X | X | X | X | X | Guest OS |
+| | [0].hardwareUUID | X | X | X | X | X | Hardware UUID |
+| | [0].memory | X | X | X | X | X | Memory in MB |
+| | [0].vram | X | X | X | X | X | VRAM in MB |
+| | [0].cpus | X | X | X | X | X | CPUs |
+| | [0].cpuExepCap | X | X | X | X | X | CPU exec cap |
+| | [0].cpuProfile | X | X | X | X | X | CPU profile |
+| | [0].chipset | X | X | X | X | X | chipset |
+| | [0].firmware | X | X | X | X | X | firmware |
+| | [0].pageFusion | X | X | X | X | X | page fusion |
+| | [0].configFile | X | X | X | X | X | config file |
+| | [0].snapshotFolder | X | X | X | X | X | snapshot folder |
+| | [0].logFolder | X | X | X | X | X | log folder path |
+| | [0].hpet | X | X | X | X | X | HPET |
+| | [0].pae | X | X | X | X | X | PAE |
+| | [0].longMode | X | X | X | X | X | long mode |
+| | [0].tripleFaultReset | X | X | X | X | X | triple fault reset |
+| | [0].apic | X | X | X | X | X | APIC |
+| | [0].x2Apic | X | X | X | X | X | X2APIC |
+| | [0].acpi | X | X | X | X | X | ACPI |
+| | [0].ioApic | X | X | X | X | X | IOAPIC |
+| | [0].biosApicMode | X | X | X | X | X | BIOS APIC mode |
+| | [0].bootMenuMode | X | X | X | X | X | boot menu Mode |
+| | [0].bootDevice1 | X | X | X | X | X | bootDevice1 |
+| | [0].bootDevice2 | X | X | X | X | X | bootDevice2 |
+| | [0].bootDevice3 | X | X | X | X | X | bootDevice3 |
+| | [0].bootDevice4 | X | X | X | X | X | bootDevice4 |
+| | [0].timeOffset | X | X | X | X | X | time Offset |
+| | [0].rtc | X | X | X | X | X | RTC |
+
+#### 16. "Get All / Observe" - functions
+
+| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
+| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
+| si.getStaticData(cb) | {...} | X | X | X | X | X | all static data at once |
+| si.getDynamicData(srv,iface,cb) | {...} | X | X | X | X | X | all dynamic data at once<br>Specify services and interfaces to monitor<br>Defaults to first external network interface<br>Pass "*" for ALL services (linux/win only)<br>Pass "*" for ALL network interfaces |
+| si.getAllData(srv,iface,cb) | {...} | X | X | X | X | X | all data at once<br>Specify services and interfaces to monitor<br>Defaults to first external network interface<br>Pass "*" for ALL services (linux/win only)<br>Pass "*" for ALL network interfaces |
+| si.get(valueObject,cb) | {...} | X | X | X | X | X | get partial system info data at once<br>In valueObject you can define<br>all values, you want to get back <br>(see documentation for details) |
+| si.observe(valueObject,interval,cb) | - | X | X | X | X | X | Observe a defined value object<br>call callback on changes<br>polling interval in milliseconds |
+
+### cb: Asynchronous Function Calls (callback)
+
+Remember: all functions (except `version` and `time`) are implemented as asynchronous functions! There are now three ways to consume them:
+
+**Callback Style**
+
+```js
+const si = require('systeminformation');
+
+si.cpu(function(data) {
+ console.log('CPU Information:');
+ console.log('- manufucturer: ' + data.manufacturer);
+ console.log('- brand: ' + data.brand);
+ console.log('- speed: ' + data.speed);
+ console.log('- cores: ' + data.cores);
+ console.log('- physical cores: ' + data.physicalCores);
+ console.log('...');
+})
+```
+
+### Promises
+
+**Promises Style** is new in version 3.0.
+
+When omitting callback parameter (cb), then you can use all function in a promise oriented way. All functions (except of `version` and `time`) are returning a promise, that you can consume:
+
+```js
+const si = require('systeminformation');
+
+si.cpu()
+ .then(data => {
+ console.log('CPU Information:');
+ console.log('- manufucturer: ' + data.manufacturer);
+ console.log('- brand: ' + data.brand);
+ console.log('- speed: ' + data.speed);
+ console.log('- cores: ' + data.cores);
+ console.log('- physical cores: ' + data.physicalCores);
+ console.log('...');
+ })
+ .catch(error => console.error(error));
+```
+
+### Async / Await
+
+**Using async / await** (available since node v7.6)
+
+Since node v7.6 you can also use the `async` / `await` pattern. The above example would then look like this:
+
+```js
+const si = require('systeminformation');
+
+async function cpuData() {
+ try {
+ const data = await si.cpu();
+ console.log('CPU Information:');
+ console.log('- manufucturer: ' + data.manufacturer);
+ console.log('- brand: ' + data.brand);
+ console.log('- speed: ' + data.speed);
+ console.log('- cores: ' + data.cores);
+ console.log('- physical cores: ' + data.physicalCores);
+ console.log('...');
+ } catch (e) {
+ console.log(e)
+ }
+}
+```
+
+## Known Issues
+
+#### macOS - Temperature Sensor
+
+To be able to measure temperature on macOS I created a little additional package. Due to some difficulties
+in NPM with `optionalDependencies` I unfortunately was getting unexpected warnings on other platforms.
+So I decided to drop this optional dependency for macOS - so by default, you will not get correct values.
+
+This additional package is now also supporting Apple Silicon M1 machines.
+
+But if you need to detect macOS temperature just run the following additional
+installation command:
+
+```bash
+$ npm install osx-temperature-sensor --save
+```
+
+`systeminformation` will then detect this additional library and return the temperature when calling systeminformations standard function `cpuTemperature()`
+
+#### Windows Temperature, Battery, ...
+
+`get-WmiObject` - which is used to determine temperature and battery sometimes needs to be run with admin
+privileges. So if you do not get any values, try to run it again with according
+privileges. If you still do not get any values, your system might not support this feature.
+In some cases we also discovered that `get-WmiObject` returned incorrect temperature values.
+
+#### Linux Temperature
+
+In some cases you need to install the Linux `sensors` package to be able to measure temperature
+e.g. on DEBIAN based systems by running `sudo apt-get install lm-sensors`
+
+#### Linux S.M.A.R.T. Status
+
+To be able to detect S.M.A.R.T. status on Linux you need to install `smartmontools`. On DEBIAN based Linux distributions you can install it by running `sudo apt-get install smartmontools`
+
+#### Windows Encoding Issues
+I now reimplemented all windows functions to avoid encoding problems (special chacarters). And as Windows 11 now droppend `wmic` support, I had to move completely to `powershell`. Be sure that powershell version 5+ is installed on your machine. On older Windows versions (7, 8) you might still see encoding problems due to the old powershell version.
+## *: Additional Notes
+
+In `fsStats()`, `disksIO()` and `networkStats()` the results / sec. values (rx_sec, IOPS, ...) are calculated correctly beginning
+with the second call of the function. It is determined by calculating the difference of transferred bytes / IOs
+divided by the time between two calls of the function.
+
+The first time you are calling one of these functions, you will get `null` for transfer rates. The second time, you should then get statistics based on the time between the two calls ...
+
+So basically, if you e.g. need a value for network stats every second, your code should look like this:
+
+```js
+const si = require('systeminformation');
+
+setInterval(function() {
+ si.networkStats().then(data => {
+ console.log(data);
+ })
+}, 1000)
+```
+
+Beginning with the second call, you get network transfer values per second.
+
+## Finding new issues
+
+I am happy to discuss any comments and suggestions. Please feel free to contact me if you see any possibility of improvement!
+
+
+## Comments
+
+If you have ideas or comments, please do not hesitate to contact me.
+
+
+Happy monitoring!
+
+Sincerely,
+
+Sebastian Hildebrandt, [+innovations](http://www.plus-innovations.com)
+
+## Credits
+
+Written by Sebastian Hildebrandt [sebhildebrandt](https://github.com/sebhildebrandt)
+
+#### Contributors
+
+- Guillaume Legrain [glegrain](https://github.com/glegrain)
+- Riccardo Novaglia [richy24](https://github.com/richy24)
+- Quentin Busuttil [Buzut](https://github.com/Buzut)
+- lapsio [lapsio](https://github.com/lapsio)
+- csy [csy](https://github.com/csy1983)
+- Tiago Roldão [tiagoroldao](https://github.com/tiagoroldao)
+- dragonjet [dragonjet](https://github.com/dragonjet)
+- Adam Reis [adamreisnz](https://github.com/adamreisnz)
+- Jimi M [ItsJimi](https://github.com/ItsJimi)
+- Git² [GitSquared](https://github.com/GitSquared)
+- weiyin [weiyin](https://github.com/weiyin)
+- Jorai Rijsdijk [Erackron](https://github.com/Erackron)
+- Rasmus Porsager [porsager](https://github.com/porsager)
+- Nathan Patten [nrpatten](https://github.com/nrpatten)
+- Juan Campuzano [juancampuzano](https://github.com/juancampuzano)
+- Ricardo Polo [ricardopolo](https://github.com/ricardopolo)
+- Miłosz Dźwigała [mily20001](https://github.com/mily20001)
+- cconley717 [cconley717](https://github.com/cconley717)
+- Maria Camila Cubides [MariaCamilaCubides](https://github.com/MariaCamilaCubides)
+- Aleksander Krasnicki [plakak](https://github.com/plakak)
+- Alexis Tyler [OmgImAlexis](https://github.com/OmgImAlexis)
+- Simon Smith [si458](https://github.com/si458)
+
+OSX Temperature: credits here are going to:
+
+- Frank Stock [pcafstockf](https://github.com/pcafstockf) - for his work on [smc-code][smc-code-url]
+
+## Copyright Information
+
+Linux is a registered trademark of Linus Torvalds. Apple, macOS, OS X are registered trademarks of Apple Inc.,
+Windows is a registered trademark of Microsoft Corporation. Node.js is a trademark of Joyent Inc.,
+Intel is a trademark of Intel Corporation, AMD is a trademark of Advanced Micro Devices Inc.,
+Raspberry Pi is a trademark of the Raspberry Pi Foundation, Debian is a trademark owned by Software in the Public Interest, Inc.,
+Ubuntu is a trademark of Canonical Ltd., FreeBSD is a registered trademark of The FreeBSD Foundation,
+NetBSD is a registered trademark of The NetBSD Foundation, Docker is a trademark of Docker, Inc., Sun,
+Solaris, OpenSolaris and registered trademarks of Sun Microsystems, VMware is a trademark of VMware Inc,
+Virtual Box is a trademark of Oracle Corporation, Xen is a registered trademark of Xen Project,
+QEMU is a trademark of Fabrice Bellard, bochs is a trademark of The Bochs Project, USB and USB Logo
+are trademarks of USB Implementation Forum, Bluetooth and Bluetooth Logo are trademarks of Bluetooth SIG,
+Android is a trademark of Google LLC.
+
+All other trademarks are the property of their respective owners.
+
+## License [![MIT license][license-img]][license-url]
+
+>The [`MIT`][license-url] License (MIT)
+>
+>Copyright &copy; 2014-2022 Sebastian Hildebrandt, [+innovations](http://www.plus-innovations.com).
+>
+>Permission is hereby granted, free of charge, to any person obtaining a copy
+>of this software and associated documentation files (the "Software"), to deal
+>in the Software without restriction, including without limitation the rights
+>to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+>copies of the Software, and to permit persons to whom the Software is
+>furnished to do so, subject to the following conditions:
+>
+>The above copyright notice and this permission notice shall be included in
+>all copies or substantial portions of the Software.
+>
+>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+>FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+>AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+>LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+>OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+>THE SOFTWARE.
+>
+>Further details see [LICENSE](LICENSE) file.
+
+
+[npm-image]: https://img.shields.io/npm/v/systeminformation.svg?style=flat-square
+[npm-url]: https://npmjs.org/package/systeminformation
+[downloads-image]: https://img.shields.io/npm/dm/systeminformation.svg?style=flat-square
+[downloads-url]: https://npmjs.org/package/systeminformation
+
+[lgtm-badge]: https://img.shields.io/lgtm/grade/javascript/g/sebhildebrandt/systeminformation.svg?style=flat-square
+[lgtm-badge-url]: https://lgtm.com/projects/g/sebhildebrandt/systeminformation/context:javascript
+[lgtm-alerts]: https://img.shields.io/lgtm/alerts/g/sebhildebrandt/systeminformation.svg?style=flat-square
+[lgtm-alerts-url]: https://lgtm.com/projects/g/sebhildebrandt/systeminformation/alerts
+
+[sponsor-badge]: https://img.shields.io/badge/-Buy%20me%20a%20coffee-blue?style=flat-square
+[sponsor-url]: https://www.buymeacoffee.com/systeminfo
+
+[license-url]: https://github.com/sebhildebrandt/systeminformation/blob/master/LICENSE
+[license-img]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
+[npmjs-license]: https://img.shields.io/npm/l/systeminformation.svg?style=flat-square
+[changelog-url]: https://github.com/sebhildebrandt/systeminformation/blob/master/CHANGELOG.md
+[changes5-url]: https://systeminformation.io/changes.html
+[caretaker-url]: https://github.com/sebhildebrandt
+[caretaker-image]: https://img.shields.io/badge/caretaker-sebhildebrandt-blue.svg?style=flat-square
+
+[nodejs-url]: https://nodejs.org/en/
+[docker-url]: https://www.docker.com/
+[systeminformation-url]: https://systeminformation.io
+
+[daviddm-img]: https://img.shields.io/david/sebhildebrandt/systeminformation.svg?style=flat-square
+[daviddm-url]: https://david-dm.org/sebhildebrandt/systeminformation
+
+[issues-img]: https://img.shields.io/github/issues/sebhildebrandt/systeminformation.svg?style=flat-square
+[issues-url]: https://github.com/sebhildebrandt/systeminformation/issues
+[closed-issues-img]: https://img.shields.io/github/issues-closed-raw/sebhildebrandt/systeminformation.svg?style=flat-square&color=brightgreen
+[closed-issues-url]: https://github.com/sebhildebrandt/systeminformation/issues?q=is%3Aissue+is%3Aclosed
+
+[new-issue]: https://github.com/sebhildebrandt/systeminformation/issues/new/choose
+
+[mmon-npm-url]: https://npmjs.org/package/mmon
+[mmon-github-url]: https://github.com/sebhildebrandt/mmon
+
+[smc-code-url]: https://github.com/pcafstockf/smc-reader
diff --git a/MistyCore/node_modules/systeminformation/lib/audio.js b/MistyCore/node_modules/systeminformation/lib/audio.js
new file mode 100644
index 0000000..ac57194
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/audio.js
@@ -0,0 +1,216 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// audio.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 16. audio
+// ----------------------------------------------------------------------------------
+
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+function parseAudioType(str, input, output) {
+ let result = '';
+
+ if (str.indexOf('speak') >= 0) { result = 'Speaker'; }
+ if (str.indexOf('laut') >= 0) { result = 'Speaker'; }
+ if (str.indexOf('loud') >= 0) { result = 'Speaker'; }
+ if (str.indexOf('head') >= 0) { result = 'Headset'; }
+ if (str.indexOf('mic') >= 0) { result = 'Microphone'; }
+ if (str.indexOf('mikr') >= 0) { result = 'Microphone'; }
+ if (str.indexOf('phone') >= 0) { result = 'Phone'; }
+ if (str.indexOf('controll') >= 0) { result = 'Controller'; }
+ if (str.indexOf('line o') >= 0) { result = 'Line Out'; }
+ if (str.indexOf('digital o') >= 0) { result = 'Digital Out'; }
+
+ if (!result && output) {
+ result = 'Speaker';
+ } else if (!result && input) {
+ result = 'Microphone';
+ }
+ return result;
+}
+
+
+function getLinuxAudioPci() {
+ let cmd = 'lspci -v 2>/dev/null';
+ let result = [];
+ try {
+ const parts = execSync(cmd).toString().split('\n\n');
+ for (let i = 0; i < parts.length; i++) {
+ const lines = parts[i].split('\n');
+ if (lines && lines.length && lines[0].toLowerCase().indexOf('audio') >= 0) {
+ const audio = {};
+ audio.slotId = lines[0].split(' ')[0];
+ audio.driver = util.getValue(lines, 'Kernel driver in use', ':', true) || util.getValue(lines, 'Kernel modules', ':', true);
+ result.push(audio);
+ }
+ }
+ return result;
+ } catch (e) {
+ return result;
+ }
+}
+
+function parseLinuxAudioPciMM(lines, audioPCI) {
+ const result = {};
+ const slotId = util.getValue(lines, 'Slot');
+
+ const pciMatch = audioPCI.filter(function (item) { return item.slotId === slotId; });
+
+ result.id = slotId;
+ result.name = util.getValue(lines, 'SDevice');
+ result.manufacturer = util.getValue(lines, 'SVendor');
+ result.revision = util.getValue(lines, 'Rev');
+ result.driver = pciMatch && pciMatch.length === 1 && pciMatch[0].driver ? pciMatch[0].driver : '';
+ result.default = null;
+ result.channel = 'PCIe';
+ result.type = parseAudioType(result.name, null, null);
+ result.in = null;
+ result.out = null;
+ result.status = 'online';
+
+ return result;
+}
+
+function parseDarwinChannel(str) {
+ let result = '';
+
+ if (str.indexOf('builtin') >= 0) { result = 'Built-In'; }
+ if (str.indexOf('extern') >= 0) { result = 'Audio-Jack'; }
+ if (str.indexOf('hdmi') >= 0) { result = 'HDMI'; }
+ if (str.indexOf('displayport') >= 0) { result = 'Display-Port'; }
+ if (str.indexOf('usb') >= 0) { result = 'USB'; }
+ if (str.indexOf('pci') >= 0) { result = 'PCIe'; }
+
+ return result;
+}
+
+function parseDarwinAudio(audioObject, id) {
+ const result = {};
+ const channelStr = ((audioObject.coreaudio_device_transport || '') + ' ' + (audioObject._name || '')).toLowerCase();
+
+ result.id = id;
+ result.name = audioObject._name;
+ result.manufacturer = audioObject.coreaudio_device_manufacturer;
+ result.revision = null;
+ result.driver = null;
+ result.default = !!(audioObject.coreaudio_default_audio_input_device || '') || !!(audioObject.coreaudio_default_audio_output_device || '');
+ result.channel = parseDarwinChannel(channelStr);
+ result.type = parseAudioType(result.name, !!(audioObject.coreaudio_device_input || ''), !!(audioObject.coreaudio_device_output || ''));
+ result.in = !!(audioObject.coreaudio_device_input || '');
+ result.out = !!(audioObject.coreaudio_device_output || '');
+ result.status = 'online';
+
+ return result;
+}
+
+function parseWindowsAudio(lines) {
+ const result = {};
+ const status = util.getValue(lines, 'StatusInfo', ':');
+
+ result.id = util.getValue(lines, 'DeviceID', ':'); // PNPDeviceID??
+ result.name = util.getValue(lines, 'name', ':');
+ result.manufacturer = util.getValue(lines, 'manufacturer', ':');
+ result.revision = null;
+ result.driver = null;
+ result.default = null;
+ result.channel = null;
+ result.type = parseAudioType(result.name, null, null);
+ result.in = null;
+ result.out = null;
+ result.status = status;
+
+ return result;
+}
+
+function audio(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = [];
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ let cmd = 'lspci -vmm 2>/dev/null';
+ exec(cmd, function (error, stdout) {
+ // PCI
+ if (!error) {
+ const audioPCI = getLinuxAudioPci();
+ const parts = stdout.toString().split('\n\n');
+ for (let i = 0; i < parts.length; i++) {
+ const lines = parts[i].split('\n');
+ if (util.getValue(lines, 'class', ':', true).toLowerCase().indexOf('audio') >= 0) {
+ const audio = parseLinuxAudioPciMM(lines, audioPCI);
+ result.push(audio);
+ }
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ let cmd = 'system_profiler SPAudioDataType -json';
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ try {
+ const outObj = JSON.parse(stdout.toString());
+ if (outObj.SPAudioDataType && outObj.SPAudioDataType.length && outObj.SPAudioDataType[0] && outObj.SPAudioDataType[0]['_items'] && outObj.SPAudioDataType[0]['_items'].length) {
+ for (let i = 0; i < outObj.SPAudioDataType[0]['_items'].length; i++) {
+ const audio = parseDarwinAudio(outObj.SPAudioDataType[0]['_items'][i], i);
+ result.push(audio);
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_windows) {
+ util.powerShell('Get-WmiObject Win32_SoundDevice | select DeviceID,StatusInfo,Name,Manufacturer | fl').then((stdout, error) => {
+ if (!error) {
+ const parts = stdout.toString().split(/\n\s*\n/);
+ for (let i = 0; i < parts.length; i++) {
+ if (util.getValue(parts[i].split('\n'), 'name', ':')) {
+ result.push(parseWindowsAudio(parts[i].split('\n')));
+ }
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ resolve(null);
+ }
+ });
+ });
+}
+
+exports.audio = audio;
diff --git a/MistyCore/node_modules/systeminformation/lib/battery.js b/MistyCore/node_modules/systeminformation/lib/battery.js
new file mode 100644
index 0000000..05f7d5c
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/battery.js
@@ -0,0 +1,308 @@
+'use strict';
+// @ts-check;
+// ==================================================================================
+// battery.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 6. Battery
+// ----------------------------------------------------------------------------------
+
+const exec = require('child_process').exec;
+const fs = require('fs');
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+function parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity) {
+ const result = {};
+ let status = util.getValue(lines, 'BatteryStatus', ':').trim();
+ // 1 = "Discharging"
+ // 2 = "On A/C"
+ // 3 = "Fully Charged"
+ // 4 = "Low"
+ // 5 = "Critical"
+ // 6 = "Charging"
+ // 7 = "Charging High"
+ // 8 = "Charging Low"
+ // 9 = "Charging Critical"
+ // 10 = "Undefined"
+ // 11 = "Partially Charged"
+ if (status >= 0) {
+ const statusValue = status ? parseInt(status) : 0;
+ result.status = statusValue;
+ result.hasBattery = true;
+ result.maxCapacity = fullChargeCapacity || parseInt(util.getValue(lines, 'DesignCapacity', ':') || 0);
+ result.designedCapacity = parseInt(util.getValue(lines, 'DesignCapacity', ':') || designedCapacity);
+ result.voltage = parseInt(util.getValue(lines, 'DesignVoltage', ':') || 0) / 1000.0;
+ result.capacityUnit = 'mWh';
+ result.percent = parseInt(util.getValue(lines, 'EstimatedChargeRemaining', ':') || 0);
+ result.currentCapacity = parseInt(result.maxCapacity * result.percent / 100);
+ result.isCharging = (statusValue >= 6 && statusValue <= 9) || statusValue === 11 || ((statusValue !== 3) && (statusValue !== 1) && result.percent < 100);
+ result.acConnected = result.isCharging || statusValue === 2;
+ result.model = util.getValue(lines, 'DeviceID', ':');
+ } else {
+ result.status = -1;
+ }
+
+ return result;
+}
+
+module.exports = function (callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = {
+ hasBattery: false,
+ cycleCount: 0,
+ isCharging: false,
+ designedCapacity: 0,
+ maxCapacity: 0,
+ currentCapacity: 0,
+ voltage: 0,
+ capacityUnit: '',
+ percent: 0,
+ timeRemaining: null,
+ acConnected: true,
+ type: '',
+ model: '',
+ manufacturer: '',
+ serial: ''
+ };
+
+ if (_linux) {
+ let battery_path = '';
+ if (fs.existsSync('/sys/class/power_supply/BAT1/uevent')) {
+ battery_path = '/sys/class/power_supply/BAT1/';
+ } else if (fs.existsSync('/sys/class/power_supply/BAT0/uevent')) {
+ battery_path = '/sys/class/power_supply/BAT0/';
+ }
+
+ let acConnected = false;
+ let acPath = '';
+ if (fs.existsSync('/sys/class/power_supply/AC/online')) {
+ acPath = '/sys/class/power_supply/AC/online';
+ } else if (fs.existsSync('/sys/class/power_supply/AC0/online')) {
+ acPath = '/sys/class/power_supply/AC0/online';
+ }
+
+ if (acPath) {
+ const file = fs.readFileSync(acPath);
+ acConnected = file.toString().trim() === '1';
+ }
+
+ if (battery_path) {
+ fs.readFile(battery_path + 'uevent', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+
+ result.isCharging = (util.getValue(lines, 'POWER_SUPPLY_STATUS', '=').toLowerCase() === 'charging');
+ result.acConnected = acConnected || result.isCharging;
+ result.voltage = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_VOLTAGE_NOW', '='), 10) / 1000000.0;
+ result.capacityUnit = result.voltage ? 'mWh' : 'mAh';
+ result.cycleCount = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CYCLE_COUNT', '='), 10);
+ result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_FULL', '=', true, true), 10) / 1000.0 * (result.voltage || 1));
+ const desingedMinVoltage = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_VOLTAGE_MIN_DESIGN', '='), 10) / 1000000.0;
+ result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_FULL_DESIGN', '=', true, true), 10) / 1000.0 * (desingedMinVoltage || result.voltage || 1));
+ result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_NOW', '='), 10) / 1000.0 * (result.voltage || 1));
+ if (!result.maxCapacity) {
+ result.maxCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_FULL', '=', true, true), 10) / 1000.0;
+ result.designedCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_FULL_DESIGN', '=', true, true), 10) / 1000.0 | result.maxCapacity;
+ result.currentCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_NOW', '='), 10) / 1000.0;
+ }
+ const percent = util.getValue(lines, 'POWER_SUPPLY_CAPACITY', '=');
+ const energy = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_NOW', '='), 10);
+ const power = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_POWER_NOW', '='), 10);
+ const current = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CURRENT_NOW', '='), 10);
+
+ result.percent = parseInt('0' + percent, 10);
+ if (result.maxCapacity && result.currentCapacity) {
+ result.hasBattery = true;
+ if (!percent) {
+ result.percent = 100.0 * result.currentCapacity / result.maxCapacity;
+ }
+ }
+ if (result.isCharging) {
+ result.hasBattery = true;
+ }
+ if (energy && power) {
+ result.timeRemaining = Math.floor(energy / power * 60);
+ } else if (current && result.currentCapacity) {
+ result.timeRemaining = Math.floor(result.currentCapacity / current * 60);
+ }
+ result.type = util.getValue(lines, 'POWER_SUPPLY_TECHNOLOGY', '=');
+ result.model = util.getValue(lines, 'POWER_SUPPLY_MODEL_NAME', '=');
+ result.manufacturer = util.getValue(lines, 'POWER_SUPPLY_MANUFACTURER', '=');
+ result.serial = util.getValue(lines, 'POWER_SUPPLY_SERIAL_NUMBER', '=');
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ exec('sysctl -i hw.acpi.battery hw.acpi.acline', function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ const batteries = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.units'), 10);
+ const percent = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.life'), 10);
+ result.hasBattery = (batteries > 0);
+ result.cycleCount = null;
+ result.isCharging = util.getValue(lines, 'hw.acpi.acline') !== '1';
+ result.acConnected = result.isCharging;
+ result.maxCapacity = null;
+ result.currentCapacity = null;
+ result.capacityUnit = 'unknown';
+ result.percent = batteries ? percent : null;
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+
+ if (_darwin) {
+ exec('ioreg -n AppleSmartBattery -r | egrep "CycleCount|IsCharging|DesignCapacity|MaxCapacity|CurrentCapacity|BatterySerialNumber|TimeRemaining|Voltage"; pmset -g batt | grep %', function (error, stdout) {
+ if (stdout) {
+ let lines = stdout.toString().replace(/ +/g, '').replace(/"+/g, '').replace(/-/g, '').split('\n');
+ result.cycleCount = parseInt('0' + util.getValue(lines, 'cyclecount', '='), 10);
+ result.voltage = parseInt('0' + util.getValue(lines, 'voltage', '='), 10) / 1000.0;
+ result.capacityUnit = result.voltage ? 'mWh' : 'mAh';
+ result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'applerawmaxcapacity', '='), 10) * (result.voltage || 1));
+ result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'applerawcurrentcapacity', '='), 10) * (result.voltage || 1));
+ result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'DesignCapacity', '='), 10) * (result.voltage || 1));
+ result.manufacturer = 'Apple';
+ result.serial = util.getValue(lines, 'BatterySerialNumber', '=');
+ let percent = null;
+ const line = util.getValue(lines, 'internal', 'Battery');
+ let parts = line.split(';');
+ if (parts && parts[0]) {
+ let parts2 = parts[0].split('\t');
+ if (parts2 && parts2[1]) {
+ percent = parseFloat(parts2[1].trim().replace(/%/g, ''));
+ }
+ }
+ if (parts && parts[1]) {
+ result.isCharging = (parts[1].trim() === 'charging');
+ result.acConnected = (parts[1].trim() !== 'discharging');
+ } else {
+ result.isCharging = util.getValue(lines, 'ischarging', '=').toLowerCase() === 'yes';
+ result.acConnected = result.isCharging;
+ }
+ if (result.maxCapacity && result.currentCapacity) {
+ result.hasBattery = true;
+ result.type = 'Li-ion';
+ result.percent = percent !== null ? percent : Math.round(100.0 * result.currentCapacity / result.maxCapacity);
+ if (!result.isCharging) {
+ result.timeRemaining = parseInt('0' + util.getValue(lines, 'TimeRemaining', '='), 10);
+ }
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_windows) {
+ try {
+ const workload = [];
+ workload.push(util.powerShell('Get-WmiObject Win32_Battery | select BatteryStatus, DesignCapacity, DesignVoltage, EstimatedChargeRemaining, DeviceID | fl'));
+ workload.push(util.powerShell('(Get-WmiObject -Class BatteryStaticData -Namespace ROOT/WMI).DesignedCapacity'));
+ workload.push(util.powerShell('(Get-WmiObject -Class BatteryFullChargedCapacity -Namespace ROOT/WMI).FullChargedCapacity'));
+ util.promiseAll(
+ workload
+ ).then((data) => {
+ if (data) {
+ let parts = data.results[0].split(/\n\s*\n/);
+ let batteries = [];
+ const hasValue = value => /\S/.test(value);
+ for (let i = 0; i < parts.length; i++) {
+ if (hasValue(parts[i]) && (!batteries.length || !hasValue(parts[i - 1]))) {
+ batteries.push([]);
+ }
+ if (hasValue(parts[i])) {
+ batteries[batteries.length - 1].push(parts[i]);
+ }
+ }
+ let designCapacities = data.results[1].split('\r\n').filter(e => e);
+ let fullChargeCapacities = data.results[2].split('\r\n').filter(e => e);
+ if (batteries.length) {
+ let first = false;
+ let additionalBatteries = [];
+ for (let i = 0; i < batteries.length; i++) {
+ let lines = batteries[i][0].split('\r\n');
+ const designedCapacity = designCapacities && designCapacities.length >= (i + 1) && designCapacities[i] ? util.toInt(designCapacities[i]) : 0;
+ const fullChargeCapacity = fullChargeCapacities && fullChargeCapacities.length >= (i + 1) && fullChargeCapacities[i] ? util.toInt(fullChargeCapacities[i]) : 0;
+ const parsed = parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity);
+ if (!first && parsed.status > 0 && parsed.status !== 10) {
+ result.hasBattery = parsed.hasBattery;
+ result.maxCapacity = parsed.maxCapacity;
+ result.designedCapacity = parsed.designedCapacity;
+ result.voltage = parsed.voltage;
+ result.capacityUnit = parsed.capacityUnit;
+ result.percent = parsed.percent;
+ result.currentCapacity = parsed.currentCapacity;
+ result.isCharging = parsed.isCharging;
+ result.acConnected = parsed.acConnected;
+ result.model = parsed.model;
+ first = true;
+ } else if (parsed.status !== -1) {
+ additionalBatteries.push(
+ {
+ hasBattery: parsed.hasBattery,
+ maxCapacity: parsed.maxCapacity,
+ designedCapacity: parsed.designedCapacity,
+ voltage: parsed.voltage,
+ capacityUnit: parsed.capacityUnit,
+ percent: parsed.percent,
+ currentCapacity: parsed.currentCapacity,
+ isCharging: parsed.isCharging,
+ timeRemaining: null,
+ acConnected: parsed.acConnected,
+ model: parsed.model,
+ type: '',
+ manufacturer: '',
+ serial: ''
+ }
+ );
+ }
+ }
+ if (!first && additionalBatteries.length) {
+ result = additionalBatteries[0];
+ additionalBatteries.shift();
+ }
+ if (additionalBatteries.length) {
+ result.additionalBatteries = additionalBatteries;
+ }
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+};
diff --git a/MistyCore/node_modules/systeminformation/lib/bluetooth.js b/MistyCore/node_modules/systeminformation/lib/bluetooth.js
new file mode 100644
index 0000000..ad0866f
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/bluetooth.js
@@ -0,0 +1,229 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// audio.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 17. bluetooth
+// ----------------------------------------------------------------------------------
+
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const path = require('path');
+const util = require('./util');
+const fs = require('fs');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+function parseBluetoothType(str) {
+ let result = '';
+
+ if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
+ if (str.indexOf('mouse') >= 0) { result = 'Mouse'; }
+ if (str.indexOf('speaker') >= 0) { result = 'Speaker'; }
+ if (str.indexOf('headset') >= 0) { result = 'Headset'; }
+ if (str.indexOf('phone') >= 0) { result = 'Phone'; }
+ if (str.indexOf('macbook') >= 0) { result = 'Computer'; }
+ if (str.indexOf('imac') >= 0) { result = 'Computer'; }
+ if (str.indexOf('ipad') >= 0) { result = 'Tablet'; }
+ if (str.indexOf('watch') >= 0) { result = 'Watch'; }
+ if (str.indexOf('headphone') >= 0) { result = 'Headset'; }
+ // to be continued ...
+
+ return result;
+}
+
+function parseBluetoothManufacturer(str) {
+ let result = str.split(' ')[0];
+ str = str.toLowerCase();
+ if (str.indexOf('apple') >= 0) { result = 'Apple'; }
+ if (str.indexOf('ipad') >= 0) { result = 'Apple'; }
+ if (str.indexOf('imac') >= 0) { result = 'Apple'; }
+ if (str.indexOf('iphone') >= 0) { result = 'Apple'; }
+ if (str.indexOf('magic mouse') >= 0) { result = 'Apple'; }
+ if (str.indexOf('macbook') >= 0) { result = 'Apple'; }
+ // to be continued ...
+
+ return result;
+}
+
+function parseLinuxBluetoothInfo(lines, macAddr1, macAddr2) {
+ const result = {};
+
+ result.device = null;
+ result.name = util.getValue(lines, 'name', '=');
+ result.manufacturer = null;
+ result.macDevice = macAddr1;
+ result.macHost = macAddr2;
+ result.batteryPercent = null;
+ result.type = parseBluetoothType(result.name.toLowerCase());
+ result.connected = false;
+
+ return result;
+}
+
+function parseDarwinBluetoothDevices(bluetoothObject, macAddr2) {
+ const result = {};
+ const typeStr = ((bluetoothObject.device_minorClassOfDevice_string || bluetoothObject.device_majorClassOfDevice_string || bluetoothObject.device_minorType || '') + (bluetoothObject.device_name || '')).toLowerCase();
+
+ result.device = bluetoothObject.device_services || '';
+ result.name = bluetoothObject.device_name || '';
+ result.manufacturer = bluetoothObject.device_manufacturer || parseBluetoothManufacturer(bluetoothObject.device_name || '') || '';
+ result.macDevice = (bluetoothObject.device_addr || bluetoothObject.device_address || '').toLowerCase().replace(/-/g, ':');
+ result.macHost = macAddr2;
+ result.batteryPercent = bluetoothObject.device_batteryPercent || null;
+ result.type = parseBluetoothType(typeStr);
+ result.connected = bluetoothObject.device_isconnected === 'attrib_Yes' || false;
+
+ return result;
+}
+
+function parseWindowsBluetooth(lines) {
+ const result = {};
+
+ result.device = null;
+ result.name = util.getValue(lines, 'name', ':');
+ result.manufacturer = util.getValue(lines, 'manufacturer', ':');
+ result.macDevice = null;
+ result.macHost = null;
+ result.batteryPercent = null;
+ result.type = parseBluetoothType(result.name.toLowerCase());
+ result.connected = null;
+
+ return result;
+}
+
+function bluetoothDevices(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = [];
+ if (_linux) {
+ // get files in /var/lib/bluetooth/ recursive
+ const btFiles = util.getFilesInPath('/var/lib/bluetooth/');
+ btFiles.forEach((element) => {
+ const filename = path.basename(element);
+ const pathParts = element.split('/');
+ const macAddr1 = pathParts.length >= 6 ? pathParts[pathParts.length - 2] : null;
+ const macAddr2 = pathParts.length >= 7 ? pathParts[pathParts.length - 3] : null;
+ if (filename === 'info') {
+ const infoFile = fs.readFileSync(element, { encoding: 'utf8' }).split('\n');
+ result.push(parseLinuxBluetoothInfo(infoFile, macAddr1, macAddr2));
+ }
+ });
+ // determine "connected" with hcitool con
+ try {
+ const hdicon = execSync('hcitool con').toString().toLowerCase();
+ for (let i = 0; i < result.length; i++) {
+ if (result[i].macDevice && result[i].macDevice.length > 10 && hdicon.indexOf(result[i].macDevice.toLowerCase()) >= 0) {
+ result[i].connected = true;
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ if (_darwin) {
+ let cmd = 'system_profiler SPBluetoothDataType -json';
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ try {
+ const outObj = JSON.parse(stdout.toString());
+ if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_title'] && outObj.SPBluetoothDataType[0]['device_title'].length) {
+ // missing: host BT Adapter macAddr ()
+ let macAddr2 = null;
+ if (outObj.SPBluetoothDataType[0]['local_device_title'] && outObj.SPBluetoothDataType[0].local_device_title.general_address) {
+ macAddr2 = outObj.SPBluetoothDataType[0].local_device_title.general_address.toLowerCase().replace(/-/g, ':');
+ }
+ outObj.SPBluetoothDataType[0]['device_title'].forEach((element) => {
+ const obj = element;
+ const objKey = Object.keys(obj);
+ if (objKey && objKey.length === 1) {
+ const innerObject = obj[objKey[0]];
+ innerObject.device_name = objKey[0];
+ const bluetoothDevice = parseDarwinBluetoothDevices(innerObject, macAddr2);
+ result.push(bluetoothDevice);
+ }
+ });
+ }
+ if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_connected'] && outObj.SPBluetoothDataType[0]['device_connected'].length) {
+ const macAddr2 = outObj.SPBluetoothDataType[0].controller_properties && outObj.SPBluetoothDataType[0].controller_properties.controller_address ? outObj.SPBluetoothDataType[0].controller_properties.controller_address.toLowerCase().replace(/-/g, ':') : null;
+ outObj.SPBluetoothDataType[0]['device_connected'].forEach((element) => {
+ const obj = element;
+ const objKey = Object.keys(obj);
+ if (objKey && objKey.length === 1) {
+ const innerObject = obj[objKey[0]];
+ innerObject.device_name = objKey[0];
+ innerObject.device_isconnected = 'attrib_Yes';
+ const bluetoothDevice = parseDarwinBluetoothDevices(innerObject, macAddr2);
+ result.push(bluetoothDevice);
+ }
+ });
+ }
+ if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_not_connected'] && outObj.SPBluetoothDataType[0]['device_not_connected'].length) {
+ const macAddr2 = outObj.SPBluetoothDataType[0].controller_properties && outObj.SPBluetoothDataType[0].controller_properties.controller_address ? outObj.SPBluetoothDataType[0].controller_properties.controller_address.toLowerCase().replace(/-/g, ':') : null;
+ outObj.SPBluetoothDataType[0]['device_not_connected'].forEach((element) => {
+ const obj = element;
+ const objKey = Object.keys(obj);
+ if (objKey && objKey.length === 1) {
+ const innerObject = obj[objKey[0]];
+ innerObject.device_name = objKey[0];
+ innerObject.device_isconnected = 'attrib_No';
+ const bluetoothDevice = parseDarwinBluetoothDevices(innerObject, macAddr2);
+ result.push(bluetoothDevice);
+ }
+ });
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_windows) {
+ util.powerShell('Get-WmiObject Win32_PNPEntity | select PNPClass, Name, Manufacturer | fl').then((stdout, error) => {
+ if (!error) {
+ const parts = stdout.toString().split(/\n\s*\n/);
+ parts.forEach((part) => {
+ if (util.getValue(part.split('\n'), 'PNPClass', ':') === 'Bluetooth') {
+ result.push(parseWindowsBluetooth(part.split('\n')));
+ }
+ });
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_freebsd || _netbsd || _openbsd || _sunos) {
+ resolve(null);
+ }
+ });
+ });
+}
+
+exports.bluetoothDevices = bluetoothDevices;
diff --git a/MistyCore/node_modules/systeminformation/lib/cli.js b/MistyCore/node_modules/systeminformation/lib/cli.js
new file mode 100755
index 0000000..48ed458
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/cli.js
@@ -0,0 +1,31 @@
+#!/usr/bin/env node
+
+'use strict';
+// @ts-check
+// ==================================================================================
+// cli.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+
+// ----------------------------------------------------------------------------------
+// Dependencies
+// ----------------------------------------------------------------------------------
+const si = require('./index');
+
+// ----------------------------------------------------------------------------------
+// Main
+// ----------------------------------------------------------------------------------
+(function () {
+ si.getStaticData().then(
+ ((data) => {
+ data.time = si.time();
+ console.log(JSON.stringify(data, null, 2));
+ }
+ ));
+})();
diff --git a/MistyCore/node_modules/systeminformation/lib/cpu.js b/MistyCore/node_modules/systeminformation/lib/cpu.js
new file mode 100644
index 0000000..eea5dbf
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/cpu.js
@@ -0,0 +1,1702 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// cpu.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 4. CPU
+// ----------------------------------------------------------------------------------
+
+const os = require('os');
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const fs = require('fs');
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+let _cpu_speed = 0;
+let _current_cpu = {
+ user: 0,
+ nice: 0,
+ system: 0,
+ idle: 0,
+ irq: 0,
+ load: 0,
+ tick: 0,
+ ms: 0,
+ currentLoad: 0,
+ currentLoadUser: 0,
+ currentLoadSystem: 0,
+ currentLoadNice: 0,
+ currentLoadIdle: 0,
+ currentLoadIrq: 0,
+ rawCurrentLoad: 0,
+ rawCurrentLoadUser: 0,
+ rawCurrentLoadSystem: 0,
+ rawCurrentLoadNice: 0,
+ rawCurrentLoadIdle: 0,
+ rawCurrentLoadIrq: 0
+};
+let _cpus = [];
+let _corecount = 0;
+
+const AMDBaseFrequencies = {
+ '8346': '1.8',
+ '8347': '1.9',
+ '8350': '2.0',
+ '8354': '2.2',
+ '8356|SE': '2.4',
+ '8356': '2.3',
+ '8360': '2.5',
+ '2372': '2.1',
+ '2373': '2.1',
+ '2374': '2.2',
+ '2376': '2.3',
+ '2377': '2.3',
+ '2378': '2.4',
+ '2379': '2.4',
+ '2380': '2.5',
+ '2381': '2.5',
+ '2382': '2.6',
+ '2384': '2.7',
+ '2386': '2.8',
+ '2387': '2.8',
+ '2389': '2.9',
+ '2393': '3.1',
+ '8374': '2.2',
+ '8376': '2.3',
+ '8378': '2.4',
+ '8379': '2.4',
+ '8380': '2.5',
+ '8381': '2.5',
+ '8382': '2.6',
+ '8384': '2.7',
+ '8386': '2.8',
+ '8387': '2.8',
+ '8389': '2.9',
+ '8393': '3.1',
+ '2419EE': '1.8',
+ '2423HE': '2.0',
+ '2425HE': '2.1',
+ '2427': '2.2',
+ '2431': '2.4',
+ '2435': '2.6',
+ '2439SE': '2.8',
+ '8425HE': '2.1',
+ '8431': '2.4',
+ '8435': '2.6',
+ '8439SE': '2.8',
+ '4122': '2.2',
+ '4130': '2.6',
+ '4162EE': '1.7',
+ '4164EE': '1.8',
+ '4170HE': '2.1',
+ '4174HE': '2.3',
+ '4176HE': '2.4',
+ '4180': '2.6',
+ '4184': '2.8',
+ '6124HE': '1.8',
+ '6128HE': '2.0',
+ '6132HE': '2.2',
+ '6128': '2.0',
+ '6134': '2.3',
+ '6136': '2.4',
+ '6140': '2.6',
+ '6164HE': '1.7',
+ '6166HE': '1.8',
+ '6168': '1.9',
+ '6172': '2.1',
+ '6174': '2.2',
+ '6176': '2.3',
+ '6176SE': '2.3',
+ '6180SE': '2.5',
+ '3250': '2.5',
+ '3260': '2.7',
+ '3280': '2.4',
+ '4226': '2.7',
+ '4228': '2.8',
+ '4230': '2.9',
+ '4234': '3.1',
+ '4238': '3.3',
+ '4240': '3.4',
+ '4256': '1.6',
+ '4274': '2.5',
+ '4276': '2.6',
+ '4280': '2.8',
+ '4284': '3.0',
+ '6204': '3.3',
+ '6212': '2.6',
+ '6220': '3.0',
+ '6234': '2.4',
+ '6238': '2.6',
+ '6262HE': '1.6',
+ '6272': '2.1',
+ '6274': '2.2',
+ '6276': '2.3',
+ '6278': '2.4',
+ '6282SE': '2.6',
+ '6284SE': '2.7',
+ '6308': '3.5',
+ '6320': '2.8',
+ '6328': '3.2',
+ '6338P': '2.3',
+ '6344': '2.6',
+ '6348': '2.8',
+ '6366': '1.8',
+ '6370P': '2.0',
+ '6376': '2.3',
+ '6378': '2.4',
+ '6380': '2.5',
+ '6386': '2.8',
+ 'FX|4100': '3.6',
+ 'FX|4120': '3.9',
+ 'FX|4130': '3.8',
+ 'FX|4150': '3.8',
+ 'FX|4170': '4.2',
+ 'FX|6100': '3.3',
+ 'FX|6120': '3.6',
+ 'FX|6130': '3.6',
+ 'FX|6200': '3.8',
+ 'FX|8100': '2.8',
+ 'FX|8120': '3.1',
+ 'FX|8140': '3.2',
+ 'FX|8150': '3.6',
+ 'FX|8170': '3.9',
+ 'FX|4300': '3.8',
+ 'FX|4320': '4.0',
+ 'FX|4350': '4.2',
+ 'FX|6300': '3.5',
+ 'FX|6350': '3.9',
+ 'FX|8300': '3.3',
+ 'FX|8310': '3.4',
+ 'FX|8320': '3.5',
+ 'FX|8350': '4.0',
+ 'FX|8370': '4.0',
+ 'FX|9370': '4.4',
+ 'FX|9590': '4.7',
+ 'FX|8320E': '3.2',
+ 'FX|8370E': '3.3',
+
+ // ZEN Desktop CPUs
+ '1200': '3.1',
+ 'Pro 1200': '3.1',
+ '1300X': '3.5',
+ 'Pro 1300': '3.5',
+ '1400': '3.2',
+ '1500X': '3.5',
+ 'Pro 1500': '3.5',
+ '1600': '3.2',
+ '1600X': '3.6',
+ 'Pro 1600': '3.2',
+ '1700': '3.0',
+ 'Pro 1700': '3.0',
+ '1700X': '3.4',
+ 'Pro 1700X': '3.4',
+ '1800X': '3.6',
+ '1900X': '3.8',
+ '1920': '3.2',
+ '1920X': '3.5',
+ '1950X': '3.4',
+
+ // ZEN Desktop APUs
+ '200GE': '3.2',
+ 'Pro 200GE': '3.2',
+ '220GE': '3.4',
+ '240GE': '3.5',
+ '3000G': '3.5',
+ '300GE': '3.4',
+ '3050GE': '3.4',
+ '2200G': '3.5',
+ 'Pro 2200G': '3.5',
+ '2200GE': '3.2',
+ 'Pro 2200GE': '3.2',
+ '2400G': '3.6',
+ 'Pro 2400G': '3.6',
+ '2400GE': '3.2',
+ 'Pro 2400GE': '3.2',
+
+ // ZEN Mobile APUs
+ 'Pro 200U': '2.3',
+ '300U': '2.4',
+ '2200U': '2.5',
+ '3200U': '2.6',
+ '2300U': '2.0',
+ 'Pro 2300U': '2.0',
+ '2500U': '2.0',
+ 'Pro 2500U': '2.2',
+ '2600H': '3.2',
+ '2700U': '2.0',
+ 'Pro 2700U': '2.2',
+ '2800H': '3.3',
+
+ // ZEN Server Processors
+ '7351': '2.4',
+ '7351P': '2.4',
+ '7401': '2.0',
+ '7401P': '2.0',
+ '7551P': '2.0',
+ '7551': '2.0',
+ '7251': '2.1',
+ '7261': '2.5',
+ '7281': '2.1',
+ '7301': '2.2',
+ '7371': '3.1',
+ '7451': '2.3',
+ '7501': '2.0',
+ '7571': '2.2',
+ '7601': '2.2',
+
+ // ZEN Embedded Processors
+ 'V1500B': '2.2',
+ 'V1780B': '3.35',
+ 'V1202B': '2.3',
+ 'V1404I': '2.0',
+ 'V1605B': '2.0',
+ 'V1756B': '3.25',
+ 'V1807B': '3.35',
+
+ '3101': '2.1',
+ '3151': '2.7',
+ '3201': '1.5',
+ '3251': '2.5',
+ '3255': '2.5',
+ '3301': '2.0',
+ '3351': '1.9',
+ '3401': '1.85',
+ '3451': '2.15',
+
+ // ZEN+ Desktop
+ '1200|AF': '3.1',
+ '2300X': '3.5',
+ '2500X': '3.6',
+ '2600': '3.4',
+ '2600E': '3.1',
+ '1600|AF': '3.2',
+ '2600X': '3.6',
+ '2700': '3.2',
+ '2700E': '2.8',
+ 'Pro 2700': '3.2',
+ '2700X': '3.7',
+ 'Pro 2700X': '3.6',
+ '2920X': '3.5',
+ '2950X': '3.5',
+ '2970WX': '3.0',
+ '2990WX': '3.0',
+
+ // ZEN+ Desktop APU
+ 'Pro 300GE': '3.4',
+ 'Pro 3125GE': '3.4',
+ '3150G': '3.5',
+ 'Pro 3150G': '3.5',
+ '3150GE': '3.3',
+ 'Pro 3150GE': '3.3',
+ '3200G': '3.6',
+ 'Pro 3200G': '3.6',
+ '3200GE': '3.3',
+ 'Pro 3200GE': '3.3',
+ '3350G': '3.6',
+ 'Pro 3350G': '3.6',
+ '3350GE': '3.3',
+ 'Pro 3350GE': '3.3',
+ '3400G': '3.7',
+ 'Pro 3400G': '3.7',
+ '3400GE': '3.3',
+ 'Pro 3400GE': '3.3',
+
+ // ZEN+ Mobile
+ '3300U': '2.1',
+ 'PRO 3300U': '2.1',
+ '3450U': '2.1',
+ '3500U': '2.1',
+ 'PRO 3500U': '2.1',
+ '3500C': '2.1',
+ '3550H': '2.1',
+ '3580U': '2.1',
+ '3700U': '2.3',
+ 'PRO 3700U': '2.3',
+ '3700C': '2.3',
+ '3750H': '2.3',
+ '3780U': '2.3',
+
+ // ZEN2 Desktop CPUS
+ '3100': '3.6',
+ '3300X': '3.8',
+ '3500': '3.6',
+ '3500X': '3.6',
+ '3600': '3.6',
+ 'Pro 3600': '3.6',
+ '3600X': '3.8',
+ '3600XT': '3.8',
+ 'Pro 3700': '3.6',
+ '3700X': '3.6',
+ '3800X': '3.9',
+ '3800XT': '3.9',
+ '3900': '3.1',
+ 'Pro 3900': '3.1',
+ '3900X': '3.8',
+ '3900XT': '3.8',
+ '3950X': '3.5',
+ '3960X': '3.8',
+ '3970X': '3.7',
+ '3990X': '2.9',
+ '3945WX': '4.0',
+ '3955WX': '3.9',
+ '3975WX': '3.5',
+ '3995WX': '2.7',
+
+ // ZEN2 Desktop APUs
+ '4300GE': '3.5',
+ 'Pro 4300GE': '3.5',
+ '4300G': '3.8',
+ 'Pro 4300G': '3.8',
+ '4600GE': '3.3',
+ 'Pro 4650GE': '3.3',
+ '4600G': '3.7',
+ 'Pro 4650G': '3.7',
+ '4700GE': '3.1',
+ 'Pro 4750GE': '3.1',
+ '4700G': '3.6',
+ 'Pro 4750G': '3.6',
+ '4300U': '2.7',
+ '4450U': '2.5',
+ 'Pro 4450U': '2.5',
+ '4500U': '2.3',
+ '4600U': '2.1',
+ 'PRO 4650U': '2.1',
+ '4680U': '2.1',
+ '4600HS': '3.0',
+ '4600H': '3.0',
+ '4700U': '2.0',
+ 'PRO 4750U': '1.7',
+ '4800U': '1.8',
+ '4800HS': '2.9',
+ '4800H': '2.9',
+ '4900HS': '3.0',
+ '4900H': '3.3',
+ '5300U': '2.6',
+ '5500U': '2.1',
+ '5700U': '1.8',
+
+ // ZEN2 - EPYC
+ '7232P': '3.1',
+ '7302P': '3.0',
+ '7402P': '2.8',
+ '7502P': '2.5',
+ '7702P': '2.0',
+ '7252': '3.1',
+ '7262': '3.2',
+ '7272': '2.9',
+ '7282': '2.8',
+ '7302': '3.0',
+ '7352': '2.3',
+ '7402': '2.8',
+ '7452': '2.35',
+ '7502': '2.5',
+ '7532': '2.4',
+ '7542': '2.9',
+ '7552': '2.2',
+ '7642': '2.3',
+ '7662': '2.0',
+ '7702': '2.0',
+ '7742': '2.25',
+ '7H12': '2.6',
+ '7F32': '3.7',
+ '7F52': '3.5',
+ '7F72': '3.2',
+
+ // Epyc (Milan)
+
+ '7763': '2.45',
+ '7713': '2.0',
+ '7713P': '2.0',
+ '7663': '2.0',
+ '7643': '2.3',
+ '75F3': '2.95',
+ '7543': '2.8',
+ '7543P': '2.8',
+ '7513': '2.6',
+ '7453': '2.75',
+ '74F3': '3.2',
+ '7443': '2.85',
+ '7443P': '2.85',
+ '7413': '2.65',
+ '73F3': '3.5',
+ '7343': '3.2',
+ '7313': '3.0',
+ '7313P': '3.0',
+ '72F3': '3.7',
+
+ // ZEN3
+ '5600X': '3.7',
+ '5800X': '3.8',
+ '5900X': '3.7',
+ '5950X': '3.4'
+};
+
+
+const socketTypes = {
+ 1: 'Other',
+ 2: 'Unknown',
+ 3: 'Daughter Board',
+ 4: 'ZIF Socket',
+ 5: 'Replacement/Piggy Back',
+ 6: 'None',
+ 7: 'LIF Socket',
+ 8: 'Slot 1',
+ 9: 'Slot 2',
+ 10: '370 Pin Socket',
+ 11: 'Slot A',
+ 12: 'Slot M',
+ 13: '423',
+ 14: 'A (Socket 462)',
+ 15: '478',
+ 16: '754',
+ 17: '940',
+ 18: '939',
+ 19: 'mPGA604',
+ 20: 'LGA771',
+ 21: 'LGA775',
+ 22: 'S1',
+ 23: 'AM2',
+ 24: 'F (1207)',
+ 25: 'LGA1366',
+ 26: 'G34',
+ 27: 'AM3',
+ 28: 'C32',
+ 29: 'LGA1156',
+ 30: 'LGA1567',
+ 31: 'PGA988A',
+ 32: 'BGA1288',
+ 33: 'rPGA988B',
+ 34: 'BGA1023',
+ 35: 'BGA1224',
+ 36: 'LGA1155',
+ 37: 'LGA1356',
+ 38: 'LGA2011',
+ 39: 'FS1',
+ 40: 'FS2',
+ 41: 'FM1',
+ 42: 'FM2',
+ 43: 'LGA2011-3',
+ 44: 'LGA1356-3',
+ 45: 'LGA1150',
+ 46: 'BGA1168',
+ 47: 'BGA1234',
+ 48: 'BGA1364',
+ 49: 'AM4',
+ 50: 'LGA1151',
+ 51: 'BGA1356',
+ 52: 'BGA1440',
+ 53: 'BGA1515',
+ 54: 'LGA3647-1',
+ 55: 'SP3',
+ 56: 'SP3r2',
+ 57: 'LGA2066',
+ 58: 'BGA1392',
+ 59: 'BGA1510',
+ 60: 'BGA1528',
+ 61: 'LGA4189',
+ 62: 'LGA1200',
+ 63: 'LGA4677',
+};
+
+const socketTypesByName = {
+ 'LGA1150': 'i7-5775C i3-4340 i3-4170 G3250 i3-4160T i3-4160 E3-1231 G3258 G3240 i7-4790S i7-4790K i7-4790 i5-4690K i5-4690 i5-4590T i5-4590S i5-4590 i5-4460 i3-4360 i3-4150 G1820 G3420 G3220 i7-4771 i5-4440 i3-4330 i3-4130T i3-4130 E3-1230 i7-4770S i7-4770K i7-4770 i5-4670K i5-4670 i5-4570T i5-4570S i5-4570 i5-4430',
+ 'LGA1151': 'i9-9900KS E-2288G E-2224 G5420 i9-9900T i9-9900 i7-9700T i7-9700F i7-9700E i7-9700 i5-9600 i5-9500T i5-9500F i5-9500 i5-9400T i3-9350K i3-9300 i3-9100T i3-9100F i3-9100 G4930 i9-9900KF i7-9700KF i5-9600KF i5-9400F i5-9400 i3-9350KF i9-9900K i7-9700K i5-9600K G5500 G5400 i7-8700T i7-8086K i5-8600 i5-8500T i5-8500 i5-8400T i3-8300 i3-8100T G4900 i7-8700K i7-8700 i5-8600K i5-8400 i3-8350K i3-8100 E3-1270 G4600 G4560 i7-7700T i7-7700K i7-7700 i5-7600K i5-7600 i5-7500T i5-7500 i5-7400 i3-7350K i3-7300 i3-7100T i3-7100 G3930 G3900 G4400 i7-6700T i7-6700K i7-6700 i5-6600K i5-6600 i5-6500T i5-6500 i5-6400T i5-6400 i3-6300 i3-6100T i3-6100 E3-1270 E3-1270 T4500 T4400',
+ '1155': 'G440 G460 G465 G470 G530T G540T G550T G1610T G1620T G530 G540 G1610 G550 G1620 G555 G1630 i3-2100T i3-2120T i3-3220T i3-3240T i3-3250T i3-2100 i3-2105 i3-2102 i3-3210 i3-3220 i3-2125 i3-2120 i3-3225 i3-2130 i3-3245 i3-3240 i3-3250 i5-3570T i5-2500T i5-2400S i5-2405S i5-2390T i5-3330S i5-2500S i5-3335S i5-2300 i5-3450S i5-3340S i5-3470S i5-3475S i5-3470T i5-2310 i5-3550S i5-2320 i5-3330 i5-3350P i5-3450 i5-2400 i5-3340 i5-3570S i5-2380P i5-2450P i5-3470 i5-2500K i5-3550 i5-2500 i5-3570 i5-3570K i5-2550K i7-3770T i7-2600S i7-3770S i7-2600K i7-2600 i7-3770 i7-3770K i7-2700K G620T G630T G640T G2020T G645T G2100T G2030T G622 G860T G620 G632 G2120T G630 G640 G2010 G840 G2020 G850 G645 G2030 G860 G2120 G870 G2130 G2140 E3-1220L E3-1220L E3-1260L E3-1265L E3-1220 E3-1225 E3-1220 E3-1235 E3-1225 E3-1230 E3-1230 E3-1240 E3-1245 E3-1270 E3-1275 E3-1240 E3-1245 E3-1270 E3-1280 E3-1275 E3-1290 E3-1280 E3-1290'
+};
+
+function getSocketTypesByName(str) {
+ let result = '';
+ for (const key in socketTypesByName) {
+ const names = socketTypesByName[key].split(' ');
+ for (let i = 0; i < names.length; i++) {
+ if (str.indexOf(names[i]) >= 0) {
+ result = key;
+ }
+ }
+ }
+ return result;
+}
+
+function cpuManufacturer(str) {
+ let result = str;
+ str = str.toLowerCase();
+
+ if (str.indexOf('intel') >= 0) { result = 'Intel'; }
+ if (str.indexOf('amd') >= 0) { result = 'AMD'; }
+ if (str.indexOf('qemu') >= 0) { result = 'QEMU'; }
+ if (str.indexOf('hygon') >= 0) { result = 'Hygon'; }
+ if (str.indexOf('centaur') >= 0) { result = 'WinChip/Via'; }
+ if (str.indexOf('vmware') >= 0) { result = 'VMware'; }
+ if (str.indexOf('Xen') >= 0) { result = 'Xen Hypervisor'; }
+ if (str.indexOf('tcg') >= 0) { result = 'QEMU'; }
+ if (str.indexOf('apple') >= 0) { result = 'Apple'; }
+
+ return result;
+}
+
+function cpuBrandManufacturer(res) {
+ res.brand = res.brand.replace(/\(R\)+/g, '®').replace(/\s+/g, ' ').trim();
+ res.brand = res.brand.replace(/\(TM\)+/g, '™').replace(/\s+/g, ' ').trim();
+ res.brand = res.brand.replace(/\(C\)+/g, '©').replace(/\s+/g, ' ').trim();
+ res.brand = res.brand.replace(/CPU+/g, '').replace(/\s+/g, ' ').trim();
+ res.manufacturer = cpuManufacturer(res.brand);
+
+ let parts = res.brand.split(' ');
+ parts.shift();
+ res.brand = parts.join(' ');
+ return res;
+}
+
+function getAMDSpeed(brand) {
+ let result = '0';
+ for (let key in AMDBaseFrequencies) {
+ if ({}.hasOwnProperty.call(AMDBaseFrequencies, key)) {
+ let parts = key.split('|');
+ let found = 0;
+ parts.forEach(item => {
+ if (brand.indexOf(item) > -1) {
+ found++;
+ }
+ });
+ if (found === parts.length) {
+ result = AMDBaseFrequencies[key];
+ }
+ }
+ }
+ return parseFloat(result);
+}
+
+// --------------------------
+// CPU - brand, speed
+
+function getCpu() {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ const UNKNOWN = 'unknown';
+ let result = {
+ manufacturer: UNKNOWN,
+ brand: UNKNOWN,
+ vendor: '',
+ family: '',
+ model: '',
+ stepping: '',
+ revision: '',
+ voltage: '',
+ speed: 0,
+ speedMin: 0,
+ speedMax: 0,
+ governor: '',
+ cores: util.cores(),
+ physicalCores: util.cores(),
+ performanceCores: util.cores(),
+ efficiencyCores: 0,
+ processors: 1,
+ socket: '',
+ flags: '',
+ virtualization: false,
+ cache: {}
+ };
+ cpuFlags().then(flags => {
+ result.flags = flags;
+ result.virtualization = flags.indexOf('vmx') > -1 || flags.indexOf('svm') > -1;
+ if (_darwin) {
+ exec('sysctl machdep.cpu hw.cpufrequency_max hw.cpufrequency_min hw.packages hw.physicalcpu_max hw.ncpu hw.tbfrequency hw.cpufamily hw.cpusubfamily', function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ const modelline = util.getValue(lines, 'machdep.cpu.brand_string');
+ const modellineParts = modelline.split('@');
+ result.brand = modellineParts[0].trim();
+ const speed = modellineParts[1] ? modellineParts[1].trim() : '0';
+ result.speed = parseFloat(speed.replace(/GHz+/g, ''));
+ let tbFrequency = util.getValue(lines, 'hw.tbfrequency') / 1000000000.0;
+ tbFrequency = tbFrequency < 0.1 ? tbFrequency * 100 : tbFrequency;
+ result.speed = result.speed === 0 ? tbFrequency : result.speed;
+
+ _cpu_speed = result.speed;
+ result = cpuBrandManufacturer(result);
+ result.speedMin = util.getValue(lines, 'hw.cpufrequency_min') ? (util.getValue(lines, 'hw.cpufrequency_min') / 1000000000.0) : result.speed;
+ result.speedMax = util.getValue(lines, 'hw.cpufrequency_max') ? (util.getValue(lines, 'hw.cpufrequency_max') / 1000000000.0) : result.speed;
+ result.vendor = util.getValue(lines, 'machdep.cpu.vendor') || 'Apple';
+ result.family = util.getValue(lines, 'machdep.cpu.family') || util.getValue(lines, 'hw.cpufamily');
+ result.model = util.getValue(lines, 'machdep.cpu.model');
+ result.stepping = util.getValue(lines, 'machdep.cpu.stepping') || util.getValue(lines, 'hw.cpusubfamily');
+ result.virtualization = true;
+ const countProcessors = util.getValue(lines, 'hw.packages');
+ const countCores = util.getValue(lines, 'hw.physicalcpu_max');
+ const countThreads = util.getValue(lines, 'hw.ncpu');
+ if (os.arch() === 'arm64') {
+ const clusters = execSync('ioreg -c IOPlatformDevice -d 3 -r | grep cluster-type').toString().split('\n');
+ const efficiencyCores = clusters.filter(line => line.indexOf('"E"') >= 0).length;
+ const performanceCores = clusters.filter(line => line.indexOf('"P"') >= 0).length;
+ result.socket = 'SOC';
+ result.efficiencyCores = efficiencyCores;
+ result.performanceCores = performanceCores;
+ }
+ if (countProcessors) {
+ result.processors = parseInt(countProcessors) || 1;
+ }
+ if (countCores && countThreads) {
+ result.cores = parseInt(countThreads) || util.cores();
+ result.physicalCores = parseInt(countCores) || util.cores();
+ }
+ cpuCache().then((res) => {
+ result.cache = res;
+ resolve(result);
+ });
+ });
+ }
+ if (_linux) {
+ let modelline = '';
+ let lines = [];
+ if (os.cpus()[0] && os.cpus()[0].model) { modelline = os.cpus()[0].model; }
+ exec('export LC_ALL=C; lscpu; echo -n "Governor: "; cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null; echo; unset LC_ALL', function (error, stdout) {
+ if (!error) {
+ lines = stdout.toString().split('\n');
+ }
+ modelline = util.getValue(lines, 'model name') || modelline;
+ const modellineParts = modelline.split('@');
+ result.brand = modellineParts[0].trim();
+ result.speed = modellineParts[1] ? parseFloat(modellineParts[1].trim()) : 0;
+ if (result.speed === 0 && (result.brand.indexOf('AMD') > -1 || result.brand.toLowerCase().indexOf('ryzen') > -1)) {
+ result.speed = getAMDSpeed(result.brand);
+ }
+ if (result.speed === 0) {
+ const current = getCpuCurrentSpeedSync();
+ if (current.avg !== 0) { result.speed = current.avg; }
+ }
+ _cpu_speed = result.speed;
+ result.speedMin = Math.round(parseFloat(util.getValue(lines, 'cpu min mhz').replace(/,/g, '.')) / 10.0) / 100;
+ result.speedMax = Math.round(parseFloat(util.getValue(lines, 'cpu max mhz').replace(/,/g, '.')) / 10.0) / 100;
+
+ result = cpuBrandManufacturer(result);
+ result.vendor = cpuManufacturer(util.getValue(lines, 'vendor id'));
+
+ result.family = util.getValue(lines, 'cpu family');
+ result.model = util.getValue(lines, 'model:');
+ result.stepping = util.getValue(lines, 'stepping');
+ result.revision = util.getValue(lines, 'cpu revision');
+ result.cache.l1d = util.getValue(lines, 'l1d cache');
+ if (result.cache.l1d) { result.cache.l1d = parseInt(result.cache.l1d) * (result.cache.l1d.indexOf('M') !== -1 ? 1024 * 1024 : (result.cache.l1d.indexOf('K') !== -1 ? 1024 : 1)); }
+ result.cache.l1i = util.getValue(lines, 'l1i cache');
+ if (result.cache.l1i) { result.cache.l1i = parseInt(result.cache.l1i) * (result.cache.l1i.indexOf('M') !== -1 ? 1024 * 1024 : (result.cache.l1i.indexOf('K') !== -1 ? 1024 : 1)); }
+ result.cache.l2 = util.getValue(lines, 'l2 cache');
+ if (result.cache.l2) { result.cache.l2 = parseInt(result.cache.l2) * (result.cache.l2.indexOf('M') !== -1 ? 1024 * 1024 : (result.cache.l2.indexOf('K') !== -1 ? 1024 : 1)); }
+ result.cache.l3 = util.getValue(lines, 'l3 cache');
+ if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3) * (result.cache.l3.indexOf('M') !== -1 ? 1024 * 1024 : (result.cache.l3.indexOf('K') !== -1 ? 1024 : 1)); }
+
+ const threadsPerCore = util.getValue(lines, 'thread(s) per core') || '1';
+ const processors = util.getValue(lines, 'socket(s)') || '1';
+ let threadsPerCoreInt = parseInt(threadsPerCore, 10); // threads per code (normally only for performance cores)
+ let processorsInt = parseInt(processors, 10) || 1; // number of sockets / processor units in machine (normally 1)
+ const coresPerSocket = parseInt(util.getValue(lines, 'core(s) per socket'), 10); // number of cores (e.g. 16 on i12900)
+ result.physicalCores = coresPerSocket ? coresPerSocket * processorsInt : result.cores / threadsPerCoreInt;
+ result.performanceCores = threadsPerCoreInt > 1 ? result.cores - result.physicalCores : result.cores;
+ result.efficiencyCores = threadsPerCoreInt > 1 ? result.cores - (threadsPerCoreInt * result.performanceCores) : 0;
+ result.processors = processorsInt;
+ result.governor = util.getValue(lines, 'governor') || '';
+
+ // Test Raspberry
+ if (result.vendor === 'ARM') {
+ const linesRpi = fs.readFileSync('/proc/cpuinfo').toString().split('\n');
+ const rPIRevision = util.decodePiCpuinfo(linesRpi);
+ if (rPIRevision.model.toLowerCase().indexOf('raspberry') >= 0) {
+ result.family = result.manufacturer;
+ result.manufacturer = rPIRevision.manufacturer;
+ result.brand = rPIRevision.processor;
+ result.revision = rPIRevision.revisionCode;
+ result.socket = 'SOC';
+ }
+ }
+
+ // socket type
+ let lines2 = [];
+ exec('export LC_ALL=C; dmidecode –t 4 2>/dev/null | grep "Upgrade: Socket"; unset LC_ALL', function (error2, stdout2) {
+ lines2 = stdout2.toString().split('\n');
+ if (lines2 && lines2.length) {
+ result.socket = util.getValue(lines2, 'Upgrade').replace('Socket', '').trim() || result.socket;
+ }
+ resolve(result);
+ });
+ });
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ let modelline = '';
+ let lines = [];
+ if (os.cpus()[0] && os.cpus()[0].model) { modelline = os.cpus()[0].model; }
+ exec('export LC_ALL=C; dmidecode -t 4; dmidecode -t 7 unset LC_ALL', function (error, stdout) {
+ let cache = [];
+ if (!error) {
+ const data = stdout.toString().split('# dmidecode');
+ const processor = data.length > 1 ? data[1] : '';
+ cache = data.length > 2 ? data[2].split('Cache Information') : [];
+
+ lines = processor.split('\n');
+ }
+ result.brand = modelline.split('@')[0].trim();
+ result.speed = modelline.split('@')[1] ? parseFloat(modelline.split('@')[1].trim()) : 0;
+ if (result.speed === 0 && (result.brand.indexOf('AMD') > -1 || result.brand.toLowerCase().indexOf('ryzen') > -1)) {
+ result.speed = getAMDSpeed(result.brand);
+ }
+ if (result.speed === 0) {
+ const current = getCpuCurrentSpeedSync();
+ if (current.avg !== 0) { result.speed = current.avg; }
+ }
+ _cpu_speed = result.speed;
+ result.speedMin = result.speed;
+ result.speedMax = Math.round(parseFloat(util.getValue(lines, 'max speed').replace(/Mhz/g, '')) / 10.0) / 100;
+
+ result = cpuBrandManufacturer(result);
+ result.vendor = cpuManufacturer(util.getValue(lines, 'manufacturer'));
+ let sig = util.getValue(lines, 'signature');
+ sig = sig.split(',');
+ for (let i = 0; i < sig.length; i++) {
+ sig[i] = sig[i].trim();
+ }
+ result.family = util.getValue(sig, 'Family', ' ', true);
+ result.model = util.getValue(sig, 'Model', ' ', true);
+ result.stepping = util.getValue(sig, 'Stepping', ' ', true);
+ result.revision = '';
+ const voltage = parseFloat(util.getValue(lines, 'voltage'));
+ result.voltage = isNaN(voltage) ? '' : voltage.toFixed(2);
+ for (let i = 0; i < cache.length; i++) {
+ lines = cache[i].split('\n');
+ let cacheType = util.getValue(lines, 'Socket Designation').toLowerCase().replace(' ', '-').split('-');
+ cacheType = cacheType.length ? cacheType[0] : '';
+ const sizeParts = util.getValue(lines, 'Installed Size').split(' ');
+ let size = parseInt(sizeParts[0], 10);
+ const unit = sizeParts.length > 1 ? sizeParts[1] : 'kb';
+ size = size * (unit === 'kb' ? 1024 : (unit === 'mb' ? 1024 * 1024 : (unit === 'gb' ? 1024 * 1024 * 1024 : 1)));
+ if (cacheType) {
+ if (cacheType === 'l1') {
+ result.cache[cacheType + 'd'] = size / 2;
+ result.cache[cacheType + 'i'] = size / 2;
+ } else {
+ result.cache[cacheType] = size;
+ }
+ }
+ }
+ // socket type
+ result.socket = util.getValue(lines, 'Upgrade').replace('Socket', '').trim();
+ // # threads / # cores
+ const threadCount = util.getValue(lines, 'thread count').trim();
+ const coreCount = util.getValue(lines, 'core count').trim();
+ if (coreCount && threadCount) {
+ result.cores = parseInt(threadCount, 10);
+ result.physicalCores = parseInt(coreCount, 10);
+ }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ resolve(result);
+ }
+ if (_windows) {
+ try {
+ const workload = [];
+ workload.push(util.powerShell('Get-WmiObject Win32_processor | select Name, Revision, L2CacheSize, L3CacheSize, Manufacturer, MaxClockSpeed, Description, UpgradeMethod, Caption, NumberOfLogicalProcessors, NumberOfCores | fl'));
+ workload.push(util.powerShell('Get-WmiObject Win32_CacheMemory | select CacheType,InstalledSize,Level | fl'));
+ workload.push(util.powerShell('(Get-CimInstance Win32_ComputerSystem).HypervisorPresent'));
+
+ Promise.all(
+ workload
+ ).then((data) => {
+ let lines = data[0].split('\r\n');
+ let name = util.getValue(lines, 'name', ':') || '';
+ if (name.indexOf('@') >= 0) {
+ result.brand = name.split('@')[0].trim();
+ result.speed = name.split('@')[1] ? parseFloat(name.split('@')[1].trim()) : 0;
+ _cpu_speed = result.speed;
+ } else {
+ result.brand = name.trim();
+ result.speed = 0;
+ }
+ result = cpuBrandManufacturer(result);
+ result.revision = util.getValue(lines, 'revision', ':');
+ result.cache.l1d = 0;
+ result.cache.l1i = 0;
+ result.cache.l2 = util.getValue(lines, 'l2cachesize', ':');
+ result.cache.l3 = util.getValue(lines, 'l3cachesize', ':');
+ if (result.cache.l2) { result.cache.l2 = parseInt(result.cache.l2, 10) * 1024; }
+ if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3, 10) * 1024; }
+ result.vendor = util.getValue(lines, 'manufacturer', ':');
+ result.speedMax = Math.round(parseFloat(util.getValue(lines, 'maxclockspeed', ':').replace(/,/g, '.')) / 10.0) / 100;
+ if (result.speed === 0 && (result.brand.indexOf('AMD') > -1 || result.brand.toLowerCase().indexOf('ryzen') > -1)) {
+ result.speed = getAMDSpeed(result.brand);
+ }
+ if (result.speed === 0) {
+ result.speed = result.speedMax;
+ }
+ result.speedMin = result.speed;
+
+ let description = util.getValue(lines, 'description', ':').split(' ');
+ for (let i = 0; i < description.length; i++) {
+ if (description[i].toLowerCase().startsWith('family') && (i + 1) < description.length && description[i + 1]) {
+ result.family = description[i + 1];
+ }
+ if (description[i].toLowerCase().startsWith('model') && (i + 1) < description.length && description[i + 1]) {
+ result.model = description[i + 1];
+ }
+ if (description[i].toLowerCase().startsWith('stepping') && (i + 1) < description.length && description[i + 1]) {
+ result.stepping = description[i + 1];
+ }
+ }
+ // socket type
+ const socketId = util.getValue(lines, 'UpgradeMethod', ':');
+ if (socketTypes[socketId]) {
+ result.socket = socketTypes[socketId];
+ }
+ const socketByName = getSocketTypesByName(name);
+ if (socketByName) {
+ result.socket = socketByName;
+ }
+ // # threads / # cores
+ const countProcessors = util.countLines(lines, 'Caption');
+ const countThreads = util.getValue(lines, 'NumberOfLogicalProcessors', ':');
+ const countCores = util.getValue(lines, 'NumberOfCores', ':');
+ if (countProcessors) {
+ result.processors = parseInt(countProcessors) || 1;
+ }
+ if (countCores && countThreads) {
+ result.cores = parseInt(countThreads) || util.cores();
+ result.physicalCores = parseInt(countCores) || util.cores();
+ }
+ if (countProcessors > 1) {
+ result.cores = result.cores * countProcessors;
+ result.physicalCores = result.physicalCores * countProcessors;
+ }
+ const parts = data[1].split(/\n\s*\n/);
+ parts.forEach(function (part) {
+ lines = part.split('\r\n');
+ const cacheType = util.getValue(lines, 'CacheType');
+ const level = util.getValue(lines, 'Level');
+ const installedSize = util.getValue(lines, 'InstalledSize');
+ // L1 Instructions
+ if (level === '3' && cacheType === '3') {
+ result.cache.l1i = parseInt(installedSize, 10);
+ }
+ // L1 Data
+ if (level === '3' && cacheType === '4') {
+ result.cache.l1d = parseInt(installedSize, 10);
+ }
+ // L1 all
+ if (level === '3' && cacheType === '5' && !result.cache.l1i && !result.cache.l1d) {
+ result.cache.l1i = parseInt(installedSize, 10) / 2;
+ result.cache.l1d = parseInt(installedSize, 10) / 2;
+ }
+ });
+ const hyperv = data[2] ? data[2].toString().toLowerCase() : '';
+ result.virtualization = hyperv.indexOf('true') !== -1;
+
+ resolve(result);
+ });
+ } catch (e) {
+ resolve(result);
+ }
+ }
+ });
+ });
+ });
+}
+
+// --------------------------
+// CPU - Processor Data
+
+function cpu(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ getCpu().then(result => {
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+ });
+}
+
+exports.cpu = cpu;
+
+// --------------------------
+// CPU - current speed - in GHz
+
+function getCpuCurrentSpeedSync() {
+
+ let cpus = os.cpus();
+ let minFreq = 999999999;
+ let maxFreq = 0;
+ let avgFreq = 0;
+ let cores = [];
+
+ if (cpus && cpus.length) {
+ for (let i in cpus) {
+ if ({}.hasOwnProperty.call(cpus, i)) {
+ let freq = cpus[i].speed > 100 ? (cpus[i].speed + 1) / 1000 : cpus[i].speed / 10;
+ avgFreq = avgFreq + freq;
+ if (freq > maxFreq) { maxFreq = freq; }
+ if (freq < minFreq) { minFreq = freq; }
+ cores.push(parseFloat(freq.toFixed(2)));
+ }
+ }
+ avgFreq = avgFreq / cpus.length;
+ return {
+ min: parseFloat(minFreq.toFixed(2)),
+ max: parseFloat(maxFreq.toFixed(2)),
+ avg: parseFloat((avgFreq).toFixed(2)),
+ cores: cores
+ };
+ } else {
+ return {
+ min: 0,
+ max: 0,
+ avg: 0,
+ cores: cores
+ };
+ }
+}
+
+function cpuCurrentSpeed(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = getCpuCurrentSpeedSync();
+ if (result.avg === 0 && _cpu_speed !== 0) {
+ const currCpuSpeed = parseFloat(_cpu_speed);
+ result = {
+ min: currCpuSpeed,
+ max: currCpuSpeed,
+ avg: currCpuSpeed,
+ cores: []
+ };
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+}
+
+exports.cpuCurrentSpeed = cpuCurrentSpeed;
+
+// --------------------------
+// CPU - temperature
+// if sensors are installed
+
+function cpuTemperature(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = {
+ main: null,
+ cores: [],
+ max: null,
+ socket: [],
+ chipset: null
+ };
+ if (_linux) {
+ // CPU Chipset, Socket
+ try {
+ const cmd = 'cat /sys/class/thermal/thermal_zone*/type 2>/dev/null; echo "-----"; cat /sys/class/thermal/thermal_zone*/temp 2>/dev/null;';
+ const parts = execSync(cmd).toString().split('-----\n');
+ if (parts.length === 2) {
+ const lines = parts[0].split('\n');
+ const lines2 = parts[1].split('\n');
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i].trim();
+ if (line.startsWith('acpi') && lines2[i]) {
+ result.socket.push(Math.round(parseInt(lines2[i], 10) / 100) / 10);
+ }
+ if (line.startsWith('pch') && lines2[i]) {
+ result.chipset = Math.round(parseInt(lines2[i], 10) / 100) / 10;
+ }
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+
+ const cmd = 'for mon in /sys/class/hwmon/hwmon*; do for label in "$mon"/temp*_label; do if [ -f $label ]; then value=${label%_*}_input; echo $(cat "$label")___$(cat "$value"); fi; done; done;';
+ try {
+ exec(cmd, function (error, stdout) {
+ stdout = stdout.toString();
+ const tdiePos = stdout.toLowerCase().indexOf('tdie');
+ if (tdiePos !== -1) {
+ stdout = stdout.substring(tdiePos);
+ }
+ let lines = stdout.split('\n');
+ lines.forEach(line => {
+ const parts = line.split('___');
+ const label = parts[0];
+ const value = parts.length > 1 && parts[1] ? parts[1] : '0';
+ if (value && (label === undefined || (label && label.toLowerCase().startsWith('core')))) {
+ result.cores.push(Math.round(parseInt(value, 10) / 100) / 10);
+ } else if (value && label && result.main === null) {
+ result.main = Math.round(parseInt(value, 10) / 100) / 10;
+ }
+ });
+
+ if (result.cores.length > 0) {
+ result.main = Math.round(result.cores.reduce((a, b) => a + b, 0) / result.cores.length);
+ let maxtmp = Math.max.apply(Math, result.cores);
+ result.max = (maxtmp > result.main) ? maxtmp : result.main;
+ }
+ if (result.main !== null) {
+ if (result.max === null) {
+ result.max = result.main;
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ return;
+ }
+ exec('sensors', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ let tdieTemp = null;
+ let newSectionStarts = true;
+ let section = '';
+ lines.forEach(function (line) {
+ // determine section
+ if (line.trim() === '') {
+ newSectionStarts = true;
+ } else if (newSectionStarts) {
+ if (line.trim().toLowerCase().startsWith('acpi')) { section = 'acpi'; }
+ if (line.trim().toLowerCase().startsWith('pch')) { section = 'pch'; }
+ if (line.trim().toLowerCase().startsWith('core')) { section = 'core'; }
+ newSectionStarts = false;
+ }
+ let regex = /[+-]([^°]*)/g;
+ let temps = line.match(regex);
+ let firstPart = line.split(':')[0].toUpperCase();
+ if (section === 'acpi') {
+ // socket temp
+ if (firstPart.indexOf('TEMP') !== -1) {
+ result.socket.push(parseFloat(temps));
+ }
+ } else if (section === 'pch') {
+ // chipset temp
+ if (firstPart.indexOf('TEMP') !== -1) {
+ result.chipset = parseFloat(temps);
+ }
+ }
+ // cpu temp
+ if (firstPart.indexOf('PHYSICAL') !== -1 || firstPart.indexOf('PACKAGE') !== -1) {
+ result.main = parseFloat(temps);
+ }
+ if (firstPart.indexOf('CORE ') !== -1) {
+ result.cores.push(parseFloat(temps));
+ }
+ if (firstPart.indexOf('TDIE') !== -1 && tdieTemp === null) {
+ tdieTemp = parseFloat(temps);
+ }
+ });
+ if (result.cores.length > 0) {
+ result.main = Math.round(result.cores.reduce((a, b) => a + b, 0) / result.cores.length);
+ let maxtmp = Math.max.apply(Math, result.cores);
+ result.max = (maxtmp > result.main) ? maxtmp : result.main;
+ } else {
+ if (result.main === null && tdieTemp !== null) {
+ result.main = tdieTemp;
+ result.max = tdieTemp;
+ }
+ }
+ if (result.main !== null || result.max !== null) {
+ if (callback) { callback(result); }
+ resolve(result);
+ return;
+ }
+ }
+ fs.stat('/sys/class/thermal/thermal_zone0/temp', function (err) {
+ if (err === null) {
+ fs.readFile('/sys/class/thermal/thermal_zone0/temp', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ if (lines.length > 0) {
+ result.main = parseFloat(lines[0]) / 1000.0;
+ result.max = result.main;
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ exec('/opt/vc/bin/vcgencmd measure_temp', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ if (lines.length > 0 && lines[0].indexOf('=')) {
+ result.main = parseFloat(lines[0].split('=')[1]);
+ result.max = result.main;
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ });
+ });
+ });
+ } catch (er) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ exec('sysctl dev.cpu | grep temp', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ let sum = 0;
+ lines.forEach(function (line) {
+ const parts = line.split(':');
+ if (parts.length > 1) {
+ const temp = parseFloat(parts[1].replace(',', '.'));
+ if (temp > result.max) { result.max = temp; }
+ sum = sum + temp;
+ result.cores.push(temp);
+ }
+ });
+ if (result.cores.length) {
+ result.main = Math.round(sum / result.cores.length * 100) / 100;
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ let osxTemp = null;
+ try {
+ osxTemp = require('osx-temperature-sensor');
+ } catch (er) {
+ osxTemp = null;
+ }
+ if (osxTemp) {
+ result = osxTemp.cpuTemperature();
+ // round to 2 digits
+ if (result.main) {
+ result.main = Math.round(result.main * 100) / 100;
+ }
+ if (result.max) {
+ result.max = Math.round(result.max * 100) / 100;
+ }
+ if (result.cores && result.cores.length) {
+ for (let i = 0; i < result.cores.length; i++) {
+ result.cores[i] = Math.round(result.cores[i] * 100) / 100;
+ }
+ }
+ }
+
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_windows) {
+ try {
+ util.powerShell('Get-WmiObject MSAcpi_ThermalZoneTemperature -Namespace "root/wmi" | Select CurrentTemperature').then((stdout, error) => {
+ if (!error) {
+ let sum = 0;
+ let lines = stdout.split('\r\n').filter(line => line.trim() !== '').filter((line, idx) => idx > 0);
+ lines.forEach(function (line) {
+ let value = (parseInt(line, 10) - 2732) / 10;
+ if (!isNaN(value)) {
+ sum = sum + value;
+ if (value > result.max) { result.max = value; }
+ result.cores.push(value);
+ }
+ });
+ if (result.cores.length) {
+ result.main = sum / result.cores.length;
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.cpuTemperature = cpuTemperature;
+
+// --------------------------
+// CPU Flags
+
+function cpuFlags(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = '';
+ if (_windows) {
+ try {
+ exec('reg query "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0" /v FeatureSet', util.execOptsWin, function (error, stdout) {
+ if (!error) {
+ let flag_hex = stdout.split('0x').pop().trim();
+ let flag_bin_unpadded = parseInt(flag_hex, 16).toString(2);
+ let flag_bin = '0'.repeat(32 - flag_bin_unpadded.length) + flag_bin_unpadded;
+ // empty flags are the reserved fields in the CPUID feature bit list
+ // as found on wikipedia:
+ // https://en.wikipedia.org/wiki/CPUID
+ let all_flags = [
+ 'fpu', 'vme', 'de', 'pse', 'tsc', 'msr', 'pae', 'mce', 'cx8', 'apic',
+ '', 'sep', 'mtrr', 'pge', 'mca', 'cmov', 'pat', 'pse-36', 'psn', 'clfsh',
+ '', 'ds', 'acpi', 'mmx', 'fxsr', 'sse', 'sse2', 'ss', 'htt', 'tm', 'ia64', 'pbe'
+ ];
+ for (let f = 0; f < all_flags.length; f++) {
+ if (flag_bin[f] === '1' && all_flags[f] !== '') {
+ result += ' ' + all_flags[f];
+ }
+ }
+ result = result.trim().toLowerCase();
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_linux) {
+ try {
+
+ exec('export LC_ALL=C; lscpu; unset LC_ALL', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ if (line.split(':')[0].toUpperCase().indexOf('FLAGS') !== -1) {
+ result = line.split(':')[1].trim().toLowerCase();
+ }
+ });
+ }
+ if (!result) {
+ fs.readFile('/proc/cpuinfo', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result = util.getValue(lines, 'features', ':', true).toLowerCase();
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ exec('export LC_ALL=C; dmidecode -t 4 2>/dev/null; unset LC_ALL', function (error, stdout) {
+ let flags = [];
+ if (!error) {
+ let parts = stdout.toString().split('\tFlags:');
+ const lines = parts.length > 1 ? parts[1].split('\tVersion:')[0].split('\n') : [];
+ lines.forEach(function (line) {
+ let flag = (line.indexOf('(') ? line.split('(')[0].toLowerCase() : '').trim().replace(/\t/g, '');
+ if (flag) {
+ flags.push(flag);
+ }
+ });
+ }
+ result = flags.join(' ').trim().toLowerCase();
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ exec('sysctl machdep.cpu.features', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ if (lines.length > 0 && lines[0].indexOf('machdep.cpu.features:') !== -1) {
+ result = lines[0].split(':')[1].trim().toLowerCase();
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.cpuFlags = cpuFlags;
+
+// --------------------------
+// CPU Cache
+
+function cpuCache(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = {
+ l1d: null,
+ l1i: null,
+ l2: null,
+ l3: null,
+ };
+ if (_linux) {
+ try {
+ exec('export LC_ALL=C; lscpu; unset LC_ALL', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ let parts = line.split(':');
+ if (parts[0].toUpperCase().indexOf('L1D CACHE') !== -1) {
+ result.l1d = parseInt(parts[1].trim()) * (parts[1].indexOf('M') !== -1 ? 1024 * 1024 : (parts[1].indexOf('K') !== -1 ? 1024 : 1));
+ }
+ if (parts[0].toUpperCase().indexOf('L1I CACHE') !== -1) {
+ result.l1i = parseInt(parts[1].trim()) * (parts[1].indexOf('M') !== -1 ? 1024 * 1024 : (parts[1].indexOf('K') !== -1 ? 1024 : 1));
+ }
+ if (parts[0].toUpperCase().indexOf('L2 CACHE') !== -1) {
+ result.l2 = parseInt(parts[1].trim()) * (parts[1].indexOf('M') !== -1 ? 1024 * 1024 : (parts[1].indexOf('K') !== -1 ? 1024 : 1));
+ }
+ if (parts[0].toUpperCase().indexOf('L3 CACHE') !== -1) {
+ result.l3 = parseInt(parts[1].trim()) * (parts[1].indexOf('M') !== -1 ? 1024 * 1024 : (parts[1].indexOf('K') !== -1 ? 1024 : 1));
+ }
+ });
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ exec('export LC_ALL=C; dmidecode -t 7 2>/dev/null; unset LC_ALL', function (error, stdout) {
+ let cache = [];
+ if (!error) {
+ const data = stdout.toString();
+ cache = data.split('Cache Information');
+ cache.shift();
+ }
+ for (let i = 0; i < cache.length; i++) {
+ const lines = cache[i].split('\n');
+ let cacheType = util.getValue(lines, 'Socket Designation').toLowerCase().replace(' ', '-').split('-');
+ cacheType = cacheType.length ? cacheType[0] : '';
+ const sizeParts = util.getValue(lines, 'Installed Size').split(' ');
+ let size = parseInt(sizeParts[0], 10);
+ const unit = sizeParts.length > 1 ? sizeParts[1] : 'kb';
+ size = size * (unit === 'kb' ? 1024 : (unit === 'mb' ? 1024 * 1024 : (unit === 'gb' ? 1024 * 1024 * 1024 : 1)));
+ if (cacheType) {
+ if (cacheType === 'l1') {
+ result.cache[cacheType + 'd'] = size / 2;
+ result.cache[cacheType + 'i'] = size / 2;
+ } else {
+ result.cache[cacheType] = size;
+ }
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ exec('sysctl hw.l1icachesize hw.l1dcachesize hw.l2cachesize hw.l3cachesize', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ let parts = line.split(':');
+ if (parts[0].toLowerCase().indexOf('hw.l1icachesize') !== -1) {
+ result.l1d = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
+ }
+ if (parts[0].toLowerCase().indexOf('hw.l1dcachesize') !== -1) {
+ result.l1i = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
+ }
+ if (parts[0].toLowerCase().indexOf('hw.l2cachesize') !== -1) {
+ result.l2 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
+ }
+ if (parts[0].toLowerCase().indexOf('hw.l3cachesize') !== -1) {
+ result.l3 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
+ }
+ });
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_windows) {
+ try {
+ util.powerShell('Get-WmiObject Win32_processor | select L2CacheSize, L3CacheSize | fl').then((stdout, error) => {
+ if (!error) {
+ let lines = stdout.split('\r\n');
+ result.l1d = 0;
+ result.l1i = 0;
+ result.l2 = util.getValue(lines, 'l2cachesize', ':');
+ result.l3 = util.getValue(lines, 'l3cachesize', ':');
+ if (result.l2) { result.l2 = parseInt(result.l2, 10) * 1024; }
+ if (result.l3) { result.l3 = parseInt(result.l3, 10) * 1024; }
+ }
+ util.powerShell('Get-WmiObject Win32_CacheMemory | select CacheType,InstalledSize,Level | fl').then((stdout, error) => {
+ if (!error) {
+ const parts = stdout.split(/\n\s*\n/);
+ parts.forEach(function (part) {
+ const lines = part.split('\r\n');
+ const cacheType = util.getValue(lines, 'CacheType');
+ const level = util.getValue(lines, 'Level');
+ const installedSize = util.getValue(lines, 'InstalledSize');
+ // L1 Instructions
+ if (level === '3' && cacheType === '3') {
+ result.l1i = parseInt(installedSize, 10);
+ }
+ // L1 Data
+ if (level === '3' && cacheType === '4') {
+ result.l1d = parseInt(installedSize, 10);
+ }
+ // L1 all
+ if (level === '3' && cacheType === '5' && !result.l1i && !result.l1d) {
+ result.l1i = parseInt(installedSize, 10) / 2;
+ result.l1d = parseInt(installedSize, 10) / 2;
+ }
+ });
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.cpuCache = cpuCache;
+
+// --------------------------
+// CPU - current load - in %
+
+function getLoad() {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let loads = os.loadavg().map(function (x) { return x / util.cores(); });
+ let avgLoad = parseFloat((Math.max.apply(Math, loads)).toFixed(2));
+ let result = {};
+
+ let now = Date.now() - _current_cpu.ms;
+ if (now >= 200) {
+ _current_cpu.ms = Date.now();
+ const cpus = os.cpus();
+ let totalUser = 0;
+ let totalSystem = 0;
+ let totalNice = 0;
+ let totalIrq = 0;
+ let totalIdle = 0;
+ let cores = [];
+ _corecount = (cpus && cpus.length) ? cpus.length : 0;
+
+ for (let i = 0; i < _corecount; i++) {
+ const cpu = cpus[i].times;
+ totalUser += cpu.user;
+ totalSystem += cpu.sys;
+ totalNice += cpu.nice;
+ totalIdle += cpu.idle;
+ totalIrq += cpu.irq;
+ let tmpTick = (_cpus && _cpus[i] && _cpus[i].totalTick ? _cpus[i].totalTick : 0);
+ let tmpLoad = (_cpus && _cpus[i] && _cpus[i].totalLoad ? _cpus[i].totalLoad : 0);
+ let tmpUser = (_cpus && _cpus[i] && _cpus[i].user ? _cpus[i].user : 0);
+ let tmpSystem = (_cpus && _cpus[i] && _cpus[i].sys ? _cpus[i].sys : 0);
+ let tmpNice = (_cpus && _cpus[i] && _cpus[i].nice ? _cpus[i].nice : 0);
+ let tmpIdle = (_cpus && _cpus[i] && _cpus[i].idle ? _cpus[i].idle : 0);
+ let tmpIrq = (_cpus && _cpus[i] && _cpus[i].irq ? _cpus[i].irq : 0);
+ _cpus[i] = cpu;
+ _cpus[i].totalTick = _cpus[i].user + _cpus[i].sys + _cpus[i].nice + _cpus[i].irq + _cpus[i].idle;
+ _cpus[i].totalLoad = _cpus[i].user + _cpus[i].sys + _cpus[i].nice + _cpus[i].irq;
+ _cpus[i].currentTick = _cpus[i].totalTick - tmpTick;
+ _cpus[i].load = (_cpus[i].totalLoad - tmpLoad);
+ _cpus[i].loadUser = (_cpus[i].user - tmpUser);
+ _cpus[i].loadSystem = (_cpus[i].sys - tmpSystem);
+ _cpus[i].loadNice = (_cpus[i].nice - tmpNice);
+ _cpus[i].loadIdle = (_cpus[i].idle - tmpIdle);
+ _cpus[i].loadIrq = (_cpus[i].irq - tmpIrq);
+ cores[i] = {};
+ cores[i].load = _cpus[i].load / _cpus[i].currentTick * 100;
+ cores[i].loadUser = _cpus[i].loadUser / _cpus[i].currentTick * 100;
+ cores[i].loadSystem = _cpus[i].loadSystem / _cpus[i].currentTick * 100;
+ cores[i].loadNice = _cpus[i].loadNice / _cpus[i].currentTick * 100;
+ cores[i].loadIdle = _cpus[i].loadIdle / _cpus[i].currentTick * 100;
+ cores[i].loadIrq = _cpus[i].loadIrq / _cpus[i].currentTick * 100;
+ cores[i].rawLoad = _cpus[i].load;
+ cores[i].rawLoadUser = _cpus[i].loadUser;
+ cores[i].rawLoadSystem = _cpus[i].loadSystem;
+ cores[i].rawLoadNice = _cpus[i].loadNice;
+ cores[i].rawLoadIdle = _cpus[i].loadIdle;
+ cores[i].rawLoadIrq = _cpus[i].loadIrq;
+ }
+ let totalTick = totalUser + totalSystem + totalNice + totalIrq + totalIdle;
+ let totalLoad = totalUser + totalSystem + totalNice + totalIrq;
+ let currentTick = totalTick - _current_cpu.tick;
+ result = {
+ avgLoad: avgLoad,
+ currentLoad: (totalLoad - _current_cpu.load) / currentTick * 100,
+ currentLoadUser: (totalUser - _current_cpu.user) / currentTick * 100,
+ currentLoadSystem: (totalSystem - _current_cpu.system) / currentTick * 100,
+ currentLoadNice: (totalNice - _current_cpu.nice) / currentTick * 100,
+ currentLoadIdle: (totalIdle - _current_cpu.idle) / currentTick * 100,
+ currentLoadIrq: (totalIrq - _current_cpu.irq) / currentTick * 100,
+ rawCurrentLoad: (totalLoad - _current_cpu.load),
+ rawCurrentLoadUser: (totalUser - _current_cpu.user),
+ rawCurrentLoadSystem: (totalSystem - _current_cpu.system),
+ rawCurrentLoadNice: (totalNice - _current_cpu.nice),
+ rawCurrentLoadIdle: (totalIdle - _current_cpu.idle),
+ rawCurrentLoadIrq: (totalIrq - _current_cpu.irq),
+ cpus: cores
+ };
+ _current_cpu = {
+ user: totalUser,
+ nice: totalNice,
+ system: totalSystem,
+ idle: totalIdle,
+ irq: totalIrq,
+ tick: totalTick,
+ load: totalLoad,
+ ms: _current_cpu.ms,
+ currentLoad: result.currentLoad,
+ currentLoadUser: result.currentLoadUser,
+ currentLoadSystem: result.currentLoadSystem,
+ currentLoadNice: result.currentLoadNice,
+ currentLoadIdle: result.currentLoadIdle,
+ currentLoadIrq: result.currentLoadIrq,
+ rawCurrentLoad: result.rawCurrentLoad,
+ rawCurrentLoadUser: result.rawCurrentLoadUser,
+ rawCurrentLoadSystem: result.rawCurrentLoadSystem,
+ rawCurrentLoadNice: result.rawCurrentLoadNice,
+ rawCurrentLoadIdle: result.rawCurrentLoadIdle,
+ rawCurrentLoadIrq: result.rawCurrentLoadIrq,
+ };
+ } else {
+ let cores = [];
+ for (let i = 0; i < _corecount; i++) {
+ cores[i] = {};
+ cores[i].load = _cpus[i].load / _cpus[i].currentTick * 100;
+ cores[i].loadUser = _cpus[i].loadUser / _cpus[i].currentTick * 100;
+ cores[i].loadSystem = _cpus[i].loadSystem / _cpus[i].currentTick * 100;
+ cores[i].loadNice = _cpus[i].loadNice / _cpus[i].currentTick * 100;
+ cores[i].loadIdle = _cpus[i].loadIdle / _cpus[i].currentTick * 100;
+ cores[i].loadIrq = _cpus[i].loadIrq / _cpus[i].currentTick * 100;
+ cores[i].rawLoad = _cpus[i].load;
+ cores[i].rawLoadUser = _cpus[i].loadUser;
+ cores[i].rawLoadSystem = _cpus[i].loadSystem;
+ cores[i].rawLoadNice = _cpus[i].loadNice;
+ cores[i].rawLoadIdle = _cpus[i].loadIdle;
+ cores[i].rawLoadIrq = _cpus[i].loadIrq;
+ }
+ result = {
+ avgLoad: avgLoad,
+ currentLoad: _current_cpu.currentLoad,
+ currentLoadUser: _current_cpu.currentLoadUser,
+ currentLoadSystem: _current_cpu.currentLoadSystem,
+ currentLoadNice: _current_cpu.currentLoadNice,
+ currentLoadIdle: _current_cpu.currentLoadIdle,
+ currentLoadIrq: _current_cpu.currentLoadIrq,
+ rawCurrentLoad: _current_cpu.rawCurrentLoad,
+ rawCurrentLoadUser: _current_cpu.rawCurrentLoadUser,
+ rawCurrentLoadSystem: _current_cpu.rawCurrentLoadSystem,
+ rawCurrentLoadNice: _current_cpu.rawCurrentLoadNice,
+ rawCurrentLoadIdle: _current_cpu.rawCurrentLoadIdle,
+ rawCurrentLoadIrq: _current_cpu.rawCurrentLoadIrq,
+ cpus: cores
+ };
+ }
+ resolve(result);
+ });
+ });
+}
+
+function currentLoad(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ getLoad().then(result => {
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+ });
+}
+
+exports.currentLoad = currentLoad;
+
+// --------------------------
+// PS - full load
+// since bootup
+
+function getFullLoad() {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ const cpus = os.cpus();
+ let totalUser = 0;
+ let totalSystem = 0;
+ let totalNice = 0;
+ let totalIrq = 0;
+ let totalIdle = 0;
+
+ let result = 0;
+
+ if (cpus && cpus.length) {
+ for (let i = 0, len = cpus.length; i < len; i++) {
+ const cpu = cpus[i].times;
+ totalUser += cpu.user;
+ totalSystem += cpu.sys;
+ totalNice += cpu.nice;
+ totalIrq += cpu.irq;
+ totalIdle += cpu.idle;
+ }
+ let totalTicks = totalIdle + totalIrq + totalNice + totalSystem + totalUser;
+ result = (totalTicks - totalIdle) / totalTicks * 100.0;
+
+ }
+ resolve(result);
+ });
+ });
+}
+
+function fullLoad(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ getFullLoad().then(result => {
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+ });
+}
+
+exports.fullLoad = fullLoad;
diff --git a/MistyCore/node_modules/systeminformation/lib/docker.js b/MistyCore/node_modules/systeminformation/lib/docker.js
new file mode 100644
index 0000000..8125fc5
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/docker.js
@@ -0,0 +1,751 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// docker.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 13. Docker
+// ----------------------------------------------------------------------------------
+
+const util = require('./util');
+const DockerSocket = require('./dockerSocket');
+
+let _platform = process.platform;
+const _windows = (_platform === 'win32');
+
+let _docker_container_stats = {};
+let _docker_socket;
+let _docker_last_read = 0;
+
+
+// --------------------------
+// get containers (parameter all: get also inactive/exited containers)
+
+function dockerInfo(callback) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (!_docker_socket) {
+ _docker_socket = new DockerSocket();
+ }
+ const result = {};
+
+ _docker_socket.getInfo((data) => {
+ result.id = data.ID;
+ result.containers = data.Containers;
+ result.containersRunning = data.ContainersRunning;
+ result.containersPaused = data.ContainersPaused;
+ result.containersStopped = data.ContainersStopped;
+ result.images = data.Images;
+ result.driver = data.Driver;
+ result.memoryLimit = data.MemoryLimit;
+ result.swapLimit = data.SwapLimit;
+ result.kernelMemory = data.KernelMemory;
+ result.cpuCfsPeriod = data.CpuCfsPeriod;
+ result.cpuCfsQuota = data.CpuCfsQuota;
+ result.cpuShares = data.CPUShares;
+ result.cpuSet = data.CPUSet;
+ result.ipv4Forwarding = data.IPv4Forwarding;
+ result.bridgeNfIptables = data.BridgeNfIptables;
+ result.bridgeNfIp6tables = data.BridgeNfIp6tables;
+ result.debug = data.Debug;
+ result.nfd = data.NFd;
+ result.oomKillDisable = data.OomKillDisable;
+ result.ngoroutines = data.NGoroutines;
+ result.systemTime = data.SystemTime;
+ result.loggingDriver = data.LoggingDriver;
+ result.cgroupDriver = data.CgroupDriver;
+ result.nEventsListener = data.NEventsListener;
+ result.kernelVersion = data.KernelVersion;
+ result.operatingSystem = data.OperatingSystem;
+ result.osType = data.OSType;
+ result.architecture = data.Architecture;
+ result.ncpu = data.NCPU;
+ result.memTotal = data.MemTotal;
+ result.dockerRootDir = data.DockerRootDir;
+ result.httpProxy = data.HttpProxy;
+ result.httpsProxy = data.HttpsProxy;
+ result.noProxy = data.NoProxy;
+ result.name = data.Name;
+ result.labels = data.Labels;
+ result.experimentalBuild = data.ExperimentalBuild;
+ result.serverVersion = data.ServerVersion;
+ result.clusterStore = data.ClusterStore;
+ result.clusterAdvertise = data.ClusterAdvertise;
+ result.defaultRuntime = data.DefaultRuntime;
+ result.liveRestoreEnabled = data.LiveRestoreEnabled;
+ result.isolation = data.Isolation;
+ result.initBinary = data.InitBinary;
+ result.productLicense = data.ProductLicense;
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+ });
+}
+
+exports.dockerInfo = dockerInfo;
+
+function dockerImages(all, callback) {
+
+ // fallback - if only callback is given
+ if (util.isFunction(all) && !callback) {
+ callback = all;
+ all = false;
+ }
+ if (typeof all === 'string' && all === 'true') {
+ all = true;
+ }
+ if (typeof all !== 'boolean' && all !== undefined) {
+ all = false;
+ }
+
+ all = all || false;
+ let result = [];
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (!_docker_socket) {
+ _docker_socket = new DockerSocket();
+ }
+ const workload = [];
+
+ _docker_socket.listImages(all, data => {
+ let dockerImages = {};
+ try {
+ dockerImages = data;
+ if (dockerImages && Object.prototype.toString.call(dockerImages) === '[object Array]' && dockerImages.length > 0) {
+
+ dockerImages.forEach(function (element) {
+
+ if (element.Names && Object.prototype.toString.call(element.Names) === '[object Array]' && element.Names.length > 0) {
+ element.Name = element.Names[0].replace(/^\/|\/$/g, '');
+ }
+ workload.push(dockerImagesInspect(element.Id.trim(), element));
+ });
+ if (workload.length) {
+ Promise.all(
+ workload
+ ).then((data) => {
+ if (callback) { callback(data); }
+ resolve(data);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } catch (err) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ });
+ });
+}
+
+// --------------------------
+// container inspect (for one container)
+
+function dockerImagesInspect(imageID, payload) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ imageID = imageID || '';
+ if (typeof imageID !== 'string') {
+ return resolve();
+ }
+ const imageIDSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(imageID, true)).trim();
+ if (imageIDSanitized) {
+
+ if (!_docker_socket) {
+ _docker_socket = new DockerSocket();
+ }
+
+ _docker_socket.inspectImage(imageIDSanitized.trim(), data => {
+ try {
+ resolve({
+ id: payload.Id,
+ container: data.Container,
+ comment: data.Comment,
+ os: data.Os,
+ architecture: data.Architecture,
+ parent: data.Parent,
+ dockerVersion: data.DockerVersion,
+ size: data.Size,
+ sharedSize: payload.SharedSize,
+ virtualSize: data.VirtualSize,
+ author: data.Author,
+ created: data.Created ? Math.round(new Date(data.Created).getTime() / 1000) : 0,
+ containerConfig: data.ContainerConfig ? data.ContainerConfig : {},
+ graphDriver: data.GraphDriver ? data.GraphDriver : {},
+ repoDigests: data.RepoDigests ? data.RepoDigests : {},
+ repoTags: data.RepoTags ? data.RepoTags : {},
+ config: data.Config ? data.Config : {},
+ rootFS: data.RootFS ? data.RootFS : {},
+ });
+ } catch (err) {
+ resolve();
+ }
+ });
+ } else {
+ resolve();
+ }
+ });
+ });
+}
+
+exports.dockerImages = dockerImages;
+
+function dockerContainers(all, callback) {
+
+ function inContainers(containers, id) {
+ let filtered = containers.filter(obj => {
+ /**
+ * @namespace
+ * @property {string} Id
+ */
+ return (obj.Id && (obj.Id === id));
+ });
+ return (filtered.length > 0);
+ }
+
+ // fallback - if only callback is given
+ if (util.isFunction(all) && !callback) {
+ callback = all;
+ all = false;
+ }
+ if (typeof all === 'string' && all === 'true') {
+ all = true;
+ }
+ if (typeof all !== 'boolean' && all !== undefined) {
+ all = false;
+ }
+
+ all = all || false;
+ let result = [];
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (!_docker_socket) {
+ _docker_socket = new DockerSocket();
+ }
+ const workload = [];
+
+ _docker_socket.listContainers(all, data => {
+ let docker_containers = {};
+ try {
+ docker_containers = data;
+ if (docker_containers && Object.prototype.toString.call(docker_containers) === '[object Array]' && docker_containers.length > 0) {
+ // GC in _docker_container_stats
+ for (let key in _docker_container_stats) {
+ if ({}.hasOwnProperty.call(_docker_container_stats, key)) {
+ if (!inContainers(docker_containers, key)) { delete _docker_container_stats[key]; }
+ }
+ }
+
+ docker_containers.forEach(function (element) {
+
+ if (element.Names && Object.prototype.toString.call(element.Names) === '[object Array]' && element.Names.length > 0) {
+ element.Name = element.Names[0].replace(/^\/|\/$/g, '');
+ }
+ workload.push(dockerContainerInspect(element.Id.trim(), element));
+ });
+ if (workload.length) {
+ Promise.all(
+ workload
+ ).then((data) => {
+ if (callback) { callback(data); }
+ resolve(data);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } catch (err) {
+ // GC in _docker_container_stats
+ for (let key in _docker_container_stats) {
+ if ({}.hasOwnProperty.call(_docker_container_stats, key)) {
+ if (!inContainers(docker_containers, key)) { delete _docker_container_stats[key]; }
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ });
+ });
+}
+
+// --------------------------
+// container inspect (for one container)
+
+function dockerContainerInspect(containerID, payload) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ containerID = containerID || '';
+ if (typeof containerID !== 'string') {
+ return resolve();
+ }
+ const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
+ if (containerIdSanitized) {
+
+ if (!_docker_socket) {
+ _docker_socket = new DockerSocket();
+ }
+
+ _docker_socket.getInspect(containerIdSanitized.trim(), data => {
+ try {
+ resolve({
+ id: payload.Id,
+ name: payload.Name,
+ image: payload.Image,
+ imageID: payload.ImageID,
+ command: payload.Command,
+ created: payload.Created,
+ started: data.State && data.State.StartedAt ? Math.round(new Date(data.State.StartedAt).getTime() / 1000) : 0,
+ finished: data.State && data.State.FinishedAt && !data.State.FinishedAt.startsWith('0001-01-01') ? Math.round(new Date(data.State.FinishedAt).getTime() / 1000) : 0,
+ createdAt: data.Created ? data.Created : '',
+ startedAt: data.State && data.State.StartedAt ? data.State.StartedAt : '',
+ finishedAt: data.State && data.State.FinishedAt && !data.State.FinishedAt.startsWith('0001-01-01') ? data.State.FinishedAt : '',
+ state: payload.State,
+ restartCount: data.RestartCount || 0,
+ platform: data.Platform || '',
+ driver: data.Driver || '',
+ ports: payload.Ports,
+ mounts: payload.Mounts,
+ // hostconfig: payload.HostConfig,
+ // network: payload.NetworkSettings
+ });
+ } catch (err) {
+ resolve();
+ }
+ });
+ } else {
+ resolve();
+ }
+ });
+ });
+}
+
+exports.dockerContainers = dockerContainers;
+
+// --------------------------
+// helper functions for calculation of docker stats
+
+function docker_calcCPUPercent(cpu_stats, precpu_stats) {
+ /**
+ * @namespace
+ * @property {object} cpu_usage
+ * @property {number} cpu_usage.total_usage
+ * @property {number} system_cpu_usage
+ * @property {object} cpu_usage
+ * @property {Array} cpu_usage.percpu_usage
+ */
+
+ if (!_windows) {
+ let cpuPercent = 0.0;
+ // calculate the change for the cpu usage of the container in between readings
+ let cpuDelta = cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage;
+ // calculate the change for the entire system between readings
+ let systemDelta = cpu_stats.system_cpu_usage - precpu_stats.system_cpu_usage;
+
+ if (systemDelta > 0.0 && cpuDelta > 0.0) {
+ // calculate the change for the cpu usage of the container in between readings
+ cpuPercent = (cpuDelta / systemDelta) * cpu_stats.cpu_usage.percpu_usage.length * 100.0;
+ }
+
+ return cpuPercent;
+ } else {
+ let nanoSecNow = util.nanoSeconds();
+ let cpuPercent = 0.0;
+ if (_docker_last_read > 0) {
+ let possIntervals = (nanoSecNow - _docker_last_read); // / 100 * os.cpus().length;
+ let intervalsUsed = cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage;
+ if (possIntervals > 0) {
+ cpuPercent = 100.0 * intervalsUsed / possIntervals;
+ }
+ }
+ _docker_last_read = nanoSecNow;
+ return cpuPercent;
+ }
+}
+
+function docker_calcNetworkIO(networks) {
+ let rx;
+ let wx;
+ for (let key in networks) {
+ // skip loop if the property is from prototype
+ if (!{}.hasOwnProperty.call(networks, key)) { continue; }
+
+ /**
+ * @namespace
+ * @property {number} rx_bytes
+ * @property {number} tx_bytes
+ */
+ let obj = networks[key];
+ rx = +obj.rx_bytes;
+ wx = +obj.tx_bytes;
+ }
+ return {
+ rx,
+ wx
+ };
+}
+
+function docker_calcBlockIO(blkio_stats) {
+ let result = {
+ r: 0,
+ w: 0
+ };
+
+ /**
+ * @namespace
+ * @property {Array} io_service_bytes_recursive
+ */
+ if (blkio_stats && blkio_stats.io_service_bytes_recursive && Object.prototype.toString.call(blkio_stats.io_service_bytes_recursive) === '[object Array]' && blkio_stats.io_service_bytes_recursive.length > 0) {
+ blkio_stats.io_service_bytes_recursive.forEach(function (element) {
+ /**
+ * @namespace
+ * @property {string} op
+ * @property {number} value
+ */
+
+ if (element.op && element.op.toLowerCase() === 'read' && element.value) {
+ result.r += element.value;
+ }
+ if (element.op && element.op.toLowerCase() === 'write' && element.value) {
+ result.w += element.value;
+ }
+ });
+ }
+ return result;
+}
+
+function dockerContainerStats(containerIDs, callback) {
+
+ let containerArray = [];
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ // fallback - if only callback is given
+ if (util.isFunction(containerIDs) && !callback) {
+ callback = containerIDs;
+ containerArray = ['*'];
+ } else {
+ containerIDs = containerIDs || '*';
+ if (typeof containerIDs !== 'string') {
+ if (callback) { callback([]); }
+ return resolve([]);
+ }
+ let containerIDsSanitized = '';
+ containerIDsSanitized.__proto__.toLowerCase = util.stringToLower;
+ containerIDsSanitized.__proto__.replace = util.stringReplace;
+ containerIDsSanitized.__proto__.trim = util.stringTrim;
+
+ containerIDsSanitized = containerIDs;
+ containerIDsSanitized = containerIDsSanitized.trim();
+ if (containerIDsSanitized !== '*') {
+ containerIDsSanitized = '';
+ const s = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerIDs, true)).trim();
+ for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
+ if (!(s[i] === undefined)) {
+ s[i].__proto__.toLowerCase = util.stringToLower;
+ const sl = s[i].toLowerCase();
+ if (sl && sl[0] && !sl[1]) {
+ containerIDsSanitized = containerIDsSanitized + sl[0];
+ }
+ }
+ }
+ }
+
+ containerIDsSanitized = containerIDsSanitized.trim().toLowerCase().replace(/,+/g, '|');
+ containerArray = containerIDsSanitized.split('|');
+ }
+
+ const result = [];
+
+ const workload = [];
+ if (containerArray.length && containerArray[0].trim() === '*') {
+ containerArray = [];
+ dockerContainers().then(allContainers => {
+ for (let container of allContainers) {
+ containerArray.push(container.id);
+ }
+ if (containerArray.length) {
+ dockerContainerStats(containerArray.join(',')).then(result => {
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ } else {
+ for (let containerID of containerArray) {
+ workload.push(dockerContainerStatsSingle(containerID.trim()));
+ }
+ if (workload.length) {
+ Promise.all(
+ workload
+ ).then((data) => {
+ if (callback) { callback(data); }
+ resolve(data);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+// --------------------------
+// container stats (for one container)
+
+function dockerContainerStatsSingle(containerID) {
+ containerID = containerID || '';
+ let result = {
+ id: containerID,
+ memUsage: 0,
+ memLimit: 0,
+ memPercent: 0,
+ cpuPercent: 0,
+ pids: 0,
+ netIO: {
+ rx: 0,
+ wx: 0
+ },
+ blockIO: {
+ r: 0,
+ w: 0
+ },
+ restartCount: 0,
+ cpuStats: {},
+ precpuStats: {},
+ memoryStats: {},
+ networks: {},
+ };
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (containerID) {
+
+ if (!_docker_socket) {
+ _docker_socket = new DockerSocket();
+ }
+
+ _docker_socket.getInspect(containerID, dataInspect => {
+ try {
+ _docker_socket.getStats(containerID, data => {
+ try {
+ let stats = data;
+
+ if (!stats.message) {
+ result.memUsage = (stats.memory_stats && stats.memory_stats.usage ? stats.memory_stats.usage : 0);
+ result.memLimit = (stats.memory_stats && stats.memory_stats.limit ? stats.memory_stats.limit : 0);
+ result.memPercent = (stats.memory_stats && stats.memory_stats.usage && stats.memory_stats.limit ? stats.memory_stats.usage / stats.memory_stats.limit * 100.0 : 0);
+ result.cpuPercent = (stats.cpu_stats && stats.precpu_stats ? docker_calcCPUPercent(stats.cpu_stats, stats.precpu_stats) : 0);
+ result.pids = (stats.pids_stats && stats.pids_stats.current ? stats.pids_stats.current : 0);
+ result.restartCount = (dataInspect.RestartCount ? dataInspect.RestartCount : 0);
+ if (stats.networks) { result.netIO = docker_calcNetworkIO(stats.networks); }
+ if (stats.blkio_stats) { result.blockIO = docker_calcBlockIO(stats.blkio_stats); }
+ result.cpuStats = (stats.cpu_stats ? stats.cpu_stats : {});
+ result.precpuStats = (stats.precpu_stats ? stats.precpu_stats : {});
+ result.memoryStats = (stats.memory_stats ? stats.memory_stats : {});
+ result.networks = (stats.networks ? stats.networks : {});
+ }
+ } catch (err) {
+ util.noop();
+ }
+ // }
+ resolve(result);
+ });
+ } catch (err) {
+ util.noop();
+ }
+ });
+ } else {
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.dockerContainerStats = dockerContainerStats;
+
+// --------------------------
+// container processes (for one container)
+
+function dockerContainerProcesses(containerID, callback) {
+ let result = [];
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ containerID = containerID || '';
+ if (typeof containerID !== 'string') {
+ return resolve(result);
+ }
+ const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
+
+ if (containerIdSanitized) {
+
+ if (!_docker_socket) {
+ _docker_socket = new DockerSocket();
+ }
+
+ _docker_socket.getProcesses(containerIdSanitized, data => {
+ /**
+ * @namespace
+ * @property {Array} Titles
+ * @property {Array} Processes
+ **/
+ try {
+ if (data && data.Titles && data.Processes) {
+ let titles = data.Titles.map(function (value) {
+ return value.toUpperCase();
+ });
+ let pos_pid = titles.indexOf('PID');
+ let pos_ppid = titles.indexOf('PPID');
+ let pos_pgid = titles.indexOf('PGID');
+ let pos_vsz = titles.indexOf('VSZ');
+ let pos_time = titles.indexOf('TIME');
+ let pos_elapsed = titles.indexOf('ELAPSED');
+ let pos_ni = titles.indexOf('NI');
+ let pos_ruser = titles.indexOf('RUSER');
+ let pos_user = titles.indexOf('USER');
+ let pos_rgroup = titles.indexOf('RGROUP');
+ let pos_group = titles.indexOf('GROUP');
+ let pos_stat = titles.indexOf('STAT');
+ let pos_rss = titles.indexOf('RSS');
+ let pos_command = titles.indexOf('COMMAND');
+
+ data.Processes.forEach(process => {
+ result.push({
+ pidHost: (pos_pid >= 0 ? process[pos_pid] : ''),
+ ppid: (pos_ppid >= 0 ? process[pos_ppid] : ''),
+ pgid: (pos_pgid >= 0 ? process[pos_pgid] : ''),
+ user: (pos_user >= 0 ? process[pos_user] : ''),
+ ruser: (pos_ruser >= 0 ? process[pos_ruser] : ''),
+ group: (pos_group >= 0 ? process[pos_group] : ''),
+ rgroup: (pos_rgroup >= 0 ? process[pos_rgroup] : ''),
+ stat: (pos_stat >= 0 ? process[pos_stat] : ''),
+ time: (pos_time >= 0 ? process[pos_time] : ''),
+ elapsed: (pos_elapsed >= 0 ? process[pos_elapsed] : ''),
+ nice: (pos_ni >= 0 ? process[pos_ni] : ''),
+ rss: (pos_rss >= 0 ? process[pos_rss] : ''),
+ vsz: (pos_vsz >= 0 ? process[pos_vsz] : ''),
+ command: (pos_command >= 0 ? process[pos_command] : '')
+ });
+ });
+ }
+ } catch (err) {
+ util.noop();
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.dockerContainerProcesses = dockerContainerProcesses;
+
+function dockerVolumes(callback) {
+
+ let result = [];
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (!_docker_socket) {
+ _docker_socket = new DockerSocket();
+ }
+ _docker_socket.listVolumes((data) => {
+ let dockerVolumes = {};
+ try {
+ dockerVolumes = data;
+ if (dockerVolumes && dockerVolumes.Volumes && Object.prototype.toString.call(dockerVolumes.Volumes) === '[object Array]' && dockerVolumes.Volumes.length > 0) {
+
+ dockerVolumes.Volumes.forEach(function (element) {
+
+ result.push({
+ name: element.Name,
+ driver: element.Driver,
+ labels: element.Labels,
+ mountpoint: element.Mountpoint,
+ options: element.Options,
+ scope: element.Scope,
+ created: element.CreatedAt ? Math.round(new Date(element.CreatedAt).getTime() / 1000) : 0,
+ });
+ });
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } catch (err) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ });
+ });
+}
+
+exports.dockerVolumes = dockerVolumes;
+function dockerAll(callback) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ dockerContainers(true).then(result => {
+ if (result && Object.prototype.toString.call(result) === '[object Array]' && result.length > 0) {
+ let l = result.length;
+ result.forEach(function (element) {
+ dockerContainerStats(element.id).then((res) => {
+ // include stats in array
+ element.memUsage = res[0].memUsage;
+ element.memLimit = res[0].memLimit;
+ element.memPercent = res[0].memPercent;
+ element.cpuPercent = res[0].cpuPercent;
+ element.pids = res[0].pids;
+ element.netIO = res[0].netIO;
+ element.blockIO = res[0].blockIO;
+ element.cpuStats = res[0].cpuStats;
+ element.precpuStats = res[0].precpuStats;
+ element.memoryStats = res[0].memoryStats;
+ element.networks = res[0].networks;
+
+ dockerContainerProcesses(element.id).then(processes => {
+ element.processes = processes;
+
+ l -= 1;
+ if (l === 0) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ // all done??
+ });
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ });
+ });
+}
+
+exports.dockerAll = dockerAll;
diff --git a/MistyCore/node_modules/systeminformation/lib/dockerSocket.js b/MistyCore/node_modules/systeminformation/lib/dockerSocket.js
new file mode 100644
index 0000000..6508dd1
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/dockerSocket.js
@@ -0,0 +1,327 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// dockerSockets.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 13. DockerSockets
+// ----------------------------------------------------------------------------------
+
+const net = require('net');
+const isWin = require('os').type() === 'Windows_NT';
+const socketPath = isWin ? '//./pipe/docker_engine' : '/var/run/docker.sock';
+
+class DockerSocket {
+
+ getInfo(callback) {
+ try {
+
+ let socket = net.createConnection({ path: socketPath });
+ let alldata = '';
+ let data;
+
+ socket.on('connect', () => {
+ socket.write('GET http:/info HTTP/1.0\r\n\r\n');
+ });
+
+ socket.on('data', data => {
+ alldata = alldata + data.toString();
+ });
+
+ socket.on('error', () => {
+ socket = false;
+ callback({});
+ });
+
+ socket.on('end', () => {
+ let startbody = alldata.indexOf('\r\n\r\n');
+ alldata = alldata.substring(startbody + 4);
+ socket = false;
+ try {
+ data = JSON.parse(alldata);
+ callback(data);
+ } catch (err) {
+ callback({});
+ }
+ });
+ } catch (err) {
+ callback({});
+ }
+ }
+
+ listImages(all, callback) {
+ try {
+
+ let socket = net.createConnection({ path: socketPath });
+ let alldata = '';
+ let data;
+
+ socket.on('connect', () => {
+ socket.write('GET http:/images/json' + (all ? '?all=1' : '') + ' HTTP/1.0\r\n\r\n');
+ });
+
+ socket.on('data', data => {
+ alldata = alldata + data.toString();
+ });
+
+ socket.on('error', () => {
+ socket = false;
+ callback({});
+ });
+
+ socket.on('end', () => {
+ let startbody = alldata.indexOf('\r\n\r\n');
+ alldata = alldata.substring(startbody + 4);
+ socket = false;
+ try {
+ data = JSON.parse(alldata);
+ callback(data);
+ } catch (err) {
+ callback({});
+ }
+ });
+ } catch (err) {
+ callback({});
+ }
+ }
+
+ inspectImage(id, callback) {
+ id = id || '';
+ if (id) {
+ try {
+ let socket = net.createConnection({ path: socketPath });
+ let alldata = '';
+ let data;
+
+ socket.on('connect', () => {
+ socket.write('GET http:/images/' + id + '/json?stream=0 HTTP/1.0\r\n\r\n');
+ });
+
+ socket.on('data', data => {
+ alldata = alldata + data.toString();
+ });
+
+ socket.on('error', () => {
+ socket = false;
+ callback({});
+ });
+
+ socket.on('end', () => {
+ let startbody = alldata.indexOf('\r\n\r\n');
+ alldata = alldata.substring(startbody + 4);
+ socket = false;
+ try {
+ data = JSON.parse(alldata);
+ callback(data);
+ } catch (err) {
+ callback({});
+ }
+ });
+ } catch (err) {
+ callback({});
+ }
+ } else {
+ callback({});
+ }
+ }
+
+ listContainers(all, callback) {
+ try {
+
+ let socket = net.createConnection({ path: socketPath });
+ let alldata = '';
+ let data;
+
+ socket.on('connect', () => {
+ socket.write('GET http:/containers/json' + (all ? '?all=1' : '') + ' HTTP/1.0\r\n\r\n');
+ });
+
+ socket.on('data', data => {
+ alldata = alldata + data.toString();
+ });
+
+ socket.on('error', () => {
+ socket = false;
+ callback({});
+ });
+
+ socket.on('end', () => {
+ let startbody = alldata.indexOf('\r\n\r\n');
+ alldata = alldata.substring(startbody + 4);
+ socket = false;
+ try {
+ data = JSON.parse(alldata);
+ callback(data);
+ } catch (err) {
+ callback({});
+ }
+ });
+ } catch (err) {
+ callback({});
+ }
+ }
+
+ getStats(id, callback) {
+ id = id || '';
+ if (id) {
+ try {
+ let socket = net.createConnection({ path: socketPath });
+ let alldata = '';
+ let data;
+
+ socket.on('connect', () => {
+ socket.write('GET http:/containers/' + id + '/stats?stream=0 HTTP/1.0\r\n\r\n');
+ });
+
+ socket.on('data', data => {
+ alldata = alldata + data.toString();
+ });
+
+ socket.on('error', () => {
+ socket = false;
+ callback({});
+ });
+
+ socket.on('end', () => {
+ let startbody = alldata.indexOf('\r\n\r\n');
+ alldata = alldata.substring(startbody + 4);
+ socket = false;
+ try {
+ data = JSON.parse(alldata);
+ callback(data);
+ } catch (err) {
+ callback({});
+ }
+ });
+ } catch (err) {
+ callback({});
+ }
+ } else {
+ callback({});
+ }
+ }
+
+ getInspect(id, callback) {
+ id = id || '';
+ if (id) {
+ try {
+ let socket = net.createConnection({ path: socketPath });
+ let alldata = '';
+ let data;
+
+ socket.on('connect', () => {
+ socket.write('GET http:/containers/' + id + '/json?stream=0 HTTP/1.0\r\n\r\n');
+ });
+
+ socket.on('data', data => {
+ alldata = alldata + data.toString();
+ });
+
+ socket.on('error', () => {
+ socket = false;
+ callback({});
+ });
+
+ socket.on('end', () => {
+ let startbody = alldata.indexOf('\r\n\r\n');
+ alldata = alldata.substring(startbody + 4);
+ socket = false;
+ try {
+ data = JSON.parse(alldata);
+ callback(data);
+ } catch (err) {
+ callback({});
+ }
+ });
+ } catch (err) {
+ callback({});
+ }
+ } else {
+ callback({});
+ }
+ }
+
+ getProcesses(id, callback) {
+ id = id || '';
+ if (id) {
+ try {
+ let socket = net.createConnection({ path: socketPath });
+ let alldata = '';
+ let data;
+
+ socket.on('connect', () => {
+ socket.write('GET http:/containers/' + id + '/top?ps_args=-opid,ppid,pgid,vsz,time,etime,nice,ruser,user,rgroup,group,stat,rss,args HTTP/1.0\r\n\r\n');
+ });
+
+ socket.on('data', data => {
+ alldata = alldata + data.toString();
+ });
+
+ socket.on('error', () => {
+ socket = false;
+ callback({});
+ });
+
+ socket.on('end', () => {
+ let startbody = alldata.indexOf('\r\n\r\n');
+ alldata = alldata.substring(startbody + 4);
+ socket = false;
+ try {
+ data = JSON.parse(alldata);
+ callback(data);
+ } catch (err) {
+ callback({});
+ }
+ });
+ } catch (err) {
+ callback({});
+ }
+ } else {
+ callback({});
+ }
+ }
+
+ listVolumes(callback) {
+ try {
+
+ let socket = net.createConnection({ path: socketPath });
+ let alldata = '';
+ let data;
+
+ socket.on('connect', () => {
+ socket.write('GET http:/volumes HTTP/1.0\r\n\r\n');
+ });
+
+ socket.on('data', data => {
+ alldata = alldata + data.toString();
+ });
+
+ socket.on('error', () => {
+ socket = false;
+ callback({});
+ });
+
+ socket.on('end', () => {
+ let startbody = alldata.indexOf('\r\n\r\n');
+ alldata = alldata.substring(startbody + 4);
+ socket = false;
+ try {
+ data = JSON.parse(alldata);
+ callback(data);
+ } catch (err) {
+ callback({});
+ }
+ });
+ } catch (err) {
+ callback({});
+ }
+ }
+}
+
+module.exports = DockerSocket;
diff --git a/MistyCore/node_modules/systeminformation/lib/filesystem.js b/MistyCore/node_modules/systeminformation/lib/filesystem.js
new file mode 100644
index 0000000..419caa1
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/filesystem.js
@@ -0,0 +1,1301 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// filesystem.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 8. File System
+// ----------------------------------------------------------------------------------
+
+const util = require('./util');
+const fs = require('fs');
+
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const execPromiseSave = util.promisifySave(require('child_process').exec);
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+let _fs_speed = {};
+let _disk_io = {};
+
+// --------------------------
+// FS - mounted file systems
+
+function fsSize(callback) {
+
+ let macOsDisks = [];
+
+ function getmacOsFsType(fs) {
+ if (!fs.startsWith('/')) { return 'NFS'; }
+ const parts = fs.split('/');
+ const fsShort = parts[parts.length - 1];
+ const macOsDisksSingle = macOsDisks.filter(item => item.indexOf(fsShort) >= 0);
+ if (macOsDisksSingle.length === 1 && macOsDisksSingle[0].indexOf('APFS') >= 0) { return 'APFS'; }
+ return 'HFS';
+ }
+
+ function isLinuxTmpFs(fs) {
+ const linuxTmpFileSystems = ['rootfs', 'unionfs', 'squashfs', 'cramfs', 'initrd', 'initramfs', 'devtmpfs', 'tmpfs', 'udev', 'devfs', 'specfs', 'type', 'appimaged'];
+ let result = false;
+ linuxTmpFileSystems.forEach(linuxFs => {
+ if (fs.toLowerCase().indexOf(linuxFs) >= 0) { result = true; }
+ });
+ return result;
+ }
+
+ function filterLines(stdout) {
+ let lines = stdout.toString().split('\n');
+ if (stdout.toString().toLowerCase().indexOf('filesystem')) {
+ let removeLines = 0;
+ for (let i = 0; i < lines.length; i++) {
+ if (lines[i] && lines[i].toLowerCase().startsWith('filesystem')) {
+ removeLines = i;
+ }
+ }
+ for (let i = 0; i < removeLines; i++) {
+ lines.shift();
+ }
+ }
+ return lines;
+ }
+
+ function parseDf(lines) {
+ let data = [];
+ lines.forEach(function (line) {
+ if (line !== '') {
+ line = line.replace(/ +/g, ' ').split(' ');
+ if (line && ((line[0].startsWith('/')) || (line[6] && line[6] === '/') || (line[0].indexOf('/') > 0) || (line[0].indexOf(':') === 1) || !_darwin && !isLinuxTmpFs(line[1]))) {
+ const fs = line[0];
+ const fsType = ((_linux || _freebsd || _openbsd || _netbsd) ? line[1] : getmacOsFsType(line[0]));
+ const size = parseInt(((_linux || _freebsd || _openbsd || _netbsd) ? line[2] : line[1])) * 1024;
+ const used = parseInt(((_linux || _freebsd || _openbsd || _netbsd) ? line[3] : line[2])) * 1024;
+ const available = parseInt(((_linux || _freebsd || _openbsd || _netbsd) ? line[4] : line[3])) * 1024;
+ const use = parseFloat((100.0 * (used / (used + available))).toFixed(2));
+ line.splice(0, (_linux || _freebsd || _openbsd || _netbsd) ? 6 : 5);
+ const mount = line.join(' ');
+ // const mount = line[line.length - 1];
+ if (!data.find(el => (el.fs === fs && el.type === fsType))) {
+ data.push({
+ fs,
+ type: fsType,
+ size,
+ used,
+ available,
+ use,
+ mount
+ });
+ }
+ }
+ }
+ });
+ return data;
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let data = [];
+ if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
+ let cmd = '';
+ if (_darwin) {
+ cmd = 'df -kP';
+ try {
+ macOsDisks = execSync('diskutil list').toString().split('\n').filter(line => {
+ return !line.startsWith('/') && line.indexOf(':') > 0;
+ });
+ } catch (e) {
+ macOsDisks = [];
+ }
+ }
+ if (_linux) { cmd = 'df -lkPTx squashfs'; } // cmd = 'df -lkPTx squashfs | grep -E "^/|^.\\:"';
+ if (_freebsd || _openbsd || _netbsd) { cmd = 'df -lkPT'; }
+ exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ let lines = filterLines(stdout);
+ data = parseDf(lines);
+ if (!error || data.length) {
+ if (callback) {
+ callback(data);
+ }
+ resolve(data);
+ } else {
+ exec('df -kPT', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = filterLines(stdout);
+ data = parseDf(lines);
+ }
+ if (callback) {
+ callback(data);
+ }
+ resolve(data);
+ });
+ }
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(data); }
+ resolve(data);
+ }
+ if (_windows) {
+ try {
+ // util.wmic('logicaldisk get Caption,FileSystem,FreeSpace,Size').then((stdout) => {
+ util.powerShell('Get-WmiObject Win32_logicaldisk | select Caption,FileSystem,FreeSpace,Size | fl').then((stdout, error) => {
+ if (!error) {
+ let devices = stdout.toString().split(/\n\s*\n/);
+ devices.forEach(function (device) {
+ let lines = device.split('\r\n');
+ const size = util.toInt(util.getValue(lines, 'size', ':'));
+ const free = util.toInt(util.getValue(lines, 'freespace', ':'));
+ const caption = util.getValue(lines, 'caption', ':');
+ if (size) {
+ data.push({
+ fs: caption,
+ type: util.getValue(lines, 'filesystem', ':'),
+ size,
+ used: size - free,
+ available: free,
+ use: parseFloat(((100.0 * (size - free)) / size).toFixed(2)),
+ mount: caption
+ });
+ }
+ });
+ }
+ if (callback) {
+ callback(data);
+ }
+ resolve(data);
+ });
+ } catch (e) {
+ if (callback) { callback(data); }
+ resolve(data);
+ }
+ }
+ });
+ });
+}
+
+exports.fsSize = fsSize;
+
+// --------------------------
+// FS - open files count
+
+function fsOpenFiles(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ const result = {
+ max: null,
+ allocated: null,
+ available: null
+ };
+ if (_freebsd || _openbsd || _netbsd || _darwin) {
+ let cmd = 'sysctl -i kern.maxfiles kern.num_files kern.open_files';
+ exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.max = parseInt(util.getValue(lines, 'kern.maxfiles', ':'), 10);
+ result.allocated = parseInt(util.getValue(lines, 'kern.num_files', ':'), 10) || parseInt(util.getValue(lines, 'kern.open_files', ':'), 10);
+ result.available = result.max - result.allocated;
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_linux) {
+ fs.readFile('/proc/sys/fs/file-nr', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ if (lines[0]) {
+ const parts = lines[0].replace(/\s+/g, ' ').split(' ');
+ if (parts.length === 3) {
+ result.allocated = parseInt(parts[0], 10);
+ result.available = parseInt(parts[1], 10);
+ result.max = parseInt(parts[2], 10);
+ if (!result.available) { result.available = result.max - result.allocated; }
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else {
+ fs.readFile('/proc/sys/fs/file-max', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ if (lines[0]) {
+ result.max = parseInt(lines[0], 10);
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(null); }
+ resolve(null);
+ }
+ if (_windows) {
+ if (callback) { callback(null); }
+ resolve(null);
+ }
+ });
+ });
+}
+
+exports.fsOpenFiles = fsOpenFiles;
+
+// --------------------------
+// disks
+
+function parseBytes(s) {
+ return parseInt(s.substr(s.indexOf(' (') + 2, s.indexOf(' Bytes)') - 10));
+}
+
+function parseDevices(lines) {
+ let devices = [];
+ let i = 0;
+ lines.forEach(line => {
+ if (line.length > 0) {
+ if (line[0] === '*') {
+ i++;
+ } else {
+ let parts = line.split(':');
+ if (parts.length > 1) {
+ if (!devices[i]) {
+ devices[i] = {
+ name: '',
+ identifier: '',
+ type: 'disk',
+ fsType: '',
+ mount: '',
+ size: 0,
+ physical: 'HDD',
+ uuid: '',
+ label: '',
+ model: '',
+ serial: '',
+ removable: false,
+ protocol: ''
+ };
+ }
+ parts[0] = parts[0].trim().toUpperCase().replace(/ +/g, '');
+ parts[1] = parts[1].trim();
+ if ('DEVICEIDENTIFIER' === parts[0]) { devices[i].identifier = parts[1]; }
+ if ('DEVICENODE' === parts[0]) { devices[i].name = parts[1]; }
+ if ('VOLUMENAME' === parts[0]) {
+ if (parts[1].indexOf('Not applicable') === -1) { devices[i].label = parts[1]; }
+ }
+ if ('PROTOCOL' === parts[0]) { devices[i].protocol = parts[1]; }
+ if ('DISKSIZE' === parts[0]) { devices[i].size = parseBytes(parts[1]); }
+ if ('FILESYSTEMPERSONALITY' === parts[0]) { devices[i].fsType = parts[1]; }
+ if ('MOUNTPOINT' === parts[0]) { devices[i].mount = parts[1]; }
+ if ('VOLUMEUUID' === parts[0]) { devices[i].uuid = parts[1]; }
+ if ('READ-ONLYMEDIA' === parts[0] && parts[1] === 'Yes') { devices[i].physical = 'CD/DVD'; }
+ if ('SOLIDSTATE' === parts[0] && parts[1] === 'Yes') { devices[i].physical = 'SSD'; }
+ if ('VIRTUAL' === parts[0]) { devices[i].type = 'virtual'; }
+ if ('REMOVABLEMEDIA' === parts[0]) { devices[i].removable = (parts[1] === 'Removable'); }
+ if ('PARTITIONTYPE' === parts[0]) { devices[i].type = 'part'; }
+ if ('DEVICE/MEDIANAME' === parts[0]) { devices[i].model = parts[1]; }
+ }
+ }
+ }
+ });
+ return devices;
+}
+
+function parseBlk(lines) {
+ let data = [];
+
+ lines.filter(line => line !== '').forEach((line) => {
+ try {
+ line = decodeURIComponent(line.replace(/\\x/g, '%'));
+ line = line.replace(/\\/g, '\\\\');
+ let disk = JSON.parse(line);
+ data.push({
+ 'name': disk.name,
+ 'type': disk.type,
+ 'fsType': disk.fsType,
+ 'mount': disk.mountpoint,
+ 'size': parseInt(disk.size),
+ 'physical': (disk.type === 'disk' ? (disk.rota === '0' ? 'SSD' : 'HDD') : (disk.type === 'rom' ? 'CD/DVD' : '')),
+ 'uuid': disk.uuid,
+ 'label': disk.label,
+ 'model': disk.model,
+ 'serial': disk.serial,
+ 'removable': disk.rm === '1',
+ 'protocol': disk.tran,
+ 'group': disk.group,
+ });
+ } catch (e) {
+ util.noop();
+ }
+ });
+ data = util.unique(data);
+ data = util.sortByKey(data, ['type', 'name']);
+ return data;
+}
+
+function blkStdoutToObject(stdout) {
+ return stdout.toString()
+ .replace(/NAME=/g, '{"name":')
+ .replace(/FSTYPE=/g, ',"fsType":')
+ .replace(/TYPE=/g, ',"type":')
+ .replace(/SIZE=/g, ',"size":')
+ .replace(/MOUNTPOINT=/g, ',"mountpoint":')
+ .replace(/UUID=/g, ',"uuid":')
+ .replace(/ROTA=/g, ',"rota":')
+ .replace(/RO=/g, ',"ro":')
+ .replace(/RM=/g, ',"rm":')
+ .replace(/TRAN=/g, ',"tran":')
+ .replace(/SERIAL=/g, ',"serial":')
+ .replace(/LABEL=/g, ',"label":')
+ .replace(/MODEL=/g, ',"model":')
+ .replace(/OWNER=/g, ',"owner":')
+ .replace(/GROUP=/g, ',"group":')
+ .replace(/\n/g, '}\n');
+}
+
+function blockDevices(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let data = [];
+ if (_linux) {
+ // see https://wiki.ubuntuusers.de/lsblk/
+ // exec("lsblk -bo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,TRAN,SERIAL,LABEL,MODEL,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,SCHED,RQ-SIZE,RA,WSAME", function (error, stdout) {
+ exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,TRAN,SERIAL,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = blkStdoutToObject(stdout).split('\n');
+ data = parseBlk(lines);
+ if (callback) {
+ callback(data);
+ }
+ resolve(data);
+ } else {
+ exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = blkStdoutToObject(stdout).split('\n');
+ data = parseBlk(lines);
+ }
+ if (callback) {
+ callback(data);
+ }
+ resolve(data);
+ });
+ }
+ });
+ }
+ if (_darwin) {
+ exec('diskutil info -all', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ // parse lines into temp array of devices
+ data = parseDevices(lines);
+ }
+ if (callback) {
+ callback(data);
+ }
+ resolve(data);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(data); }
+ resolve(data);
+ }
+ if (_windows) {
+ let drivetypes = ['Unknown', 'NoRoot', 'Removable', 'Local', 'Network', 'CD/DVD', 'RAM'];
+ try {
+ // util.wmic('logicaldisk get Caption,Description,DeviceID,DriveType,FileSystem,FreeSpace,Name,Size,VolumeName,VolumeSerialNumber /value').then((stdout, error) => {
+ // util.powerShell('Get-WmiObject Win32_logicaldisk | select Caption,DriveType,Name,FileSystem,Size,VolumeSerialNumber,VolumeName | fl').then((stdout, error) => {
+ util.powerShell('Get-CimInstance -ClassName Win32_LogicalDisk | select Caption,DriveType,Name,FileSystem,Size,VolumeSerialNumber,VolumeName | fl').then((stdout, error) => {
+ if (!error) {
+ let devices = stdout.toString().split(/\n\s*\n/);
+ devices.forEach(function (device) {
+ let lines = device.split('\r\n');
+ let drivetype = util.getValue(lines, 'drivetype', ':');
+ if (drivetype) {
+ data.push({
+ name: util.getValue(lines, 'name', ':'),
+ identifier: util.getValue(lines, 'caption', ':'),
+ type: 'disk',
+ fsType: util.getValue(lines, 'filesystem', ':').toLowerCase(),
+ mount: util.getValue(lines, 'caption', ':'),
+ size: util.getValue(lines, 'size', ':'),
+ physical: (drivetype >= 0 && drivetype <= 6) ? drivetypes[drivetype] : drivetypes[0],
+ uuid: util.getValue(lines, 'volumeserialnumber', ':'),
+ label: util.getValue(lines, 'volumename', ':'),
+ model: '',
+ serial: util.getValue(lines, 'volumeserialnumber', ':'),
+ removable: drivetype === '2',
+ protocol: ''
+ });
+ }
+ });
+ }
+ if (callback) {
+ callback(data);
+ }
+ resolve(data);
+ });
+ } catch (e) {
+ if (callback) { callback(data); }
+ resolve(data);
+ }
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ // will follow
+ if (callback) { callback(null); }
+ resolve(null);
+ }
+
+ });
+ });
+}
+
+exports.blockDevices = blockDevices;
+
+// --------------------------
+// FS - speed
+
+function calcFsSpeed(rx, wx) {
+ let result = {
+ rx: 0,
+ wx: 0,
+ tx: 0,
+ rx_sec: null,
+ wx_sec: null,
+ tx_sec: null,
+ ms: 0
+ };
+
+ if (_fs_speed && _fs_speed.ms) {
+ result.rx = rx;
+ result.wx = wx;
+ result.tx = result.rx + result.wx;
+ result.ms = Date.now() - _fs_speed.ms;
+ result.rx_sec = (result.rx - _fs_speed.bytes_read) / (result.ms / 1000);
+ result.wx_sec = (result.wx - _fs_speed.bytes_write) / (result.ms / 1000);
+ result.tx_sec = result.rx_sec + result.wx_sec;
+ _fs_speed.rx_sec = result.rx_sec;
+ _fs_speed.wx_sec = result.wx_sec;
+ _fs_speed.tx_sec = result.tx_sec;
+ _fs_speed.bytes_read = result.rx;
+ _fs_speed.bytes_write = result.wx;
+ _fs_speed.bytes_overall = result.rx + result.wx;
+ _fs_speed.ms = Date.now();
+ _fs_speed.last_ms = result.ms;
+ } else {
+ result.rx = rx;
+ result.wx = wx;
+ result.tx = result.rx + result.wx;
+ _fs_speed.rx_sec = null;
+ _fs_speed.wx_sec = null;
+ _fs_speed.tx_sec = null;
+ _fs_speed.bytes_read = result.rx;
+ _fs_speed.bytes_write = result.wx;
+ _fs_speed.bytes_overall = result.rx + result.wx;
+ _fs_speed.ms = Date.now();
+ _fs_speed.last_ms = 0;
+ }
+ return result;
+}
+
+function fsStats(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (_windows || _freebsd || _openbsd || _netbsd || _sunos) {
+ return resolve(null);
+ }
+
+ let result = {
+ rx: 0,
+ wx: 0,
+ tx: 0,
+ rx_sec: null,
+ wx_sec: null,
+ tx_sec: null,
+ ms: 0
+ };
+
+ let rx = 0;
+ let wx = 0;
+ if ((_fs_speed && !_fs_speed.ms) || (_fs_speed && _fs_speed.ms && Date.now() - _fs_speed.ms >= 500)) {
+ if (_linux) {
+ // exec("df -k | grep /dev/", function(error, stdout) {
+ exec('lsblk -r 2>/dev/null | grep /', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ let fs_filter = [];
+ lines.forEach(function (line) {
+ if (line !== '') {
+ line = line.trim().split(' ');
+ if (fs_filter.indexOf(line[0]) === -1) { fs_filter.push(line[0]); }
+ }
+ });
+
+ let output = fs_filter.join('|');
+ exec('cat /proc/diskstats | egrep "' + output + '"', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.trim();
+ if (line !== '') {
+ line = line.replace(/ +/g, ' ').split(' ');
+
+ rx += parseInt(line[5]) * 512;
+ wx += parseInt(line[9]) * 512;
+ }
+ });
+ result = calcFsSpeed(rx, wx);
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ }
+ if (_darwin) {
+ exec('ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n "/IOBlockStorageDriver/,/Statistics/p" | grep "Statistics" | tr -cd "01234567890,\n"', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.trim();
+ if (line !== '') {
+ line = line.split(',');
+
+ rx += parseInt(line[2]);
+ wx += parseInt(line[9]);
+ }
+ });
+ result = calcFsSpeed(rx, wx);
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ } else {
+ result.ms = _fs_speed.last_ms;
+ result.rx = _fs_speed.bytes_read;
+ result.wx = _fs_speed.bytes_write;
+ result.tx = _fs_speed.bytes_read + _fs_speed.bytes_write;
+ result.rx_sec = _fs_speed.rx_sec;
+ result.wx_sec = _fs_speed.wx_sec;
+ result.tx_sec = _fs_speed.tx_sec;
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.fsStats = fsStats;
+
+function calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime) {
+ let result = {
+ rIO: 0,
+ wIO: 0,
+ tIO: 0,
+ rIO_sec: null,
+ wIO_sec: null,
+ tIO_sec: null,
+ rWaitTime: 0,
+ wWaitTime: 0,
+ tWaitTime: 0,
+ rWaitPercent: null,
+ wWaitPercent: null,
+ tWaitPercent: null,
+ ms: 0
+ };
+ if (_disk_io && _disk_io.ms) {
+ result.rIO = rIO;
+ result.wIO = wIO;
+ result.tIO = rIO + wIO;
+ result.ms = Date.now() - _disk_io.ms;
+ result.rIO_sec = (result.rIO - _disk_io.rIO) / (result.ms / 1000);
+ result.wIO_sec = (result.wIO - _disk_io.wIO) / (result.ms / 1000);
+ result.tIO_sec = result.rIO_sec + result.wIO_sec;
+ result.rWaitTime = rWaitTime;
+ result.wWaitTime = wWaitTime;
+ result.tWaitTime = tWaitTime;
+ result.rWaitPercent = (result.rWaitTime - _disk_io.rWaitTime) * 100 / (result.ms);
+ result.wWaitPercent = (result.wWaitTime - _disk_io.wWaitTime) * 100 / (result.ms);
+ result.tWaitPercent = (result.tWaitTime - _disk_io.tWaitTime) * 100 / (result.ms);
+ _disk_io.rIO = rIO;
+ _disk_io.wIO = wIO;
+ _disk_io.rIO_sec = result.rIO_sec;
+ _disk_io.wIO_sec = result.wIO_sec;
+ _disk_io.tIO_sec = result.tIO_sec;
+ _disk_io.rWaitTime = rWaitTime;
+ _disk_io.wWaitTime = wWaitTime;
+ _disk_io.tWaitTime = tWaitTime;
+ _disk_io.rWaitPercent = result.rWaitPercent;
+ _disk_io.wWaitPercent = result.wWaitPercent;
+ _disk_io.tWaitPercent = result.tWaitPercent;
+ _disk_io.last_ms = result.ms;
+ _disk_io.ms = Date.now();
+ } else {
+ result.rIO = rIO;
+ result.wIO = wIO;
+ result.tIO = rIO + wIO;
+ result.rWaitTime = rWaitTime;
+ result.wWaitTime = wWaitTime;
+ result.tWaitTime = tWaitTime;
+ _disk_io.rIO = rIO;
+ _disk_io.wIO = wIO;
+ _disk_io.rIO_sec = null;
+ _disk_io.wIO_sec = null;
+ _disk_io.tIO_sec = null;
+ _disk_io.rWaitTime = rWaitTime;
+ _disk_io.wWaitTime = wWaitTime;
+ _disk_io.tWaitTime = tWaitTime;
+ _disk_io.rWaitPercent = null;
+ _disk_io.wWaitPercent = null;
+ _disk_io.tWaitPercent = null;
+ _disk_io.last_ms = 0;
+ _disk_io.ms = Date.now();
+ }
+ return result;
+}
+
+function disksIO(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (_windows) {
+ return resolve(null);
+ }
+ if (_sunos) {
+ return resolve(null);
+ }
+
+ let result = {
+ rIO: 0,
+ wIO: 0,
+ tIO: 0,
+ rIO_sec: null,
+ wIO_sec: null,
+ tIO_sec: null,
+ rWaitTime: 0,
+ wWaitTime: 0,
+ tWaitTime: 0,
+ rWaitPercent: null,
+ wWaitPercent: null,
+ tWaitPercent: null,
+ ms: 0
+ };
+ let rIO = 0;
+ let wIO = 0;
+ let rWaitTime = 0;
+ let wWaitTime = 0;
+ let tWaitTime = 0;
+
+ if ((_disk_io && !_disk_io.ms) || (_disk_io && _disk_io.ms && Date.now() - _disk_io.ms >= 500)) {
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ // prints Block layer statistics for all mounted volumes
+ // var cmd = "for mount in `lsblk | grep / | sed -r 's/│ └─//' | cut -d ' ' -f 1`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done";
+ // var cmd = "for mount in `lsblk | grep / | sed 's/[│└─├]//g' | awk '{$1=$1};1' | cut -d ' ' -f 1 | sort -u`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done";
+ let cmd = 'for mount in `lsblk 2>/dev/null | grep " disk " | sed "s/[│└─├]//g" | awk \'{$1=$1};1\' | cut -d " " -f 1 | sort -u`; do cat /sys/block/$mount/stat | sed -r "s/ +/;/g" | sed -r "s/^;//"; done';
+
+ exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.split('\n');
+ lines.forEach(function (line) {
+ // ignore empty lines
+ if (!line) { return; }
+
+ // sum r/wIO of all disks to compute all disks IO
+ let stats = line.split(';');
+ rIO += parseInt(stats[0]);
+ wIO += parseInt(stats[4]);
+ rWaitTime += parseInt(stats[3]);
+ wWaitTime += parseInt(stats[7]);
+ tWaitTime += parseInt(stats[10]);
+ });
+ result = calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime);
+
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ }
+ if (_darwin) {
+ exec('ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n "/IOBlockStorageDriver/,/Statistics/p" | grep "Statistics" | tr -cd "01234567890,\n"', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.trim();
+ if (line !== '') {
+ line = line.split(',');
+
+ rIO += parseInt(line[10]);
+ wIO += parseInt(line[0]);
+ }
+ });
+ result = calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime);
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ } else {
+ result.rIO = _disk_io.rIO;
+ result.wIO = _disk_io.wIO;
+ result.tIO = _disk_io.rIO + _disk_io.wIO;
+ result.ms = _disk_io.last_ms;
+ result.rIO_sec = _disk_io.rIO_sec;
+ result.wIO_sec = _disk_io.wIO_sec;
+ result.tIO_sec = _disk_io.tIO_sec;
+ result.rWaitTime = _disk_io.rWaitTime;
+ result.wWaitTime = _disk_io.wWaitTime;
+ result.tWaitTime = _disk_io.tWaitTime;
+ result.rWaitPercent = _disk_io.rWaitPercent;
+ result.wWaitPercent = _disk_io.wWaitPercent;
+ result.tWaitPercent = _disk_io.tWaitPercent;
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.disksIO = disksIO;
+
+function diskLayout(callback) {
+
+ function getVendorFromModel(model) {
+ const diskManufacturers = [
+ { pattern: 'WESTERN.*', manufacturer: 'Western Digital' },
+ { pattern: '^WDC.*', manufacturer: 'Western Digital' },
+ { pattern: 'WD.*', manufacturer: 'Western Digital' },
+ { pattern: 'TOSHIBA.*', manufacturer: 'Toshiba' },
+ { pattern: 'HITACHI.*', manufacturer: 'Hitachi' },
+ { pattern: '^IC.*', manufacturer: 'Hitachi' },
+ { pattern: '^HTS.*', manufacturer: 'Hitachi' },
+ { pattern: 'SANDISK.*', manufacturer: 'SanDisk' },
+ { pattern: 'KINGSTON.*', manufacturer: 'Kingston Technology' },
+ { pattern: '^SONY.*', manufacturer: 'Sony' },
+ { pattern: 'TRANSCEND.*', manufacturer: 'Transcend' },
+ { pattern: 'SAMSUNG.*', manufacturer: 'Samsung' },
+ { pattern: '^ST(?!I\\ ).*', manufacturer: 'Seagate' },
+ { pattern: '^STI\\ .*', manufacturer: 'SimpleTech' },
+ { pattern: '^D...-.*', manufacturer: 'IBM' },
+ { pattern: '^IBM.*', manufacturer: 'IBM' },
+ { pattern: '^FUJITSU.*', manufacturer: 'Fujitsu' },
+ { pattern: '^MP.*', manufacturer: 'Fujitsu' },
+ { pattern: '^MK.*', manufacturer: 'Toshiba' },
+ { pattern: 'MAXTO.*', manufacturer: 'Maxtor' },
+ { pattern: 'PIONEER.*', manufacturer: 'Pioneer' },
+ { pattern: 'PHILIPS.*', manufacturer: 'Philips' },
+ { pattern: 'QUANTUM.*', manufacturer: 'Quantum Technology' },
+ { pattern: 'FIREBALL.*', manufacturer: 'Quantum Technology' },
+ { pattern: '^VBOX.*', manufacturer: 'VirtualBox' },
+ { pattern: 'CORSAIR.*', manufacturer: 'Corsair Components' },
+ { pattern: 'CRUCIAL.*', manufacturer: 'Crucial' },
+ { pattern: 'ECM.*', manufacturer: 'ECM' },
+ { pattern: 'INTEL.*', manufacturer: 'INTEL' },
+ { pattern: 'EVO.*', manufacturer: 'Samsung' },
+ { pattern: 'APPLE.*', manufacturer: 'Apple' },
+ ];
+
+ let result = '';
+ if (model) {
+ model = model.toUpperCase();
+ diskManufacturers.forEach((manufacturer) => {
+ const re = RegExp(manufacturer.pattern);
+ if (re.test(model)) { result = manufacturer.manufacturer; }
+ });
+ }
+ return result;
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ const commitResult = res => {
+ for (let i = 0; i < res.length; i++) {
+ delete res[i].BSDName;
+ }
+ if (callback) {
+ callback(res);
+ }
+ resolve(res);
+ };
+
+ let result = [];
+ let cmd = '';
+
+ if (_linux) {
+ let cmdFullSmart = '';
+
+ exec('export LC_ALL=C; lsblk -ablJO 2>/dev/null; unset LC_ALL', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ try {
+ const out = stdout.toString().trim();
+ let devices = [];
+ try {
+ const outJSON = JSON.parse(out);
+ if (outJSON && {}.hasOwnProperty.call(outJSON, 'blockdevices')) {
+ devices = outJSON.blockdevices.filter(item => { return (item.type === 'disk') && item.size > 0 && (item.model !== null || (item.mountpoint === null && item.label === null && item.fstype === null && item.parttype === null && item.path && item.path.indexOf('/ram') !== 0 && item.path.indexOf('/loop') !== 0 && item['disc-max'] && item['disc-max'] !== 0)); });
+ }
+ } catch (e) {
+ // fallback to older version of lsblk
+ const out2 = execSync('export LC_ALL=C; lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER,GROUP 2>/dev/null; unset LC_ALL').toString();
+ let lines = blkStdoutToObject(out2).split('\n');
+ const data = parseBlk(lines);
+ devices = data.filter(item => { return (item.type === 'disk') && item.size > 0 && ((item.model !== null && item.model !== '') || (item.mount === '' && item.label === '' && item.fsType === '')); });
+ }
+ devices.forEach((device) => {
+ let mediumType = '';
+ const BSDName = '/dev/' + device.name;
+ const logical = device.name;
+ try {
+ mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational 2>/dev/null').toString().split('\n')[0];
+ } catch (e) {
+ util.noop();
+ }
+ let interfaceType = device.tran ? device.tran.toUpperCase().trim() : '';
+ if (interfaceType === 'NVME') {
+ mediumType = '2';
+ interfaceType = 'PCIe';
+ }
+ result.push({
+ device: BSDName,
+ type: (mediumType === '0' ? 'SSD' : (mediumType === '1' ? 'HD' : (mediumType === '2' ? 'NVMe' : (device.model && device.model.indexOf('SSD') > -1 ? 'SSD' : (device.model && device.model.indexOf('NVM') > -1 ? 'NVMe' : 'HD'))))),
+ name: device.model || '',
+ vendor: getVendorFromModel(device.model) || (device.vendor ? device.vendor.trim() : ''),
+ size: device.size || 0,
+ bytesPerSector: null,
+ totalCylinders: null,
+ totalHeads: null,
+ totalSectors: null,
+ totalTracks: null,
+ tracksPerCylinder: null,
+ sectorsPerTrack: null,
+ firmwareRevision: device.rev ? device.rev.trim() : '',
+ serialNum: device.serial ? device.serial.trim() : '',
+ interfaceType: interfaceType,
+ smartStatus: 'unknown',
+ temperature: null,
+ BSDName: BSDName
+ });
+ cmd += `printf "\n${BSDName}|"; smartctl -H ${BSDName} | grep overall;`;
+ cmdFullSmart += `${cmdFullSmart ? 'printf ",";' : ''}smartctl -a -j ${BSDName};`;
+ });
+ } catch (e) {
+ util.noop();
+ }
+ }
+ // check S.M.A.R.T. status
+ if (cmdFullSmart) {
+ exec(cmdFullSmart, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ try {
+ const data = JSON.parse(`[${stdout}]`);
+ data.forEach(disk => {
+ const diskBSDName = disk.smartctl.argv[disk.smartctl.argv.length - 1];
+
+ for (let i = 0; i < result.length; i++) {
+ if (result[i].BSDName === diskBSDName) {
+ result[i].smartStatus = (disk.smart_status.passed ? 'Ok' : (disk.smart_status.passed === false ? 'Predicted Failure' : 'unknown'));
+ if (disk.temperature && disk.temperature.current) {
+ result[i].temperature = disk.temperature.current;
+ }
+ result[i].smartData = disk;
+ }
+ }
+ });
+ commitResult(result);
+ } catch (e) {
+ if (cmd) {
+ cmd = cmd + 'printf "\n"';
+ exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(line => {
+ if (line) {
+ let parts = line.split('|');
+ if (parts.length === 2) {
+ let BSDName = parts[0];
+ parts[1] = parts[1].trim();
+ let parts2 = parts[1].split(':');
+ if (parts2.length === 2) {
+ parts2[1] = parts2[1].trim();
+ let status = parts2[1].toLowerCase();
+ for (let i = 0; i < result.length; i++) {
+ if (result[i].BSDName === BSDName) {
+ result[i].smartStatus = (status === 'passed' ? 'Ok' : (status === 'failed!' ? 'Predicted Failure' : 'unknown'));
+ }
+ }
+ }
+ }
+ }
+ });
+ commitResult(result);
+ });
+ } else {
+ commitResult(result);
+ }
+ }
+ });
+ } else {
+ commitResult(result);
+ }
+ });
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_darwin) {
+ exec('system_profiler SPSerialATADataType SPNVMeDataType SPUSBDataType', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ if (!error) {
+ // split by type:
+ let lines = stdout.toString().split('\n');
+ let linesSATA = [];
+ let linesNVMe = [];
+ let linesUSB = [];
+ let dataType = 'SATA';
+ lines.forEach(line => {
+ if (line === 'NVMExpress:') { dataType = 'NVMe'; }
+ else if (line === 'USB:') { dataType = 'USB'; }
+ else if (line === 'SATA/SATA Express:') { dataType = 'SATA'; }
+ else if (dataType === 'SATA') { linesSATA.push(line); }
+ else if (dataType === 'NVMe') { linesNVMe.push(line); }
+ else if (dataType === 'USB') { linesUSB.push(line); }
+ });
+ try {
+ // Serial ATA Drives
+ let devices = linesSATA.join('\n').split(' Physical Interconnect: ');
+ devices.shift();
+ devices.forEach(function (device) {
+ device = 'InterfaceType: ' + device;
+ let lines = device.split('\n');
+ const mediumType = util.getValue(lines, 'Medium Type', ':', true).trim();
+ const sizeStr = util.getValue(lines, 'capacity', ':', true).trim();
+ const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim();
+ if (sizeStr) {
+ let sizeValue = 0;
+ if (sizeStr.indexOf('(') >= 0) {
+ sizeValue = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, '').replace(/,/g, '').replace(/\s/g, ''));
+ }
+ if (!sizeValue) {
+ sizeValue = parseInt(sizeStr);
+ }
+ if (sizeValue) {
+ const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase();
+ result.push({
+ device: BSDName,
+ type: mediumType.startsWith('Solid') ? 'SSD' : 'HD',
+ name: util.getValue(lines, 'Model', ':', true).trim(),
+ vendor: getVendorFromModel(util.getValue(lines, 'Model', ':', true).trim()) || util.getValue(lines, 'Manufacturer', ':', true),
+ size: sizeValue,
+ bytesPerSector: null,
+ totalCylinders: null,
+ totalHeads: null,
+ totalSectors: null,
+ totalTracks: null,
+ tracksPerCylinder: null,
+ sectorsPerTrack: null,
+ firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(),
+ serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(),
+ interfaceType: util.getValue(lines, 'InterfaceType', ':', true).trim(),
+ smartStatus: smartStatusString === 'verified' ? 'OK' : smartStatusString || 'unknown',
+ temperature: null,
+ BSDName: BSDName
+ });
+ cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
+ }
+ }
+ });
+ } catch (e) {
+ util.noop();
+ }
+
+ // NVME Drives
+ try {
+ let devices = linesNVMe.join('\n').split('\n\n Capacity:');
+ devices.shift();
+ devices.forEach(function (device) {
+ device = '!Capacity: ' + device;
+ let lines = device.split('\n');
+ const linkWidth = util.getValue(lines, 'link width', ':', true).trim();
+ const sizeStr = util.getValue(lines, '!capacity', ':', true).trim();
+ const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim();
+ if (sizeStr) {
+ let sizeValue = 0;
+ if (sizeStr.indexOf('(') >= 0) {
+ sizeValue = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, '').replace(/,/g, '').replace(/\s/g, ''));
+ }
+ if (!sizeValue) {
+ sizeValue = parseInt(sizeStr);
+ }
+ if (sizeValue) {
+ const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase();
+ result.push({
+ device: BSDName,
+ type: 'NVMe',
+ name: util.getValue(lines, 'Model', ':', true).trim(),
+ vendor: getVendorFromModel(util.getValue(lines, 'Model', ':', true).trim()),
+ size: sizeValue,
+ bytesPerSector: null,
+ totalCylinders: null,
+ totalHeads: null,
+ totalSectors: null,
+ totalTracks: null,
+ tracksPerCylinder: null,
+ sectorsPerTrack: null,
+ firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(),
+ serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(),
+ interfaceType: ('PCIe ' + linkWidth).trim(),
+ smartStatus: smartStatusString === 'verified' ? 'OK' : smartStatusString || 'unknown',
+ temperature: null,
+ BSDName: BSDName
+ });
+ cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
+ }
+ }
+ });
+ } catch (e) {
+ util.noop();
+ }
+ // USB Drives
+ try {
+ let devices = linesUSB.join('\n').replaceAll('Media:\n ', 'Model:').split('\n\n Product ID:');
+ devices.shift();
+ devices.forEach(function (device) {
+ let lines = device.split('\n');
+ const sizeStr = util.getValue(lines, 'Capacity', ':', true).trim();
+ const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim();
+ if (sizeStr) {
+ let sizeValue = 0;
+ if (sizeStr.indexOf('(') >= 0) {
+ sizeValue = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, '').replace(/,/g, '').replace(/\s/g, ''));
+ }
+ if (!sizeValue) {
+ sizeValue = parseInt(sizeStr);
+ }
+ if (sizeValue) {
+ const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase();
+ result.push({
+ device: BSDName,
+ type: 'USB',
+ name: util.getValue(lines, 'Model', ':', true).trim().replaceAll(':', ''),
+ vendor: getVendorFromModel(util.getValue(lines, 'Model', ':', true).trim()),
+ size: sizeValue,
+ bytesPerSector: null,
+ totalCylinders: null,
+ totalHeads: null,
+ totalSectors: null,
+ totalTracks: null,
+ tracksPerCylinder: null,
+ sectorsPerTrack: null,
+ firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(),
+ serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(),
+ interfaceType: 'USB',
+ smartStatus: smartStatusString === 'verified' ? 'OK' : smartStatusString || 'unknown',
+ temperature: null,
+ BSDName: BSDName
+ });
+ cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
+ }
+ }
+ });
+ } catch (e) {
+ util.noop();
+ }
+ if (cmd) {
+ cmd = cmd + 'printf "\n"';
+ exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(line => {
+ if (line) {
+ let parts = line.split('|');
+ if (parts.length === 2) {
+ let BSDName = parts[0];
+ parts[1] = parts[1].trim();
+ let parts2 = parts[1].split(':');
+ if (parts2.length === 2) {
+ parts2[1] = parts2[1].trim();
+ let status = parts2[1].toLowerCase();
+ for (let i = 0; i < result.length; i++) {
+ if (result[i].BSDName === BSDName) {
+ result[i].smartStatus = (status === 'not supported' ? 'not supported' : (status === 'verified' ? 'Ok' : (status === 'failing' ? 'Predicted Failure' : 'unknown')));
+ }
+ }
+ }
+ }
+ }
+ });
+ for (let i = 0; i < result.length; i++) {
+ delete result[i].BSDName;
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ for (let i = 0; i < result.length; i++) {
+ delete result[i].BSDName;
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ }
+ });
+ }
+ if (_windows) {
+ try {
+ const workload = [];
+ workload.push(util.powerShell('Get-WmiObject Win32_DiskDrive | select Caption,Size,Status,PNPDeviceId,BytesPerSector,TotalCylinders,TotalHeads,TotalSectors,TotalTracks,TracksPerCylinder,SectorsPerTrack,FirmwareRevision,SerialNumber,InterfaceType | fl'));
+ workload.push(util.powerShell('Get-PhysicalDisk | select BusType,MediaType,FriendlyName,Model,SerialNumber,Size | fl'));
+ if (util.smartMonToolsInstalled()) {
+ try {
+ const smartDev = JSON.parse(execSync('smartctl --scan -j'));
+ if (smartDev && smartDev.devices && smartDev.devices.length > 0) {
+ smartDev.devices.forEach((dev) => {
+ workload.push(execPromiseSave(`smartctl -j -a ${dev.name}`, util.execOptsWin));
+ });
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ util.promiseAll(
+ workload
+ ).then((data) => {
+ let devices = data.results[0].toString().split(/\n\s*\n/);
+ devices.forEach(function (device) {
+ let lines = device.split('\r\n');
+ const size = util.getValue(lines, 'Size', ':').trim();
+ const status = util.getValue(lines, 'Status', ':').trim().toLowerCase();
+ if (size) {
+ result.push({
+ device: util.getValue(lines, 'PNPDeviceId', ':'),
+ type: device.indexOf('SSD') > -1 ? 'SSD' : 'HD', // just a starting point ... better: MSFT_PhysicalDisk - Media Type ... see below
+ name: util.getValue(lines, 'Caption', ':'),
+ vendor: getVendorFromModel(util.getValue(lines, 'Caption', ':', true).trim()),
+ size: parseInt(size),
+ bytesPerSector: parseInt(util.getValue(lines, 'BytesPerSector', ':')),
+ totalCylinders: parseInt(util.getValue(lines, 'TotalCylinders', ':')),
+ totalHeads: parseInt(util.getValue(lines, 'TotalHeads', ':')),
+ totalSectors: parseInt(util.getValue(lines, 'TotalSectors', ':')),
+ totalTracks: parseInt(util.getValue(lines, 'TotalTracks', ':')),
+ tracksPerCylinder: parseInt(util.getValue(lines, 'TracksPerCylinder', ':')),
+ sectorsPerTrack: parseInt(util.getValue(lines, 'SectorsPerTrack', ':')),
+ firmwareRevision: util.getValue(lines, 'FirmwareRevision', ':').trim(),
+ serialNum: util.getValue(lines, 'SerialNumber', ':').trim(),
+ interfaceType: util.getValue(lines, 'InterfaceType', ':').trim(),
+ smartStatus: (status === 'ok' ? 'Ok' : (status === 'degraded' ? 'Degraded' : (status === 'pred fail' ? 'Predicted Failure' : 'Unknown'))),
+ temperature: null,
+ });
+ }
+ });
+ devices = data.results[1].split(/\n\s*\n/);
+ devices.forEach(function (device) {
+ let lines = device.split('\r\n');
+ const serialNum = util.getValue(lines, 'SerialNumber', ':').trim();
+ const name = util.getValue(lines, 'FriendlyName', ':').trim().replace('Msft ', 'Microsoft');
+ const size = util.getValue(lines, 'Size', ':').trim();
+ const model = util.getValue(lines, 'Model', ':').trim();
+ const interfaceType = util.getValue(lines, 'BusType', ':').trim();
+ let mediaType = util.getValue(lines, 'MediaType', ':').trim();
+ if (mediaType === '3' || mediaType === 'HDD') { mediaType = 'HD'; }
+ if (mediaType === '4') { mediaType = 'SSD'; }
+ if (mediaType === '5') { mediaType = 'SCM'; }
+ if (mediaType === 'Unspecified' && (model.toLowerCase().indexOf('virtual') > -1 || model.toLowerCase().indexOf('vbox') > -1)) { mediaType = 'Virtual'; }
+ if (size) {
+ let i = util.findObjectByKey(result, 'serialNum', serialNum);
+ if (i === -1 || serialNum === '') {
+ i = util.findObjectByKey(result, 'name', name);
+ }
+ if (i != -1) {
+ result[i].type = mediaType;
+ result[i].interfaceType = interfaceType;
+ }
+ }
+ });
+ // S.M.A.R.T
+ data.results.shift();
+ data.results.shift();
+ if (data.results.length) {
+ data.results.forEach((smartStr) => {
+ try {
+ const smartData = JSON.parse(smartStr);
+ if (smartData.serial_number) {
+ const serialNum = smartData.serial_number;
+ let i = util.findObjectByKey(result, 'serialNum', serialNum);
+ if (i != -1) {
+ result[i].smartStatus = (smartData.smart_status && smartData.smart_status.passed ? 'Ok' : (smartData.smart_status && smartData.smart_status.passed === false ? 'Predicted Failure' : 'unknown'));
+ if (smartData.temperature && smartData.temperature.current) {
+ result[i].temperature = smartData.temperature.current;
+ }
+ result[i].smartData = smartData;
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+ });
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.diskLayout = diskLayout;
diff --git a/MistyCore/node_modules/systeminformation/lib/graphics.js b/MistyCore/node_modules/systeminformation/lib/graphics.js
new file mode 100644
index 0000000..e5d98b5
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/graphics.js
@@ -0,0 +1,1066 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// graphics.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 7. Graphics (controller, display)
+// ----------------------------------------------------------------------------------
+
+const fs = require('fs');
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const util = require('./util');
+
+let _platform = process.platform;
+let _nvidiaSmiPath = '';
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+let _resolutionX = 0;
+let _resolutionY = 0;
+let _pixelDepth = 0;
+let _refreshRate = 0;
+
+const videoTypes = {
+ '-2': 'UNINITIALIZED',
+ '-1': 'OTHER',
+ '0': 'HD15',
+ '1': 'SVIDEO',
+ '2': 'Composite video',
+ '3': 'Component video',
+ '4': 'DVI',
+ '5': 'HDMI',
+ '6': 'LVDS',
+ '8': 'D_JPN',
+ '9': 'SDI',
+ '10': 'DP',
+ '11': 'DP embedded',
+ '12': 'UDI',
+ '13': 'UDI embedded',
+ '14': 'SDTVDONGLE',
+ '15': 'MIRACAST',
+ '2147483648': 'INTERNAL'
+};
+
+function getVendorFromModel(model) {
+ const manufacturers = [
+ { pattern: '^LG.+', manufacturer: 'LG' },
+ { pattern: '^BENQ.+', manufacturer: 'BenQ' },
+ { pattern: '^ASUS.+', manufacturer: 'Asus' },
+ { pattern: '^DELL.+', manufacturer: 'Dell' },
+ { pattern: '^SAMSUNG.+', manufacturer: 'Samsung' },
+ { pattern: '^VIEWSON.+', manufacturer: 'ViewSonic' },
+ { pattern: '^SONY.+', manufacturer: 'Sony' },
+ { pattern: '^ACER.+', manufacturer: 'Acer' },
+ { pattern: '^AOC.+', manufacturer: 'AOC Monitors' },
+ { pattern: '^HP.+', manufacturer: 'HP' },
+ { pattern: '^EIZO.?', manufacturer: 'Eizo' },
+ { pattern: '^PHILIPS.?', manufacturer: 'Philips' },
+ { pattern: '^IIYAMA.?', manufacturer: 'Iiyama' },
+ { pattern: '^SHARP.?', manufacturer: 'Sharp' },
+ { pattern: '^NEC.?', manufacturer: 'NEC' },
+ { pattern: '^LENOVO.?', manufacturer: 'Lenovo' },
+ { pattern: 'COMPAQ.?', manufacturer: 'Compaq' },
+ { pattern: 'APPLE.?', manufacturer: 'Apple' },
+ { pattern: 'INTEL.?', manufacturer: 'Intel' },
+ { pattern: 'AMD.?', manufacturer: 'AMD' },
+ { pattern: 'NVIDIA.?', manufacturer: 'NVDIA' },
+ ];
+
+ let result = '';
+ if (model) {
+ model = model.toUpperCase();
+ manufacturers.forEach((manufacturer) => {
+ const re = RegExp(manufacturer.pattern);
+ if (re.test(model)) { result = manufacturer.manufacturer; }
+ });
+ }
+ return result;
+}
+
+function getVendorFromId(id) {
+ const vendors = {
+ '610': 'Apple',
+ '1e6d': 'LG',
+ '10ac': 'DELL',
+ '4dd9': 'Sony',
+ '38a3': 'NEC',
+ };
+ return vendors[id] || '';
+}
+
+function vendorToId(str) {
+ let result = '';
+ str = (str || '').toLowerCase();
+ if (str.indexOf('apple') >= 0) { result = '0x05ac'; }
+ else if (str.indexOf('nvidia') >= 0) { result = '0x10de'; }
+ else if (str.indexOf('intel') >= 0) { result = '0x8086'; }
+ else if (str.indexOf('ati') >= 0 || str.indexOf('amd') >= 0) { result = '0x1002'; }
+
+ return result;
+}
+
+function getMetalVersion(id) {
+ const families = {
+ 'spdisplays_mtlgpufamilymac1': 'mac1',
+ 'spdisplays_mtlgpufamilymac2': 'mac2',
+ 'spdisplays_mtlgpufamilyapple1': 'apple1',
+ 'spdisplays_mtlgpufamilyapple2': 'apple2',
+ 'spdisplays_mtlgpufamilyapple3': 'apple3',
+ 'spdisplays_mtlgpufamilyapple4': 'apple4',
+ 'spdisplays_mtlgpufamilyapple5': 'apple5',
+ 'spdisplays_mtlgpufamilyapple6': 'apple6',
+ 'spdisplays_mtlgpufamilyapple7': 'apple7',
+ 'spdisplays_metalfeaturesetfamily11': 'family1_v1',
+ 'spdisplays_metalfeaturesetfamily12': 'family1_v2',
+ 'spdisplays_metalfeaturesetfamily13': 'family1_v3',
+ 'spdisplays_metalfeaturesetfamily14': 'family1_v4',
+ 'spdisplays_metalfeaturesetfamily21': 'family2_v1'
+ };
+ return families[id] || '';
+}
+
+function graphics(callback) {
+
+ function parseLinesDarwin(graphicsArr) {
+ const res = {
+ controllers: [],
+ displays: []
+ };
+ try {
+ graphicsArr.forEach(function (item) {
+ // controllers
+ const bus = ((item.sppci_bus || '').indexOf('builtin') > -1 ? 'Built-In' : ((item.sppci_bus || '').indexOf('pcie') > -1 ? 'PCIe' : ''));
+ const vram = (parseInt((item.spdisplays_vram || ''), 10) || 0) * (((item.spdisplays_vram || '').indexOf('GB') > -1) ? 1024 : 1);
+ const vramDyn = (parseInt((item.spdisplays_vram_shared || ''), 10) || 0) * (((item.spdisplays_vram_shared || '').indexOf('GB') > -1) ? 1024 : 1);
+ let metalVersion = getMetalVersion(item.spdisplays_metal || item.spdisplays_metalfamily || '');
+ res.controllers.push({
+ vendor: getVendorFromModel(item.spdisplays_vendor || '') || item.spdisplays_vendor || '',
+ model: item.sppci_model || '',
+ bus,
+ vramDynamic: bus === 'Built-In',
+ vram: vram || vramDyn || null,
+ deviceId: item['spdisplays_device-id'] || '',
+ vendorId: item['spdisplays_vendor-id'] || vendorToId((item['spdisplays_vendor'] || '') + (item.sppci_model || '')),
+ external: (item.sppci_device_type === 'spdisplays_egpu'),
+ cores: item['sppci_cores'] || null,
+ metalVersion
+ });
+
+ // displays
+ if (item.spdisplays_ndrvs && item.spdisplays_ndrvs.length) {
+ item.spdisplays_ndrvs.forEach(function (displayItem) {
+ const connectionType = displayItem['spdisplays_connection_type'] || '';
+ const currentResolutionParts = (displayItem['_spdisplays_resolution'] || '').split('@');
+ const currentResolution = currentResolutionParts[0].split('x');
+ const pixelParts = (displayItem['_spdisplays_pixels'] || '').split('x');
+ const pixelDepthString = displayItem['spdisplays_depth'] || '';
+ const serial = displayItem['_spdisplays_display-serial-number'] || displayItem['_spdisplays_display-serial-number2'] || null;
+ res.displays.push({
+ vendor: getVendorFromId(displayItem['_spdisplays_display-vendor-id'] || '') || getVendorFromModel(displayItem['_name'] || ''),
+ vendorId: displayItem['_spdisplays_display-vendor-id'] || '',
+ model: displayItem['_name'] || '',
+ productionYear: displayItem['_spdisplays_display-year'] || null,
+ serial: serial !== '0' ? serial : null,
+ displayId: displayItem['_spdisplays_displayID'] || null,
+ main: displayItem['spdisplays_main'] ? displayItem['spdisplays_main'] === 'spdisplays_yes' : false,
+ builtin: (displayItem['spdisplays_display_type'] || '').indexOf('built-in') > -1,
+ connection: ((connectionType.indexOf('_internal') > -1) ? 'Internal' : ((connectionType.indexOf('_displayport') > -1) ? 'Display Port' : ((connectionType.indexOf('_hdmi') > -1) ? 'HDMI' : null))),
+ sizeX: null,
+ sizeY: null,
+ pixelDepth: (pixelDepthString === 'CGSThirtyBitColor' ? 30 : (pixelDepthString === 'CGSThirtytwoBitColor' ? 32 : (pixelDepthString === 'CGSTwentyfourBitColor' ? 24 : null))),
+ resolutionX: pixelParts.length > 1 ? parseInt(pixelParts[0], 10) : null,
+ resolutionY: pixelParts.length > 1 ? parseInt(pixelParts[1], 10) : null,
+ currentResX: currentResolution.length > 1 ? parseInt(currentResolution[0], 10) : null,
+ currentResY: currentResolution.length > 1 ? parseInt(currentResolution[1], 10) : null,
+ positionX: 0,
+ positionY: 0,
+ currentRefreshRate: currentResolutionParts.length > 1 ? parseInt(currentResolutionParts[1], 10) : null,
+
+ });
+ });
+ }
+ });
+ return res;
+ } catch (e) {
+ return res;
+ }
+ }
+
+ function parseLinesLinuxControllers(lines) {
+ let controllers = [];
+ let currentController = {
+ vendor: '',
+ model: '',
+ bus: '',
+ busAddress: '',
+ vram: null,
+ vramDynamic: false,
+ pciID: ''
+ };
+ let isGraphicsController = false;
+ // PCI bus IDs
+ let pciIDs = [];
+ try {
+ pciIDs = execSync('export LC_ALL=C; dmidecode -t 9 2>/dev/null; unset LC_ALL | grep "Bus Address: "').toString().split('\n');
+ for (let i = 0; i < pciIDs.length; i++) {
+ pciIDs[i] = pciIDs[i].replace('Bus Address:', '').replace('0000:', '').trim();
+ }
+ pciIDs = pciIDs.filter(function (el) {
+ return el != null && el;
+ });
+ } catch (e) {
+ util.noop();
+ }
+ for (let i = 0; i < lines.length; i++) {
+ if ('' !== lines[i].trim()) {
+ if (' ' !== lines[i][0] && '\t' !== lines[i][0]) { // first line of new entry
+ let isExternal = (pciIDs.indexOf(lines[i].split(' ')[0]) >= 0);
+ let vgapos = lines[i].toLowerCase().indexOf(' vga ');
+ let _3dcontrollerpos = lines[i].toLowerCase().indexOf('3d controller');
+ if (vgapos !== -1 || _3dcontrollerpos !== -1) { // VGA
+ if (_3dcontrollerpos !== -1 && vgapos === -1) {
+ vgapos = _3dcontrollerpos;
+ }
+ if (currentController.vendor || currentController.model || currentController.bus || currentController.vram !== null || currentController.vramDynamic) { // already a controller found
+ controllers.push(currentController);
+ currentController = {
+ vendor: '',
+ model: '',
+ bus: '',
+ busAddress: '',
+ vram: null,
+ vramDynamic: false,
+ };
+ }
+
+ const pciIDCandidate = lines[i].split(' ')[0];
+ if (/[\da-fA-F]{2}:[\da-fA-F]{2}\.[\da-fA-F]/.test(pciIDCandidate)) {
+ currentController.busAddress = pciIDCandidate;
+ }
+ isGraphicsController = true;
+ let endpos = lines[i].search(/\[[0-9a-f]{4}:[0-9a-f]{4}]|$/);
+ let parts = lines[i].substr(vgapos, endpos - vgapos).split(':');
+ currentController.busAddress = lines[i].substr(0, vgapos).trim();
+ if (parts.length > 1) {
+ parts[1] = parts[1].trim();
+ if (parts[1].toLowerCase().indexOf('corporation') >= 0) {
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf('corporation') + 11).trim();
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf('corporation') + 11, 200).trim().split('(')[0];
+ currentController.bus = (pciIDs.length > 0 && isExternal) ? 'PCIe' : 'Onboard';
+ currentController.vram = null;
+ currentController.vramDynamic = false;
+ } else if (parts[1].toLowerCase().indexOf(' inc.') >= 0) {
+ if ((parts[1].match(new RegExp(']', 'g')) || []).length > 1) {
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(']') + 1).trim();
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(']') + 1, 200).trim().split('(')[0].trim();
+ } else {
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(' inc.') + 5).trim();
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(' inc.') + 5, 200).trim().split('(')[0].trim();
+ }
+ currentController.bus = (pciIDs.length > 0 && isExternal) ? 'PCIe' : 'Onboard';
+ currentController.vram = null;
+ currentController.vramDynamic = false;
+ } else if (parts[1].toLowerCase().indexOf(' ltd.') >= 0) {
+ if ((parts[1].match(new RegExp(']', 'g')) || []).length > 1) {
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(']') + 1).trim();
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(']') + 1, 200).trim().split('(')[0].trim();
+ } else {
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(' ltd.') + 5).trim();
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(' ltd.') + 5, 200).trim().split('(')[0].trim();
+ }
+ }
+ }
+
+ } else {
+ isGraphicsController = false;
+ }
+ }
+ if (isGraphicsController) { // within VGA details
+ let parts = lines[i].split(':');
+ if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('devicename') !== -1 && parts[1].toLowerCase().indexOf('onboard') !== -1) { currentController.bus = 'Onboard'; }
+ if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('region') !== -1 && parts[1].toLowerCase().indexOf('memory') !== -1) {
+ let memparts = parts[1].split('=');
+ if (memparts.length > 1) {
+ currentController.vram = parseInt(memparts[1]);
+ }
+ }
+ }
+ }
+ }
+ if (currentController.vendor || currentController.model || currentController.bus || currentController.busAddress || currentController.vram !== null || currentController.vramDynamic) { // already a controller found
+ controllers.push(currentController);
+ }
+ return (controllers);
+ }
+
+ function parseLinesLinuxClinfo(controllers, lines) {
+ const fieldPattern = /\[([^\]]+)\]\s+(\w+)\s+(.*)/;
+ const devices = lines.reduce((devices, line) => {
+ const field = fieldPattern.exec(line.trim());
+ if (field) {
+ if (!devices[field[1]]) {
+ devices[field[1]] = {};
+ }
+ devices[field[1]][field[2]] = field[3];
+ }
+ return devices;
+ }, {});
+ for (let deviceId in devices) {
+ const device = devices[deviceId];
+ if (device['CL_DEVICE_TYPE'] === 'CL_DEVICE_TYPE_GPU') {
+ let busAddress;
+ if (device['CL_DEVICE_TOPOLOGY_AMD']) {
+ const bdf = device['CL_DEVICE_TOPOLOGY_AMD'].match(/[a-zA-Z0-9]+:\d+\.\d+/);
+ if (bdf) {
+ busAddress = bdf[0];
+ }
+ } else if (device['CL_DEVICE_PCI_BUS_ID_NV'] && device['CL_DEVICE_PCI_SLOT_ID_NV']) {
+ const bus = parseInt(device['CL_DEVICE_PCI_BUS_ID_NV']);
+ const slot = parseInt(device['CL_DEVICE_PCI_SLOT_ID_NV']);
+ if (!isNaN(bus) && !isNaN(slot)) {
+ const b = bus & 0xff;
+ const d = (slot >> 3) & 0xff;
+ const f = slot & 0x07;
+ busAddress = `${b.toString().padStart(2, '0')}:${d.toString().padStart(2, '0')}.${f}`;
+ }
+ }
+ if (busAddress) {
+ let controller = controllers.find(controller => controller.busAddress === busAddress);
+ if (!controller) {
+ controller = {
+ vendor: '',
+ model: '',
+ bus: '',
+ busAddress,
+ vram: null,
+ vramDynamic: false
+ };
+ controllers.push(controller);
+ }
+ controller.vendor = device['CL_DEVICE_VENDOR'];
+ if (device['CL_DEVICE_BOARD_NAME_AMD']) {
+ controller.model = device['CL_DEVICE_BOARD_NAME_AMD'];
+ } else {
+ controller.model = device['CL_DEVICE_NAME'];
+ }
+ const memory = parseInt(device['CL_DEVICE_GLOBAL_MEM_SIZE']);
+ if (!isNaN(memory)) {
+ controller.vram = Math.round(memory / 1024 / 1024);
+ }
+ }
+ }
+ }
+ return controllers;
+ }
+
+ function getNvidiaSmi() {
+ if (_nvidiaSmiPath) {
+ return _nvidiaSmiPath;
+ }
+
+ if (_windows) {
+ try {
+ const basePath = util.WINDIR + '\\System32\\DriverStore\\FileRepository';
+ // find all directories that have an nvidia-smi.exe file
+ const candidateDirs = fs.readdirSync(basePath).filter(dir => {
+ return fs.readdirSync([basePath, dir].join('/')).includes('nvidia-smi.exe');
+ });
+ // use the directory with the most recently created nvidia-smi.exe file
+ const targetDir = candidateDirs.reduce((prevDir, currentDir) => {
+ const previousNvidiaSmi = fs.statSync([basePath, prevDir, 'nvidia-smi.exe'].join('/'));
+ const currentNvidiaSmi = fs.statSync([basePath, currentDir, 'nvidia-smi.exe'].join('/'));
+ return (previousNvidiaSmi.ctimeMs > currentNvidiaSmi.ctimeMs) ? prevDir : currentDir;
+ });
+
+ if (targetDir) {
+ _nvidiaSmiPath = [basePath, targetDir, 'nvidia-smi.exe'].join('/');
+ }
+ } catch (e) {
+ util.noop();
+ }
+ } else if (_linux) {
+ _nvidiaSmiPath = 'nvidia-smi';
+ }
+ return _nvidiaSmiPath;
+ }
+
+ function nvidiaSmi(options) {
+ const nvidiaSmiExe = getNvidiaSmi();
+ options = options || util.execOptsWin;
+ if (nvidiaSmiExe) {
+ const nvidiaSmiOpts = '--query-gpu=driver_version,pci.sub_device_id,name,pci.bus_id,fan.speed,memory.total,memory.used,memory.free,utilization.gpu,utilization.memory,temperature.gpu,temperature.memory,power.draw,power.limit,clocks.gr,clocks.mem --format=csv,noheader,nounits';
+ const cmd = nvidiaSmiExe + ' ' + nvidiaSmiOpts + (_linux ? ' 2>/dev/null' : '');
+ try {
+ const res = execSync(cmd, options).toString();
+ return res;
+ } catch (e) {
+ util.noop();
+ }
+ }
+ return '';
+ }
+
+ function nvidiaDevices() {
+
+ function safeParseNumber(value) {
+ if ([null, undefined].includes(value)) {
+ return value;
+ }
+ return parseFloat(value);
+ }
+
+ const stdout = nvidiaSmi();
+ if (!stdout) {
+ return [];
+ }
+
+ const gpus = stdout.split('\n').filter(Boolean);
+ let results = gpus.map(gpu => {
+ const splittedData = gpu.split(', ').map(value => value.includes('N/A') ? undefined : value);
+ if (splittedData.length === 16) {
+ return {
+ driverVersion: splittedData[0],
+ subDeviceId: splittedData[1],
+ name: splittedData[2],
+ pciBus: splittedData[3],
+ fanSpeed: safeParseNumber(splittedData[4]),
+ memoryTotal: safeParseNumber(splittedData[5]),
+ memoryUsed: safeParseNumber(splittedData[6]),
+ memoryFree: safeParseNumber(splittedData[7]),
+ utilizationGpu: safeParseNumber(splittedData[8]),
+ utilizationMemory: safeParseNumber(splittedData[9]),
+ temperatureGpu: safeParseNumber(splittedData[10]),
+ temperatureMemory: safeParseNumber(splittedData[11]),
+ powerDraw: safeParseNumber(splittedData[12]),
+ powerLimit: safeParseNumber(splittedData[13]),
+ clockCore: safeParseNumber(splittedData[14]),
+ clockMemory: safeParseNumber(splittedData[15]),
+ };
+ } else {
+ return {};
+ }
+ });
+ results = results.filter((item) => {
+ return ('pciBus' in item);
+ });
+ return results;
+ }
+
+ function mergeControllerNvidia(controller, nvidia) {
+ if (nvidia.driverVersion) { controller.driverVersion = nvidia.driverVersion; }
+ if (nvidia.subDeviceId) { controller.subDeviceId = nvidia.subDeviceId; }
+ if (nvidia.name) { controller.name = nvidia.name; }
+ if (nvidia.pciBus) { controller.pciBus = nvidia.pciBus; }
+ if (nvidia.fanSpeed) { controller.fanSpeed = nvidia.fanSpeed; }
+ if (nvidia.memoryTotal) {
+ controller.memoryTotal = nvidia.memoryTotal;
+ controller.vram = nvidia.memoryTotal;
+ controller.vramDynamic = false;
+ }
+ if (nvidia.memoryUsed) { controller.memoryUsed = nvidia.memoryUsed; }
+ if (nvidia.memoryFree) { controller.memoryFree = nvidia.memoryFree; }
+ if (nvidia.utilizationGpu) { controller.utilizationGpu = nvidia.utilizationGpu; }
+ if (nvidia.utilizationMemory) { controller.utilizationMemory = nvidia.utilizationMemory; }
+ if (nvidia.temperatureGpu) { controller.temperatureGpu = nvidia.temperatureGpu; }
+ if (nvidia.temperatureMemory) { controller.temperatureMemory = nvidia.temperatureMemory; }
+ if (nvidia.powerDraw) { controller.powerDraw = nvidia.powerDraw; }
+ if (nvidia.powerLimit) { controller.powerLimit = nvidia.powerLimit; }
+ if (nvidia.clockCore) { controller.clockCore = nvidia.clockCore; }
+ if (nvidia.clockMemory) { controller.clockMemory = nvidia.clockMemory; }
+ return controller;
+ }
+
+ function parseLinesLinuxEdid(edid) {
+ // parsen EDID
+ // --> model
+ // --> resolutionx
+ // --> resolutiony
+ // --> builtin = false
+ // --> pixeldepth (?)
+ // --> sizex
+ // --> sizey
+ let result = {
+ vendor: '',
+ model: '',
+ deviceName: '',
+ main: false,
+ builtin: false,
+ connection: '',
+ sizeX: null,
+ sizeY: null,
+ pixelDepth: null,
+ resolutionX: null,
+ resolutionY: null,
+ currentResX: null,
+ currentResY: null,
+ positionX: 0,
+ positionY: 0,
+ currentRefreshRate: null
+ };
+ // find first "Detailed Timing Description"
+ let start = 108;
+ if (edid.substr(start, 6) === '000000') {
+ start += 36;
+ }
+ if (edid.substr(start, 6) === '000000') {
+ start += 36;
+ }
+ if (edid.substr(start, 6) === '000000') {
+ start += 36;
+ }
+ if (edid.substr(start, 6) === '000000') {
+ start += 36;
+ }
+ result.resolutionX = parseInt('0x0' + edid.substr(start + 8, 1) + edid.substr(start + 4, 2));
+ result.resolutionY = parseInt('0x0' + edid.substr(start + 14, 1) + edid.substr(start + 10, 2));
+ result.sizeX = parseInt('0x0' + edid.substr(start + 28, 1) + edid.substr(start + 24, 2));
+ result.sizeY = parseInt('0x0' + edid.substr(start + 29, 1) + edid.substr(start + 26, 2));
+ // monitor name
+ start = edid.indexOf('000000fc00'); // find first "Monitor Description Data"
+ if (start >= 0) {
+ let model_raw = edid.substr(start + 10, 26);
+ if (model_raw.indexOf('0a') !== -1) {
+ model_raw = model_raw.substr(0, model_raw.indexOf('0a'));
+ }
+ try {
+ if (model_raw.length > 2) {
+ result.model = model_raw.match(/.{1,2}/g).map(function (v) {
+ return String.fromCharCode(parseInt(v, 16));
+ }).join('');
+ }
+ } catch (e) {
+ util.noop();
+ }
+ } else {
+ result.model = '';
+ }
+ return result;
+ }
+
+ function parseLinesLinuxDisplays(lines, depth) {
+ let displays = [];
+ let currentDisplay = {
+ vendor: '',
+ model: '',
+ deviceName: '',
+ main: false,
+ builtin: false,
+ connection: '',
+ sizeX: null,
+ sizeY: null,
+ pixelDepth: null,
+ resolutionX: null,
+ resolutionY: null,
+ currentResX: null,
+ currentResY: null,
+ positionX: 0,
+ positionY: 0,
+ currentRefreshRate: null
+ };
+ let is_edid = false;
+ let is_current = false;
+ let edid_raw = '';
+ let start = 0;
+ for (let i = 1; i < lines.length; i++) { // start with second line
+ if ('' !== lines[i].trim()) {
+ if (' ' !== lines[i][0] && '\t' !== lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') !== -1) { // first line of new entry
+ if (currentDisplay.model || currentDisplay.main || currentDisplay.builtin || currentDisplay.connection || currentDisplay.sizeX !== null || currentDisplay.pixelDepth !== null || currentDisplay.resolutionX !== null) { // push last display to array
+ displays.push(currentDisplay);
+ currentDisplay = {
+ vendor: '',
+ model: '',
+ main: false,
+ builtin: false,
+ connection: '',
+ sizeX: null,
+ sizeY: null,
+ pixelDepth: null,
+ resolutionX: null,
+ resolutionY: null,
+ currentResX: null,
+ currentResY: null,
+ positionX: 0,
+ positionY: 0,
+ currentRefreshRate: null
+ };
+ }
+ let parts = lines[i].split(' ');
+ currentDisplay.connection = parts[0];
+ currentDisplay.main = lines[i].toLowerCase().indexOf(' primary ') >= 0;
+ currentDisplay.builtin = (parts[0].toLowerCase().indexOf('edp') >= 0);
+ }
+
+ // try to read EDID information
+ if (is_edid) {
+ if (lines[i].search(/\S|$/) > start) {
+ edid_raw += lines[i].toLowerCase().trim();
+ } else {
+ // parsen EDID
+ let edid_decoded = parseLinesLinuxEdid(edid_raw);
+ currentDisplay.vendor = edid_decoded.vendor;
+ currentDisplay.model = edid_decoded.model;
+ currentDisplay.resolutionX = edid_decoded.resolutionX;
+ currentDisplay.resolutionY = edid_decoded.resolutionY;
+ currentDisplay.sizeX = edid_decoded.sizeX;
+ currentDisplay.sizeY = edid_decoded.sizeY;
+ currentDisplay.pixelDepth = depth;
+ is_edid = false;
+ }
+ }
+ if (lines[i].toLowerCase().indexOf('edid:') >= 0) {
+ is_edid = true;
+ start = lines[i].search(/\S|$/);
+ }
+ if (lines[i].toLowerCase().indexOf('*current') >= 0) {
+ const parts1 = lines[i].split('(');
+ if (parts1 && parts1.length > 1 && parts1[0].indexOf('x') >= 0) {
+ const resParts = parts1[0].trim().split('x');
+ currentDisplay.currentResX = util.toInt(resParts[0]);
+ currentDisplay.currentResY = util.toInt(resParts[1]);
+ }
+ is_current = true;
+ }
+ if (is_current && lines[i].toLowerCase().indexOf('clock') >= 0 && lines[i].toLowerCase().indexOf('hz') >= 0 && lines[i].toLowerCase().indexOf('v: height') >= 0) {
+ const parts1 = lines[i].split('clock');
+ if (parts1 && parts1.length > 1 && parts1[1].toLowerCase().indexOf('hz') >= 0) {
+ currentDisplay.currentRefreshRate = util.toInt(parts1[1]);
+ }
+ is_current = false;
+ }
+ }
+ }
+
+ // pushen displays
+ if (currentDisplay.model || currentDisplay.main || currentDisplay.builtin || currentDisplay.connection || currentDisplay.sizeX !== null || currentDisplay.pixelDepth !== null || currentDisplay.resolutionX !== null) { // still information there
+ displays.push(currentDisplay);
+ }
+ return displays;
+ }
+
+ // function starts here
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = {
+ controllers: [],
+ displays: []
+ };
+ if (_darwin) {
+ let cmd = 'system_profiler -xml -detailLevel full SPDisplaysDataType';
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ try {
+ let output = stdout.toString();
+ result = parseLinesDarwin(util.plistParser(output)[0]._items);
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_linux) {
+ // Raspberry: https://elinux.org/RPI_vcgencmd_usage
+ if (util.isRaspberry() && util.isRaspbian()) {
+ let cmd = 'fbset -s | grep \'mode "\'; vcgencmd get_mem gpu; tvservice -s; tvservice -n;';
+ exec(cmd, function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ if (lines.length > 3 && lines[0].indexOf('mode "') >= -1 && lines[2].indexOf('0x12000a') > -1) {
+ const parts = lines[0].replace('mode', '').replace(/"/g, '').trim().split('x');
+ if (parts.length === 2) {
+ result.displays.push({
+ vendor: '',
+ model: util.getValue(lines, 'device_name', '='),
+ main: true,
+ builtin: false,
+ connection: 'HDMI',
+ sizeX: null,
+ sizeY: null,
+ pixelDepth: null,
+ resolutionX: parseInt(parts[0], 10),
+ resolutionY: parseInt(parts[1], 10),
+ currentResX: null,
+ currentResY: null,
+ positionX: 0,
+ positionY: 0,
+ currentRefreshRate: null
+ });
+ }
+ }
+ if (lines.length > 1 && stdout.toString().indexOf('gpu=') >= -1) {
+ result.controllers.push({
+ vendor: 'Broadcom',
+ model: 'VideoCore IV',
+ bus: '',
+ vram: util.getValue(lines, 'gpu', '=').replace('M', ''),
+ vramDynamic: true
+ });
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ let cmd = 'lspci -vvv 2>/dev/null';
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.controllers = parseLinesLinuxControllers(lines);
+ const nvidiaData = nvidiaDevices();
+ // needs to be rewritten ... using no spread operators
+ result.controllers = result.controllers.map((controller) => { // match by busAddress
+ return mergeControllerNvidia(controller, nvidiaData.find((contr) => contr.pciBus.toLowerCase().endsWith(controller.busAddress.toLowerCase())) || {});
+ });
+ }
+ let cmd = 'clinfo --raw';
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.controllers = parseLinesLinuxClinfo(result.controllers, lines);
+ }
+ let cmd = 'xdpyinfo 2>/dev/null | grep \'depth of root window\' | awk \'{ print $5 }\'';
+ exec(cmd, function (error, stdout) {
+ let depth = 0;
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ depth = parseInt(lines[0]) || 0;
+ }
+ let cmd = 'xrandr --verbose 2>/dev/null';
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.displays = parseLinesLinuxDisplays(lines, depth);
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ });
+ });
+ });
+ }
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ if (callback) { callback(null); }
+ resolve(null);
+ }
+ if (_sunos) {
+ if (callback) { callback(null); }
+ resolve(null);
+ }
+ if (_windows) {
+
+ // https://blogs.technet.microsoft.com/heyscriptingguy/2013/10/03/use-powershell-to-discover-multi-monitor-information/
+ // https://devblogs.microsoft.com/scripting/use-powershell-to-discover-multi-monitor-information/
+ try {
+ const workload = [];
+ workload.push(util.powerShell('Get-WmiObject win32_VideoController | fl *'));
+ workload.push(util.powerShell('gp "HKLM:\\SYSTEM\\ControlSet001\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\*" -ErrorAction SilentlyContinue | where MatchingDeviceId $null -NE | select MatchingDeviceId,HardwareInformation.qwMemorySize | fl'));
+ workload.push(util.powerShell('Get-WmiObject win32_desktopmonitor | fl *'));
+ workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorBasicDisplayParams | fl'));
+ workload.push(util.powerShell('Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Screen]::AllScreens'));
+ workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorConnectionParams | fl'));
+ workload.push(util.powerShell('gwmi WmiMonitorID -Namespace root\\wmi | ForEach-Object {(($_.ManufacturerName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.ProductCodeID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.UserFriendlyName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.SerialNumberID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + $_.InstanceName}'));
+
+ const nvidiaData = nvidiaDevices();
+
+ Promise.all(
+ workload
+ ).then((data) => {
+ // controller + vram
+ let csections = data[0].replace(/\r/g, '').split(/\n\s*\n/);
+ let vsections = data[1].replace(/\r/g, '').split(/\n\s*\n/);
+ result.controllers = parseLinesWindowsControllers(csections, vsections);
+ result.controllers = result.controllers.map((controller) => { // match by subDeviceId
+ if (controller.vendor.toLowerCase() === 'nvidia') {
+ return mergeControllerNvidia(controller, nvidiaData.find(device => {
+ let windowsSubDeviceId = (controller.subDeviceId || '').toLowerCase();
+ const nvidiaSubDeviceIdParts = device.subDeviceId.split('x');
+ let nvidiaSubDeviceId = nvidiaSubDeviceIdParts.length > 1 ? nvidiaSubDeviceIdParts[1].toLowerCase() : nvidiaSubDeviceIdParts[0].toLowerCase();
+ const lengthDifference = Math.abs(windowsSubDeviceId.length - nvidiaSubDeviceId.length);
+ if (windowsSubDeviceId.length > nvidiaSubDeviceId.length) {
+ for (let i = 0; i < lengthDifference; i++) {
+ nvidiaSubDeviceId = '0' + nvidiaSubDeviceId;
+ }
+ } else if (windowsSubDeviceId.length < nvidiaSubDeviceId.length) {
+ for (let i = 0; i < lengthDifference; i++) {
+ windowsSubDeviceId = '0' + windowsSubDeviceId;
+ }
+ }
+ return windowsSubDeviceId === nvidiaSubDeviceId;
+ }) || {});
+ } else {
+ return controller;
+ }
+ });
+
+ // displays
+ let dsections = data[2].replace(/\r/g, '').split(/\n\s*\n/);
+ // result.displays = parseLinesWindowsDisplays(dsections);
+ if (dsections[0].trim() === '') { dsections.shift(); }
+ if (dsections.length && dsections[dsections.length - 1].trim() === '') { dsections.pop(); }
+
+ // monitor (powershell)
+ let msections = data[3].replace(/\r/g, '').split('Active ');
+ msections.shift();
+
+ // forms.screens (powershell)
+ let ssections = data[4].replace(/\r/g, '').split('BitsPerPixel ');
+ ssections.shift();
+
+ // connection params (powershell) - video type
+ let tsections = data[5].replace(/\r/g, '').split(/\n\s*\n/);
+ tsections.shift();
+
+ // monitor ID (powershell) - model / vendor
+ const res = data[6].replace(/\r/g, '').split(/\n/);
+ let isections = [];
+ res.forEach(element => {
+ const parts = element.split('|');
+ if (parts.length === 5) {
+ isections.push({
+ vendor: parts[0],
+ code: parts[1],
+ model: parts[2],
+ serial: parts[3],
+ instanceId: parts[4]
+ });
+ }
+ });
+
+ result.displays = parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections);
+
+ if (result.displays.length === 1) {
+ if (_resolutionX) {
+ result.displays[0].resolutionX = _resolutionX;
+ if (!result.displays[0].currentResX) {
+ result.displays[0].currentResX = _resolutionX;
+ }
+ }
+ if (_resolutionY) {
+ result.displays[0].resolutionY = _resolutionY;
+ if (result.displays[0].currentResY === 0) {
+ result.displays[0].currentResY = _resolutionY;
+ }
+ }
+ if (_pixelDepth) {
+ result.displays[0].pixelDepth = _pixelDepth;
+ }
+ if (_refreshRate && !result.displays[0].currentRefreshRate) {
+ result.displays[0].currentRefreshRate = _refreshRate;
+ }
+ }
+
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ })
+ .catch(() => {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+
+ function parseLinesWindowsControllers(sections, vections) {
+ const memorySizes = {};
+ for (const i in vections) {
+ if ({}.hasOwnProperty.call(vections, i)) {
+ if (vections[i].trim() !== '') {
+ const lines = vections[i].trim().split('\n');
+ const matchingDeviceId = util.getValue(lines, 'MatchingDeviceId').match(/PCI\\(VEN_[0-9A-F]{4})&(DEV_[0-9A-F]{4})(?:&(SUBSYS_[0-9A-F]{8}))?(?:&(REV_[0-9A-F]{2}))?/i);
+ if (matchingDeviceId) {
+ const quadWordmemorySize = parseInt(util.getValue(lines, 'HardwareInformation.qwMemorySize'));
+ if (!isNaN(quadWordmemorySize)) {
+ let deviceId = matchingDeviceId[1].toUpperCase() + '&' + matchingDeviceId[2].toUpperCase();
+ if (matchingDeviceId[3]) {
+ deviceId += '&' + matchingDeviceId[3].toUpperCase();
+ }
+ if (matchingDeviceId[4]) {
+ deviceId += '&' + matchingDeviceId[4].toUpperCase();
+ }
+ memorySizes[deviceId] = quadWordmemorySize;
+ }
+ }
+ }
+ }
+ }
+
+ let controllers = [];
+ for (let i in sections) {
+ if ({}.hasOwnProperty.call(sections, i)) {
+ if (sections[i].trim() !== '') {
+ let lines = sections[i].trim().split('\n');
+ let pnpDeviceId = util.getValue(lines, 'PNPDeviceID', ':').match(/PCI\\(VEN_[0-9A-F]{4})&(DEV_[0-9A-F]{4})(?:&(SUBSYS_[0-9A-F]{8}))?(?:&(REV_[0-9A-F]{2}))?/i);
+ let subDeviceId = null;
+ let memorySize = null;
+ if (pnpDeviceId) {
+ subDeviceId = pnpDeviceId[3] || '';
+ if (subDeviceId) {
+ subDeviceId = subDeviceId.split('_')[1];
+ }
+
+ // Match PCI device identifier (there's an order of increasing generality):
+ // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-pci-devices
+
+ // PCI\VEN_v(4)&DEV_d(4)&SUBSYS_s(4)n(4)&REV_r(2)
+ if (memorySize == null && pnpDeviceId[3] && pnpDeviceId[4]) {
+ const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[3].toUpperCase() + '&' + pnpDeviceId[4].toUpperCase();
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
+ memorySize = memorySizes[deviceId];
+ }
+ }
+
+ // PCI\VEN_v(4)&DEV_d(4)&SUBSYS_s(4)n(4)
+ if (memorySize == null && pnpDeviceId[3]) {
+ const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[3].toUpperCase();
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
+ memorySize = memorySizes[deviceId];
+ }
+ }
+
+ // PCI\VEN_v(4)&DEV_d(4)&REV_r(2)
+ if (memorySize == null && pnpDeviceId[4]) {
+ const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[4].toUpperCase();
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
+ memorySize = memorySizes[deviceId];
+ }
+ }
+
+ // PCI\VEN_v(4)&DEV_d(4)
+ if (memorySize == null) {
+ const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase();
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
+ memorySize = memorySizes[deviceId];
+ }
+ }
+ }
+
+ controllers.push({
+ vendor: util.getValue(lines, 'AdapterCompatibility', ':'),
+ model: util.getValue(lines, 'name', ':'),
+ bus: util.getValue(lines, 'PNPDeviceID', ':').startsWith('PCI') ? 'PCI' : '',
+ vram: (memorySize == null ? util.toInt(util.getValue(lines, 'AdapterRAM', ':')) : memorySize) / 1024 / 1024,
+ vramDynamic: (util.getValue(lines, 'VideoMemoryType', ':') === '2'),
+ subDeviceId
+ });
+ _resolutionX = util.toInt(util.getValue(lines, 'CurrentHorizontalResolution', ':')) || _resolutionX;
+ _resolutionY = util.toInt(util.getValue(lines, 'CurrentVerticalResolution', ':')) || _resolutionY;
+ _refreshRate = util.toInt(util.getValue(lines, 'CurrentRefreshRate', ':')) || _refreshRate;
+ _pixelDepth = util.toInt(util.getValue(lines, 'CurrentBitsPerPixel', ':')) || _pixelDepth;
+ }
+ }
+ }
+ return controllers;
+ }
+
+ function parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections) {
+ let displays = [];
+ let vendor = '';
+ let model = '';
+ let deviceID = '';
+ let resolutionX = 0;
+ let resolutionY = 0;
+ if (dsections && dsections.length) {
+ let linesDisplay = dsections[0].split('\n');
+ vendor = util.getValue(linesDisplay, 'MonitorManufacturer', ':');
+ model = util.getValue(linesDisplay, 'Name', ':');
+ deviceID = util.getValue(linesDisplay, 'PNPDeviceID', ':').replace(/&amp;/g, '&').toLowerCase();
+ resolutionX = util.toInt(util.getValue(linesDisplay, 'ScreenWidth', ':'));
+ resolutionY = util.toInt(util.getValue(linesDisplay, 'ScreenHeight', ':'));
+ }
+ for (let i = 0; i < ssections.length; i++) {
+ if (ssections[i].trim() !== '') {
+ ssections[i] = 'BitsPerPixel ' + ssections[i];
+ msections[i] = 'Active ' + msections[i];
+ // tsections can be empty OR undefined on earlier versions of powershell (<=2.0)
+ // Tag connection type as UNKNOWN by default if this information is missing
+ if (tsections.length === 0 || tsections[i] === undefined) {
+ tsections[i] = 'Unknown';
+ }
+ let linesScreen = ssections[i].split('\n');
+ let linesMonitor = msections[i].split('\n');
+
+ let linesConnection = tsections[i].split('\n');
+ const bitsPerPixel = util.getValue(linesScreen, 'BitsPerPixel');
+ const bounds = util.getValue(linesScreen, 'Bounds').replace('{', '').replace('}', '').replace(/=/g, ':').split(',');
+ const primary = util.getValue(linesScreen, 'Primary');
+ const sizeX = util.getValue(linesMonitor, 'MaxHorizontalImageSize');
+ const sizeY = util.getValue(linesMonitor, 'MaxVerticalImageSize');
+ const instanceName = util.getValue(linesMonitor, 'InstanceName').toLowerCase();
+ const videoOutputTechnology = util.getValue(linesConnection, 'VideoOutputTechnology');
+ const deviceName = util.getValue(linesScreen, 'DeviceName');
+ let displayVendor = '';
+ let displayModel = '';
+ isections.forEach(element => {
+ if (element.instanceId.toLowerCase().startsWith(instanceName) && vendor.startsWith('(') && model.startsWith('PnP')) {
+ displayVendor = element.vendor;
+ displayModel = element.model;
+ }
+ });
+ displays.push({
+ vendor: instanceName.startsWith(deviceID) && displayVendor === '' ? vendor : displayVendor,
+ model: instanceName.startsWith(deviceID) && displayModel === '' ? model : displayModel,
+ deviceName,
+ main: primary.toLowerCase() === 'true',
+ builtin: videoOutputTechnology === '2147483648',
+ connection: videoOutputTechnology && videoTypes[videoOutputTechnology] ? videoTypes[videoOutputTechnology] : '',
+ resolutionX: util.toInt(util.getValue(bounds, 'Width', ':')),
+ resolutionY: util.toInt(util.getValue(bounds, 'Height', ':')),
+ sizeX: sizeX ? parseInt(sizeX, 10) : null,
+ sizeY: sizeY ? parseInt(sizeY, 10) : null,
+ pixelDepth: bitsPerPixel,
+ currentResX: util.toInt(util.getValue(bounds, 'Width', ':')),
+ currentResY: util.toInt(util.getValue(bounds, 'Height', ':')),
+ positionX: util.toInt(util.getValue(bounds, 'X', ':')),
+ positionY: util.toInt(util.getValue(bounds, 'Y', ':')),
+ });
+ }
+ }
+ if (ssections.length === 0) {
+ displays.push({
+ vendor,
+ model,
+ main: true,
+ sizeX: null,
+ sizeY: null,
+ resolutionX,
+ resolutionY,
+ pixelDepth: null,
+ currentResX: resolutionX,
+ currentResY: resolutionY,
+ positionX: 0,
+ positionY: 0
+ });
+ }
+ return displays;
+ }
+}
+
+exports.graphics = graphics;
diff --git a/MistyCore/node_modules/systeminformation/lib/index.d.ts b/MistyCore/node_modules/systeminformation/lib/index.d.ts
new file mode 100644
index 0000000..b519397
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/index.d.ts
@@ -0,0 +1,996 @@
+// Type definitions for systeminformation
+// Project: https://github.com/sebhildebrandt/systeminformation
+// Definitions by: sebhildebrandt <https://github.com/sebhildebrandt>
+
+export namespace Systeminformation {
+
+ // 1. General
+
+ interface TimeData {
+ current: number;
+ uptime: number;
+ timezone: string;
+ timezoneName: string;
+ }
+
+ // 2. System (HW)
+
+ interface RaspberryRevisionData {
+ manufacturer: string;
+ processor: string;
+ type: string;
+ revision: string;
+ }
+ interface SystemData {
+ manufacturer: string;
+ model: string;
+ version: string;
+ serial: string;
+ uuid: string;
+ sku: string;
+ virtual: boolean;
+ virtualHost?: string;
+ raspberry?: RaspberryRevisionData;
+ }
+
+ interface BiosData {
+ vendor: string;
+ version: string;
+ releaseDate: string;
+ revision: string;
+ serial?: string;
+ language?: string;
+ features?: string[];
+ }
+
+ interface BaseboardData {
+ manufacturer: string;
+ model: string;
+ version: string;
+ serial: string;
+ assetTag: string;
+ memMax: number | null;
+ memSlots: number | null;
+ }
+
+ interface ChassisData {
+ manufacturer: string;
+ model: string;
+ type: string;
+ version: string;
+ serial: string;
+ assetTag: string;
+ sku: string;
+ }
+
+ // 3. CPU, Memory, Disks, Battery, Graphics
+
+ interface CpuData {
+ manufacturer: string;
+ brand: string;
+ vendor: string;
+ family: string;
+ model: string;
+ stepping: string;
+ revision: string;
+ voltage: string;
+ speed: number;
+ speedMin: number;
+ speedMax: number;
+ governor: string;
+ cores: number;
+ physicalCores: number;
+ efficiencyCores?: number;
+ performanceCores?: number;
+ processors: number;
+ socket: string;
+ flags: string;
+ virtualization: boolean;
+ cache: CpuCacheData;
+ }
+
+ interface CpuCacheData {
+ l1d: number;
+ l1i: number;
+ l2: number;
+ l3: number;
+ }
+
+ interface CpuCurrentSpeedData {
+ min: number;
+ max: number;
+ avg: number;
+ cores: number[];
+ }
+
+ interface CpuTemperatureData {
+ main: number;
+ cores: number[];
+ max: number;
+ socket?: number[];
+ chipset?: number;
+ }
+
+ interface MemData {
+ total: number;
+ free: number;
+ used: number;
+ active: number;
+ available: number;
+ buffcache: number;
+ buffers: number;
+ cached: number;
+ slab: number;
+ swaptotal: number;
+ swapused: number;
+ swapfree: number;
+ }
+
+ interface MemLayoutData {
+ size: number;
+ bank: string;
+ type: string;
+ ecc?: boolean | null;
+ clockSpeed: number | null;
+ formFactor: string;
+ manufacturer?: string;
+ partNum: string;
+ serialNum: string;
+ voltageConfigured: number | null;
+ voltageMin: number | null;
+ voltageMax: number | null;
+ }
+
+ interface SmartData {
+ json_format_version: number[];
+ smartctl: {
+ version: number[];
+ platform_info: string;
+ build_info: string;
+ argv: string[];
+ exit_status: number;
+ };
+ device: {
+ name: string;
+ info_name: string;
+ type: string;
+ protocol: string;
+ };
+ model_family?: string;
+ model_name?: string;
+ serial_number?: string;
+ firmware_version?: string;
+ smart_status: {
+ passed: boolean;
+ };
+ trim?: {
+ supported: boolean;
+ };
+ ata_smart_attributes?: {
+ revision: number;
+ table: {
+ id: number;
+ name: string;
+ value: number;
+ worst: number;
+ thresh: number;
+ when_failed: string;
+ flags: {
+ value: number;
+ string: string;
+ prefailure: boolean;
+ updated_online: boolean;
+ performance: boolean;
+ error_rate: boolean;
+ event_count: boolean;
+ auto_keep: boolean;
+ };
+ raw: {
+ value: number;
+ string: string;
+ };
+ }[];
+ };
+ ata_smart_error_log?: {
+ summary: {
+ revision: number;
+ count: number;
+ };
+ };
+ ata_smart_self_test_log?: {
+ standard: {
+ revision: number;
+ table: {
+ type: {
+ value: number;
+ string: string;
+ };
+ status: {
+ value: number;
+ string: string;
+ passed: boolean;
+ };
+ lifetime_hours: number;
+ }[];
+ count: number;
+ error_count_total: number;
+ error_count_outdated: number;
+ };
+ };
+ nvme_pci_vendor?: {
+ id: number;
+ subsystem_id: number;
+ },
+ nvme_smart_health_information_log?: {
+ critical_warning?: number;
+ temperature?: number;
+ available_spare?: number;
+ available_spare_threshold?: number;
+ percentage_used?: number;
+ data_units_read?: number;
+ data_units_written?: number;
+ host_reads?: number;
+ host_writes?: number;
+ controller_busy_time?: number;
+ power_cycles?: number;
+ power_on_hours?: number;
+ unsafe_shutdowns?: number;
+ media_errors?: number;
+ num_err_log_entries?: number;
+ warning_temp_time?: number;
+ critical_comp_time?: number;
+ temperature_sensors?: number[];
+ },
+ user_capacity?: {
+ blocks: number;
+ bytes: number;
+ },
+ logical_block_size?: number;
+ temperature: {
+ current: number;
+ };
+ power_cycle_count: number;
+ power_on_time: {
+ hours: number;
+ };
+ }
+
+ interface DiskLayoutData {
+ device: string;
+ type: string;
+ name: string;
+ vendor: string;
+ size: number;
+ bytesPerSector: number;
+ totalCylinders: number;
+ totalHeads: number;
+ totalSectors: number;
+ totalTracks: number;
+ tracksPerCylinder: number;
+ sectorsPerTrack: number;
+ firmwareRevision: string;
+ serialNum: string;
+ interfaceType: string;
+ smartStatus: string;
+ temperature: null | number;
+ smartData?: SmartData;
+ }
+
+ interface BatteryData {
+ hasBattery: boolean;
+ cycleCount: number;
+ isCharging: boolean;
+ voltage: number;
+ designedCapacity: number;
+ maxCapacity: number;
+ currentCapacity: number;
+ capacityUnit: string;
+ percent: number;
+ timeRemaining: number;
+ acConnected: boolean;
+ type: string;
+ model: string;
+ manufacturer: string;
+ serial: string;
+ additionalBatteries?: BatteryData[];
+ }
+
+ interface GraphicsData {
+ controllers: GraphicsControllerData[];
+ displays: GraphicsDisplayData[];
+ }
+
+ interface GraphicsControllerData {
+ vendor: string;
+ vendorId?: string;
+ model: string;
+ deviceId?: string;
+ bus: string;
+ busAddress?: string;
+ vram: number | null;
+ vramDynamic: boolean;
+ external?: boolean;
+ cores?: number;
+ metalVersion?: string;
+ subDeviceId?: string;
+ driverVersion?: string;
+ name?: string;
+ pciBus?: string;
+ pciID?: string;
+ fanSpeed?: number;
+ memoryTotal?: number;
+ memoryUsed?: number;
+ memoryFree?: number;
+ utilizationGpu?: number;
+ utilizationMemory?: number;
+ temperatureGpu?: number;
+ temperatureMemory?: number;
+ powerDraw?: number;
+ powerLimit?: number;
+ clockCore?: number;
+ clockMemory?: number;
+ }
+
+ interface GraphicsDisplayData {
+ vendor: string;
+ vendorId: string | null;
+ model: string;
+ productionYear: number | null;
+ serial: string | null;
+ deviceName: string | null;
+ displayId: string | null;
+ main: boolean;
+ builtin: boolean;
+ connection: string | null;
+ sizeX: number | null;
+ sizeY: number | null;
+ pixelDepth: number | null;
+ resolutionX: number | null;
+ resolutionY: number | null;
+ currentResX: number | null;
+ currentResY: number | null;
+ positionX: number;
+ positionY: number;
+ currentRefreshRate: number | null;
+ }
+
+ // 4. Operating System
+
+ interface OsData {
+ platform: string;
+ distro: string;
+ release: string;
+ codename: string;
+ kernel: string;
+ arch: string;
+ hostname: string;
+ fqdn: string;
+ codepage: string;
+ logofile: string;
+ serial: string;
+ build: string;
+ servicepack: string;
+ uefi: boolean;
+ hypervizor?: boolean;
+ remoteSession?: boolean;
+ hypervisor?: boolean;
+ }
+
+ interface UuidData {
+ os: string;
+ hardware: string;
+ macs: string[];
+ }
+
+ interface VersionData {
+ kernel?: string;
+ openssl?: string;
+ systemOpenssl?: string;
+ systemOpensslLib?: string;
+ node?: string;
+ v8?: string;
+ npm?: string;
+ yarn?: string;
+ pm2?: string;
+ gulp?: string;
+ grunt?: string;
+ git?: string;
+ tsc?: string;
+ mysql?: string;
+ redis?: string;
+ mongodb?: string;
+ nginx?: string;
+ php?: string;
+ docker?: string;
+ postfix?: string;
+ postgresql?: string;
+ perl?: string;
+ python?: string;
+ python3?: string;
+ pip?: string;
+ pip3?: string;
+ java?: string;
+ gcc?: string;
+ virtualbox?: string;
+ dotnet?: string;
+ }
+
+ interface UserData {
+ user: string;
+ tty: string;
+ date: string;
+ time: string;
+ ip: string;
+ command: string;
+ }
+
+ // 5. File System
+
+ interface FsSizeData {
+ fs: string;
+ type: string;
+ size: number;
+ used: number;
+ available: number;
+ use: number;
+ mount: string;
+ }
+
+ interface FsOpenFilesData {
+ max: number;
+ allocated: number;
+ available: number;
+ }
+
+ interface BlockDevicesData {
+ name: string;
+ identifier: string;
+ type: string;
+ fsType: string;
+ mount: string;
+ size: number;
+ physical: string;
+ uuid: string;
+ label: string;
+ model: string;
+ serial: string;
+ removable: boolean;
+ protocol: string;
+ }
+
+ interface FsStatsData {
+ rx: number;
+ wx: number;
+ tx: number;
+ rx_sec: number | null;
+ wx_sec: number | null;
+ tx_sec: number | null;
+ ms: number;
+ }
+
+ interface DisksIoData {
+ rIO: number;
+ wIO: number;
+ tIO: number;
+ rIO_sec: number | null;
+ wIO_sec: number | null;
+ tIO_sec: number | null;
+ rWaitTime: number;
+ wWaitTime: number;
+ tWaitTime: number;
+ rWaitPercent: number | null;
+ wWaitPercent: number | null;
+ tWaitPercent: number | null;
+ ms: number;
+ }
+
+ // 6. Network related functions
+
+ interface NetworkInterfacesData {
+ iface: string;
+ ifaceName: string;
+ ip4: string;
+ ip4subnet: string;
+ ip6: string;
+ ip6subnet: string;
+ mac: string;
+ internal: boolean;
+ virtual: boolean;
+ operstate: string;
+ type: string;
+ duplex: string;
+ mtu: number;
+ speed: number;
+ dhcp: boolean;
+ dnsSuffix: string;
+ ieee8021xAuth: string;
+ ieee8021xState: string;
+ carrierChanges: number;
+ }
+
+ interface NetworkStatsData {
+ iface: string;
+ operstate: string;
+ rx_bytes: number;
+ rx_dropped: number;
+ rx_errors: number;
+ tx_bytes: number;
+ tx_dropped: number;
+ tx_errors: number;
+ rx_sec: number;
+ tx_sec: number;
+ ms: number;
+ }
+
+ interface NetworkConnectionsData {
+ protocol: string;
+ localAddress: string;
+ localPort: string;
+ peerAddress: string;
+ peerPort: string;
+ state: string;
+ pid: number;
+ process: string;
+ }
+
+ interface InetChecksiteData {
+ url: string;
+ ok: boolean;
+ status: number;
+ ms: number;
+ }
+
+ interface WifiNetworkData {
+ ssid: string;
+ bssid: string;
+ mode: string;
+ channel: number;
+ frequency: number;
+ signalLevel: number;
+ quality: number;
+ security: string[];
+ wpaFlags: string[];
+ rsnFlags: string[];
+ }
+
+ interface WifiInterfaceData {
+ id: string;
+ iface: string;
+ model: string;
+ vendor: string;
+ mac: string;
+ }
+
+ interface WifiConnectionData {
+ id: string;
+ iface: string;
+ model: string;
+ ssid: string;
+ bssid: string;
+ channel: number;
+ type: string;
+ security: string;
+ frequency: number;
+ signalLevel: number;
+ txRate: number;
+ }
+
+ // 7. Current Load, Processes & Services
+
+ interface CurrentLoadData {
+ avgLoad: number;
+ currentLoad: number;
+ currentLoadUser: number;
+ currentLoadSystem: number;
+ currentLoadNice: number;
+ currentLoadIdle: number;
+ currentLoadIrq: number;
+ rawCurrentLoad: number;
+ rawCurrentLoadUser: number;
+ rawCurrentLoadSystem: number;
+ rawCurrentLoadNice: number;
+ rawCurrentLoadIdle: number;
+ rawCurrentLoadIrq: number;
+ cpus: CurrentLoadCpuData[];
+ }
+
+ interface CurrentLoadCpuData {
+ load: number;
+ loadUser: number;
+ loadSystem: number;
+ loadNice: number;
+ loadIdle: number;
+ loadIrq: number;
+ rawLoad: number;
+ rawLoadUser: number;
+ rawLoadSystem: number;
+ rawLoadNice: number;
+ rawLoadIdle: number;
+ rawLoadIrq: number;
+ }
+
+ interface ProcessesData {
+ all: number;
+ running: number;
+ blocked: number;
+ sleeping: number;
+ unknown: number;
+ list: ProcessesProcessData[];
+ }
+
+ interface ProcessesProcessData {
+ pid: number;
+ parentPid: number;
+ name: string;
+ cpu: number;
+ cpuu: number;
+ cpus: number;
+ mem: number;
+ priority: number;
+ memVsz: number;
+ memRss: number;
+ nice: number;
+ started: string;
+ state: string;
+ tty: string;
+ user: string;
+ command: string;
+ params: string;
+ path: string;
+ }
+
+ interface ProcessesProcessLoadData {
+ proc: string;
+ pid: number;
+ pids: number[];
+ cpu: number;
+ mem: number;
+ }
+
+ interface ServicesData {
+ name: string;
+ running: boolean;
+ startmode: string;
+ pids: number[];
+ cpu: number;
+ mem: number;
+ }
+
+ // 8. Docker
+
+ interface DockerInfoData {
+ id: string;
+ containers: number;
+ containersRunning: number;
+ containersPaused: number;
+ containersStopped: number;
+ images: number;
+ driver: string;
+ memoryLimit: boolean;
+ swapLimit: boolean;
+ kernelMemory: boolean;
+ cpuCfsPeriod: boolean;
+ cpuCfsQuota: boolean;
+ cpuShares: boolean;
+ cpuSet: boolean;
+ ipv4Forwarding: boolean;
+ bridgeNfIptables: boolean;
+ bridgeNfIp6tables: boolean;
+ debug: boolean;
+ nfd: number;
+ oomKillDisable: boolean;
+ ngoroutines: number;
+ systemTime: string;
+ loggingDriver: string;
+ cgroupDriver: string;
+ nEventsListener: number;
+ kernelVersion: string;
+ operatingSystem: string;
+ osType: string;
+ architecture: string;
+ ncpu: number;
+ memTotal: number;
+ dockerRootDir: string;
+ httpProxy: string;
+ httpsProxy: string;
+ noProxy: string;
+ name: string;
+ labels: string[];
+ experimentalBuild: boolean;
+ serverVersion: string;
+ clusterStore: string;
+ clusterAdvertise: string;
+ defaultRuntime: string;
+ liveRestoreEnabled: boolean;
+ isolation: string;
+ initBinary: string;
+ productLicense: string;
+ }
+
+ interface DockerImageData {
+ id: string;
+ container: string;
+ comment: string;
+ os: string;
+ architecture: string;
+ parent: string;
+ dockerVersion: string;
+ size: number;
+ sharedSize: number;
+ virtualSize: number;
+ author: string;
+ created: number;
+ containerConfig: any;
+ graphDriver: any;
+ repoDigests: any;
+ repoTags: any;
+ config: any;
+ rootFS: any;
+ }
+
+ interface DockerContainerData {
+ id: string;
+ name: string;
+ image: string;
+ imageID: string;
+ command: string;
+ created: number;
+ started: number;
+ finished: number;
+ createdAt: string;
+ startedAt: string;
+ finishedAt: string;
+ state: string;
+ restartCount: number;
+ platform: string;
+ driver: string;
+ ports: number[];
+ mounts: DockerContainerMountData[];
+ }
+
+ interface DockerContainerMountData {
+ Type: string;
+ Source: string;
+ Destination: string;
+ Mode: string;
+ RW: boolean;
+ Propagation: string;
+ }
+
+ interface DockerContainerStatsData {
+ id: string;
+ memUsage: number;
+ memLimit: number;
+ memPercent: number;
+ cpuPercent: number;
+ pids: number;
+ netIO: {
+ rx: number;
+ wx: number;
+ };
+ blockIO: {
+ r: number;
+ w: number;
+ };
+ restartCount: number;
+ cpuStats: any;
+ precpuStats: any;
+ memoryStats: any;
+ networks: any;
+ }
+
+ interface DockerContainerProcessData {
+ pidHost: string;
+ ppid: string;
+ pgid: string;
+ user: string;
+ ruser: string;
+ group: string;
+ rgroup: string;
+ stat: string;
+ time: string;
+ elapsed: string;
+ nice: string;
+ rss: string;
+ vsz: string;
+ command: string;
+ }
+
+ interface DockerVolumeData {
+ name: string;
+ driver: string;
+ labels: any;
+ mountpoint: string;
+ options: any;
+ scope: string;
+ created: number;
+ }
+
+ // 9. Virtual Box
+
+ interface VboxInfoData {
+ id: string;
+ name: string;
+ running: boolean;
+ started: string;
+ runningSince: number;
+ stopped: string;
+ stoppedSince: number;
+ guestOS: string;
+ hardwareUUID: string;
+ memory: number;
+ vram: number;
+ cpus: number;
+ cpuExepCap: string;
+ cpuProfile: string;
+ chipset: string;
+ firmware: string;
+ pageFusion: boolean;
+ configFile: string;
+ snapshotFolder: string;
+ logFolder: string;
+ hpet: boolean;
+ pae: boolean;
+ longMode: boolean;
+ tripleFaultReset: boolean;
+ apic: boolean;
+ x2Apic: boolean;
+ acpi: boolean;
+ ioApic: boolean;
+ biosApicMode: string;
+ bootMenuMode: string;
+ bootDevice1: string;
+ bootDevice2: string;
+ bootDevice3: string;
+ bootDevice4: string;
+ timeOffset: string;
+ rtc: string;
+ }
+
+ interface PrinterData {
+ id: number;
+ name: string;
+ model: string;
+ uri: string;
+ uuid: string;
+ local: boolean;
+ status: string;
+ default: boolean;
+ shared: boolean;
+ }
+
+ interface UsbData {
+ id: number | string;
+ bus: number;
+ deviceId: number;
+ name: string;
+ type: string;
+ removable: boolean;
+ vendor: string;
+ manufacturer: string;
+ maxPower: string;
+ serialNumber: string;
+ }
+
+ interface AudioData {
+ id: number | string;
+ name: string;
+ manufacturer: string;
+ default: boolean;
+ revision: string;
+ driver: string;
+ channel: string;
+ in: boolean;
+ out: boolean;
+ type: string;
+ status: string;
+ }
+
+ interface BluetoothDeviceData {
+ device: string;
+ name: string;
+ macDevice: string;
+ macHost: string;
+ batteryPercent: number;
+ manufacturer: string;
+ type: string;
+ connected: boolean;
+ }
+
+ // 10. "Get All at once" - functions
+
+ interface StaticData {
+ version: string;
+ system: SystemData;
+ bios: BiosData;
+ baseboard: BaseboardData;
+ chassis: ChassisData;
+ os: OsData;
+ uuid: UuidData;
+ versions: VersionData;
+ cpu: CpuData;
+ graphics: GraphicsData;
+ net: NetworkInterfacesData[];
+ memLayout: MemLayoutData[];
+ diskLayout: DiskLayoutData[];
+ }
+}
+
+export function version(): string;
+export function system(cb?: (data: Systeminformation.SystemData) => any): Promise<Systeminformation.SystemData>;
+export function bios(cb?: (data: Systeminformation.BiosData) => any): Promise<Systeminformation.BiosData>;
+export function baseboard(cb?: (data: Systeminformation.BaseboardData) => any): Promise<Systeminformation.BaseboardData>;
+export function chassis(cb?: (data: Systeminformation.ChassisData) => any): Promise<Systeminformation.ChassisData>;
+
+export function time(): Systeminformation.TimeData;
+export function osInfo(cb?: (data: Systeminformation.OsData) => any): Promise<Systeminformation.OsData>;
+export function versions(apps?: string, cb?: (data: Systeminformation.VersionData) => any): Promise<Systeminformation.VersionData>;
+export function shell(cb?: (data: string) => any): Promise<string>;
+export function uuid(cb?: (data: Systeminformation.UuidData) => any): Promise<Systeminformation.UuidData>;
+
+export function cpu(cb?: (data: Systeminformation.CpuData) => any): Promise<Systeminformation.CpuData>;
+export function cpuFlags(cb?: (data: string) => any): Promise<string>;
+export function cpuCache(cb?: (data: Systeminformation.CpuCacheData) => any): Promise<Systeminformation.CpuCacheData>;
+export function cpuCurrentSpeed(cb?: (data: Systeminformation.CpuCurrentSpeedData) => any): Promise<Systeminformation.CpuCurrentSpeedData>;
+export function cpuTemperature(cb?: (data: Systeminformation.CpuTemperatureData) => any): Promise<Systeminformation.CpuTemperatureData>;
+export function currentLoad(cb?: (data: Systeminformation.CurrentLoadData) => any): Promise<Systeminformation.CurrentLoadData>;
+export function fullLoad(cb?: (data: number) => any): Promise<number>;
+
+export function mem(cb?: (data: Systeminformation.MemData) => any): Promise<Systeminformation.MemData>;
+export function memLayout(cb?: (data: Systeminformation.MemLayoutData[]) => any): Promise<Systeminformation.MemLayoutData[]>;
+
+export function battery(cb?: (data: Systeminformation.BatteryData) => any): Promise<Systeminformation.BatteryData>;
+export function graphics(cb?: (data: Systeminformation.GraphicsData) => any): Promise<Systeminformation.GraphicsData>;
+
+export function fsSize(cb?: (data: Systeminformation.FsSizeData[]) => any): Promise<Systeminformation.FsSizeData[]>;
+export function fsOpenFiles(cb?: (data: Systeminformation.FsOpenFilesData[]) => any): Promise<Systeminformation.FsOpenFilesData[]>;
+export function blockDevices(cb?: (data: Systeminformation.BlockDevicesData[]) => any): Promise<Systeminformation.BlockDevicesData[]>;
+export function fsStats(cb?: (data: Systeminformation.FsStatsData) => any): Promise<Systeminformation.FsStatsData>;
+export function disksIO(cb?: (data: Systeminformation.DisksIoData) => any): Promise<Systeminformation.DisksIoData>;
+export function diskLayout(cb?: (data: Systeminformation.DiskLayoutData[]) => any): Promise<Systeminformation.DiskLayoutData[]>;
+
+export function networkInterfaceDefault(cb?: (data: string) => any): Promise<string>;
+export function networkGatewayDefault(cb?: (data: string) => any): Promise<string>;
+export function networkInterfaces(cb?: (data: Systeminformation.NetworkInterfacesData[]) => any): Promise<Systeminformation.NetworkInterfacesData[]>;
+
+export function networkStats(ifaces?: string, cb?: (data: Systeminformation.NetworkStatsData[]) => any): Promise<Systeminformation.NetworkStatsData[]>;
+export function networkConnections(cb?: (data: Systeminformation.NetworkConnectionsData[]) => any): Promise<Systeminformation.NetworkConnectionsData[]>;
+export function inetChecksite(url: string, cb?: (data: Systeminformation.InetChecksiteData) => any): Promise<Systeminformation.InetChecksiteData>;
+export function inetLatency(host?: string, cb?: (data: number) => any): Promise<number>;
+
+export function wifiNetworks(cb?: (data: Systeminformation.WifiNetworkData[]) => any): Promise<Systeminformation.WifiNetworkData[]>;
+export function wifiInterfaces(cb?: (data: Systeminformation.WifiInterfaceData[]) => any): Promise<Systeminformation.WifiInterfaceData[]>;
+export function wifiConnections(cb?: (data: Systeminformation.WifiConnectionData[]) => any): Promise<Systeminformation.WifiConnectionData[]>;
+
+export function users(cb?: (data: Systeminformation.UserData[]) => any): Promise<Systeminformation.UserData[]>;
+
+export function processes(cb?: (data: Systeminformation.ProcessesData) => any): Promise<Systeminformation.ProcessesData>;
+export function processLoad(processNames: string, cb?: (data: Systeminformation.ProcessesProcessLoadData[]) => any): Promise<Systeminformation.ProcessesProcessLoadData[]>;
+export function services(serviceName: string, cb?: (data: Systeminformation.ServicesData[]) => any): Promise<Systeminformation.ServicesData[]>;
+
+export function dockerInfo(cb?: (data: Systeminformation.DockerInfoData) => any): Promise<Systeminformation.DockerInfoData>;
+export function dockerImages(all?: boolean, cb?: (data: Systeminformation.DockerImageData[]) => any): Promise<Systeminformation.DockerImageData[]>;
+export function dockerContainers(all?: boolean, cb?: (data: Systeminformation.DockerContainerData[]) => any): Promise<Systeminformation.DockerContainerData[]>;
+export function dockerContainerStats(id?: string, cb?: (data: Systeminformation.DockerContainerStatsData[]) => any): Promise<Systeminformation.DockerContainerStatsData[]>;
+export function dockerContainerProcesses(id?: string, cb?: (data: any) => any): Promise<Systeminformation.DockerContainerProcessData[]>;
+export function dockerVolumes(cb?: (data: Systeminformation.DockerVolumeData[]) => any): Promise<Systeminformation.DockerVolumeData[]>;
+export function dockerAll(cb?: (data: any) => any): Promise<any>;
+
+export function vboxInfo(cb?: (data: Systeminformation.VboxInfoData[]) => any): Promise<Systeminformation.VboxInfoData[]>;
+
+export function printer(cb?: (data: Systeminformation.PrinterData[]) => any): Promise<Systeminformation.PrinterData[]>;
+
+export function usb(cb?: (data: Systeminformation.UsbData[]) => any): Promise<Systeminformation.UsbData[]>;
+
+export function audio(cb?: (data: Systeminformation.AudioData[]) => any): Promise<Systeminformation.AudioData[]>;
+
+export function bluetoothDevices(cb?: (data: Systeminformation.BluetoothDeviceData[]) => any): Promise<Systeminformation.BluetoothDeviceData[]>;
+
+export function getStaticData(cb?: (data: Systeminformation.StaticData) => any): Promise<Systeminformation.StaticData>;
+export function getDynamicData(srv?: string, iface?: string, cb?: (data: any) => any): Promise<any>;
+export function getAllData(srv?: string, iface?: string, cb?: (data: any) => any): Promise<any>;
+export function get(valuesObject: any, cb?: (data: any) => any): Promise<any>;
+export function observe(valuesObject: any, interval: number, cb?: (data: any) => any): number;
+
+export function powerShellStart(): void;
+export function powerShellRelease(): void;
diff --git a/MistyCore/node_modules/systeminformation/lib/index.js b/MistyCore/node_modules/systeminformation/lib/index.js
new file mode 100644
index 0000000..1dd5bb2
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/index.js
@@ -0,0 +1,504 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// index.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// Contributors: Guillaume Legrain (https://github.com/glegrain)
+// Riccardo Novaglia (https://github.com/richy24)
+// Quentin Busuttil (https://github.com/Buzut)
+// Lapsio (https://github.com/lapsio)
+// csy (https://github.com/csy1983)
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+
+// ----------------------------------------------------------------------------------
+// Dependencies
+// ----------------------------------------------------------------------------------
+
+const lib_version = require('../package.json').version;
+const util = require('./util');
+const system = require('./system');
+const osInfo = require('./osinfo');
+const cpu = require('./cpu');
+const memory = require('./memory');
+const battery = require('./battery');
+const graphics = require('./graphics');
+const filesystem = require('./filesystem');
+const network = require('./network');
+const wifi = require('./wifi');
+const processes = require('./processes');
+const users = require('./users');
+const internet = require('./internet');
+const docker = require('./docker');
+const vbox = require('./virtualbox');
+const printer = require('./printer');
+const usb = require('./usb');
+const audio = require('./audio');
+const bluetooth = require('./bluetooth');
+
+let _platform = process.platform;
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+// ----------------------------------------------------------------------------------
+// init
+// ----------------------------------------------------------------------------------
+
+if (_windows) {
+ util.getCodepage();
+}
+
+// ----------------------------------------------------------------------------------
+// General
+// ----------------------------------------------------------------------------------
+
+function version() {
+ return lib_version;
+}
+
+// ----------------------------------------------------------------------------------
+// Get static and dynamic data (all)
+// ----------------------------------------------------------------------------------
+
+// --------------------------
+// get static data - they should not change until restarted
+
+function getStaticData(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let data = {};
+
+ data.version = version();
+
+ Promise.all([
+ system.system(),
+ system.bios(),
+ system.baseboard(),
+ system.chassis(),
+ osInfo.osInfo(),
+ osInfo.uuid(),
+ osInfo.versions(),
+ cpu.cpu(),
+ cpu.cpuFlags(),
+ graphics.graphics(),
+ network.networkInterfaces(),
+ memory.memLayout(),
+ filesystem.diskLayout()
+ ]).then((res) => {
+ data.system = res[0];
+ data.bios = res[1];
+ data.baseboard = res[2];
+ data.chassis = res[3];
+ data.os = res[4];
+ data.uuid = res[5];
+ data.versions = res[6];
+ data.cpu = res[7];
+ data.cpu.flags = res[8];
+ data.graphics = res[9];
+ data.net = res[10];
+ data.memLayout = res[11];
+ data.diskLayout = res[12];
+ if (callback) { callback(data); }
+ resolve(data);
+ });
+ });
+ });
+}
+
+
+// --------------------------
+// get all dynamic data - e.g. for monitoring agents
+// may take some seconds to get all data
+// --------------------------
+// 2 additional parameters needed
+// - srv: comma separated list of services to monitor e.g. "mysql, apache, postgresql"
+// - iface: define network interface for which you like to monitor network speed e.g. "eth0"
+
+function getDynamicData(srv, iface, callback) {
+
+ if (util.isFunction(iface)) {
+ callback = iface;
+ iface = '';
+ }
+ if (util.isFunction(srv)) {
+ callback = srv;
+ srv = '';
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ iface = iface || network.getDefaultNetworkInterface();
+ srv = srv || '';
+
+ // use closure to track ƒ completion
+ let functionProcessed = (function () {
+ let totalFunctions = 15;
+ if (_windows) { totalFunctions = 13; }
+ if (_freebsd || _openbsd || _netbsd) { totalFunctions = 11; }
+ if (_sunos) { totalFunctions = 6; }
+
+ return function () {
+ if (--totalFunctions === 0) {
+ if (callback) {
+ callback(data);
+ }
+ resolve(data);
+ }
+ };
+ })();
+
+ let data = {};
+
+ // get time
+ data.time = osInfo.time();
+
+ /**
+ * @namespace
+ * @property {Object} versions
+ * @property {string} versions.node
+ * @property {string} versions.v8
+ */
+ data.node = process.versions.node;
+ data.v8 = process.versions.v8;
+
+ cpu.cpuCurrentSpeed().then((res) => {
+ data.cpuCurrentSpeed = res;
+ functionProcessed();
+ });
+
+ users.users().then((res) => {
+ data.users = res;
+ functionProcessed();
+ });
+
+ processes.processes().then((res) => {
+ data.processes = res;
+ functionProcessed();
+ });
+
+ cpu.currentLoad().then((res) => {
+ data.currentLoad = res;
+ functionProcessed();
+ });
+
+ if (!_sunos) {
+ cpu.cpuTemperature().then((res) => {
+ data.temp = res;
+ functionProcessed();
+ });
+ }
+
+ if (!_openbsd && !_freebsd && !_netbsd && !_sunos) {
+ network.networkStats(iface).then((res) => {
+ data.networkStats = res;
+ functionProcessed();
+ });
+ }
+
+ if (!_sunos) {
+ network.networkConnections().then((res) => {
+ data.networkConnections = res;
+ functionProcessed();
+ });
+ }
+
+ memory.mem().then((res) => {
+ data.mem = res;
+ functionProcessed();
+ });
+
+ if (!_sunos) {
+ battery().then((res) => {
+ data.battery = res;
+ functionProcessed();
+ });
+ }
+
+ if (!_sunos) {
+ processes.services(srv).then((res) => {
+ data.services = res;
+ functionProcessed();
+ });
+ }
+
+ if (!_sunos) {
+ filesystem.fsSize().then((res) => {
+ data.fsSize = res;
+ functionProcessed();
+ });
+ }
+
+ if (!_windows && !_openbsd && !_freebsd && !_netbsd && !_sunos) {
+ filesystem.fsStats().then((res) => {
+ data.fsStats = res;
+ functionProcessed();
+ });
+ }
+
+ if (!_windows && !_openbsd && !_freebsd && !_netbsd && !_sunos) {
+ filesystem.disksIO().then((res) => {
+ data.disksIO = res;
+ functionProcessed();
+ });
+ }
+
+ if (!_openbsd && !_freebsd && !_netbsd && !_sunos) {
+ wifi.wifiNetworks().then((res) => {
+ data.wifiNetworks = res;
+ functionProcessed();
+ });
+ }
+
+ internet.inetLatency().then((res) => {
+ data.inetLatency = res;
+ functionProcessed();
+ });
+ });
+ });
+}
+
+// --------------------------
+// get all data at once
+// --------------------------
+// 2 additional parameters needed
+// - srv: comma separated list of services to monitor e.g. "mysql, apache, postgresql"
+// - iface: define network interface for which you like to monitor network speed e.g. "eth0"
+
+function getAllData(srv, iface, callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let data = {};
+
+ if (iface && util.isFunction(iface) && !callback) {
+ callback = iface;
+ iface = '';
+ }
+
+ if (srv && util.isFunction(srv) && !iface && !callback) {
+ callback = srv;
+ srv = '';
+ iface = '';
+ }
+
+ getStaticData().then((res) => {
+ data = res;
+ getDynamicData(srv, iface).then((res) => {
+ for (let key in res) {
+ if ({}.hasOwnProperty.call(res, key)) {
+ data[key] = res[key];
+ }
+ }
+ if (callback) { callback(data); }
+ resolve(data);
+ });
+ });
+ });
+ });
+}
+
+function get(valueObject, callback) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ const allPromises = Object.keys(valueObject)
+ .filter(func => ({}.hasOwnProperty.call(exports, func)))
+ .map(func => {
+ const params = valueObject[func].substring(valueObject[func].lastIndexOf('(') + 1, valueObject[func].lastIndexOf(')'));
+ let funcWithoutParams = func.indexOf(')') >= 0 ? func.split(')')[1].trim() : func;
+ funcWithoutParams = func.indexOf('|') >= 0 ? func.split('|')[0].trim() : funcWithoutParams;
+ if (params) {
+ return exports[funcWithoutParams](params);
+ } else {
+ return exports[funcWithoutParams]('');
+ }
+ });
+
+ Promise.all(allPromises).then((data) => {
+ const result = {};
+ let i = 0;
+ for (let key in valueObject) {
+ if ({}.hasOwnProperty.call(valueObject, key) && {}.hasOwnProperty.call(exports, key) && data.length > i) {
+ if (valueObject[key] === '*' || valueObject[key] === 'all') {
+ result[key] = data[i];
+ } else {
+ let keys = valueObject[key];
+ let filter = '';
+ let filterParts = [];
+ // remove params
+ if (keys.indexOf(')') >= 0) {
+ keys = keys.split(')')[1].trim();
+ }
+ // extract filter and remove it from keys
+ if (keys.indexOf('|') >= 0) {
+ filter = keys.split('|')[1].trim();
+ filterParts = filter.split(':');
+
+ keys = keys.split('|')[0].trim();
+ }
+ keys = keys.replace(/,/g, ' ').replace(/ +/g, ' ').split(' ');
+ if (data[i]) {
+ if (Array.isArray(data[i])) {
+ // result is in an array, go through all elements of array and pick only the right ones
+ const partialArray = [];
+ data[i].forEach(element => {
+ let partialRes = {};
+ if (keys.length === 1 && (keys[0] === '*' || keys[0] === 'all')) {
+ partialRes = element;
+ } else {
+ keys.forEach(k => {
+ if ({}.hasOwnProperty.call(element, k)) {
+ partialRes[k] = element[k];
+ }
+ });
+ }
+ // if there is a filter, then just take those elements
+ if (filter && filterParts.length === 2) {
+ if ({}.hasOwnProperty.call(partialRes, filterParts[0].trim())) {
+ const val = partialRes[filterParts[0].trim()];
+ if (typeof val == 'number') {
+ if (val === parseFloat(filterParts[1].trim())) {
+ partialArray.push(partialRes);
+ }
+ } else if (typeof val == 'string') {
+ if (val.toLowerCase() === filterParts[1].trim().toLowerCase()) {
+ partialArray.push(partialRes);
+ }
+ }
+ }
+ } else {
+ partialArray.push(partialRes);
+ }
+
+ });
+ result[key] = partialArray;
+ } else {
+ const partialRes = {};
+ keys.forEach(k => {
+ if ({}.hasOwnProperty.call(data[i], k)) {
+ partialRes[k] = data[i][k];
+ }
+ });
+ result[key] = partialRes;
+ }
+ } else {
+ result[key] = {};
+ }
+ }
+ i++;
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+ });
+}
+
+function observe(valueObject, interval, callback) {
+ let _data = null;
+
+ const result = setInterval(() => {
+ get(valueObject).then((data) => {
+ if (JSON.stringify(_data) !== JSON.stringify(data)) {
+ _data = Object.assign({}, data);
+ callback(data);
+ }
+ });
+ }, interval);
+ return result;
+}
+
+// ----------------------------------------------------------------------------------
+// export all libs
+// ----------------------------------------------------------------------------------
+
+exports.version = version;
+exports.system = system.system;
+exports.bios = system.bios;
+exports.baseboard = system.baseboard;
+exports.chassis = system.chassis;
+
+exports.time = osInfo.time;
+exports.osInfo = osInfo.osInfo;
+exports.versions = osInfo.versions;
+exports.shell = osInfo.shell;
+exports.uuid = osInfo.uuid;
+
+exports.cpu = cpu.cpu;
+exports.cpuFlags = cpu.cpuFlags;
+exports.cpuCache = cpu.cpuCache;
+exports.cpuCurrentSpeed = cpu.cpuCurrentSpeed;
+exports.cpuTemperature = cpu.cpuTemperature;
+exports.currentLoad = cpu.currentLoad;
+exports.fullLoad = cpu.fullLoad;
+
+exports.mem = memory.mem;
+exports.memLayout = memory.memLayout;
+
+exports.battery = battery;
+
+exports.graphics = graphics.graphics;
+
+exports.fsSize = filesystem.fsSize;
+exports.fsOpenFiles = filesystem.fsOpenFiles;
+exports.blockDevices = filesystem.blockDevices;
+exports.fsStats = filesystem.fsStats;
+exports.disksIO = filesystem.disksIO;
+exports.diskLayout = filesystem.diskLayout;
+
+exports.networkInterfaceDefault = network.networkInterfaceDefault;
+exports.networkGatewayDefault = network.networkGatewayDefault;
+exports.networkInterfaces = network.networkInterfaces;
+exports.networkStats = network.networkStats;
+exports.networkConnections = network.networkConnections;
+
+exports.wifiNetworks = wifi.wifiNetworks;
+exports.wifiInterfaces = wifi.wifiInterfaces;
+exports.wifiConnections = wifi.wifiConnections;
+
+exports.services = processes.services;
+exports.processes = processes.processes;
+exports.processLoad = processes.processLoad;
+
+exports.users = users.users;
+
+exports.inetChecksite = internet.inetChecksite;
+exports.inetLatency = internet.inetLatency;
+
+exports.dockerInfo = docker.dockerInfo;
+exports.dockerImages = docker.dockerImages;
+exports.dockerContainers = docker.dockerContainers;
+exports.dockerContainerStats = docker.dockerContainerStats;
+exports.dockerContainerProcesses = docker.dockerContainerProcesses;
+exports.dockerVolumes = docker.dockerVolumes;
+exports.dockerAll = docker.dockerAll;
+
+exports.vboxInfo = vbox.vboxInfo;
+
+exports.printer = printer.printer;
+
+exports.usb = usb.usb;
+
+exports.audio = audio.audio;
+exports.bluetoothDevices = bluetooth.bluetoothDevices;
+
+exports.getStaticData = getStaticData;
+exports.getDynamicData = getDynamicData;
+exports.getAllData = getAllData;
+exports.get = get;
+exports.observe = observe;
+
+exports.powerShellStart = util.powerShellStart;
+exports.powerShellRelease = util.powerShellRelease;
diff --git a/MistyCore/node_modules/systeminformation/lib/internet.js b/MistyCore/node_modules/systeminformation/lib/internet.js
new file mode 100644
index 0000000..71f0878
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/internet.js
@@ -0,0 +1,240 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// internet.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 12. Internet
+// ----------------------------------------------------------------------------------
+
+// const exec = require('child_process').exec;
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+// --------------------------
+// check if external site is available
+
+function inetChecksite(url, callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = {
+ url: url,
+ ok: false,
+ status: 404,
+ ms: null
+ };
+ if (typeof url !== 'string') {
+ if (callback) { callback(result); }
+ return resolve(result);
+ }
+ let urlSanitized = '';
+ const s = util.sanitizeShellString(url, true);
+ for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
+ if (!(s[i] === undefined)) {
+ s[i].__proto__.toLowerCase = util.stringToLower;
+ const sl = s[i].toLowerCase();
+ if (sl && sl[0] && !sl[1] && sl[0].length === 1) {
+ urlSanitized = urlSanitized + sl[0];
+ }
+ }
+ }
+ result.url = urlSanitized;
+ try {
+ if (urlSanitized && !util.isPrototypePolluted()) {
+ urlSanitized.__proto__.startsWith = util.stringStartWith;
+ if (urlSanitized.startsWith('file:') || urlSanitized.startsWith('gopher:') || urlSanitized.startsWith('telnet:') || urlSanitized.startsWith('mailto:') || urlSanitized.startsWith('news:') || urlSanitized.startsWith('nntp:')) {
+ if (callback) { callback(result); }
+ return resolve(result);
+ }
+ let t = Date.now();
+ if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) {
+ let args = ['-I', '--connect-timeout', '5', '-m', '5'];
+ args.push(urlSanitized);
+ let cmd = 'curl';
+ util.execSafe(cmd, args).then((stdout) => {
+ const lines = stdout.split('\n');
+ let statusCode = lines[0] && lines[0].indexOf(' ') >= 0 ? parseInt(lines[0].split(' ')[1], 10) : 404;
+ result.status = statusCode || 404;
+ result.ok = (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304);
+ result.ms = (result.ok ? Date.now() - t : null);
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_windows) { // if this is stable, this can be used for all OS types
+ const http = (urlSanitized.startsWith('https:') ? require('https') : require('http'));
+ try {
+ http.get(urlSanitized, (res) => {
+ const statusCode = res.statusCode;
+
+ result.status = statusCode || 404;
+ result.ok = (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304);
+
+ if (statusCode !== 200) {
+ res.resume();
+ result.ms = (result.ok ? Date.now() - t : null);
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ res.on('data', () => { });
+ res.on('end', () => {
+ result.ms = (result.ok ? Date.now() - t : null);
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ }).on('error', () => {
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (err) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } catch (err) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.inetChecksite = inetChecksite;
+
+// --------------------------
+// check inet latency
+
+function inetLatency(host, callback) {
+
+ // fallback - if only callback is given
+ if (util.isFunction(host) && !callback) {
+ callback = host;
+ host = '';
+ }
+
+ host = host || '8.8.8.8';
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (typeof host !== 'string') {
+ if (callback) { callback(null); }
+ return resolve(null);
+ }
+ let hostSanitized = '';
+ const s = (util.isPrototypePolluted() ? '8.8.8.8' : util.sanitizeShellString(host, true)).trim();
+ for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
+ if (!(s[i] === undefined)) {
+ s[i].__proto__.toLowerCase = util.stringToLower;
+ const sl = s[i].toLowerCase();
+ if (sl && sl[0] && !sl[1]) {
+ hostSanitized = hostSanitized + sl[0];
+ }
+ }
+ }
+ hostSanitized.__proto__.startsWith = util.stringStartWith;
+ if (hostSanitized.startsWith('file:') || hostSanitized.startsWith('gopher:') || hostSanitized.startsWith('telnet:') || hostSanitized.startsWith('mailto:') || hostSanitized.startsWith('news:') || hostSanitized.startsWith('nntp:')) {
+ if (callback) { callback(null); }
+ return resolve(null);
+ }
+ let params;
+ let filt;
+ if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
+ if (_linux) {
+ params = ['-c', '2', '-w', '3', hostSanitized];
+ filt = 'rtt';
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ params = ['-c', '2', '-t', '3', hostSanitized];
+ filt = 'round-trip';
+ }
+ if (_darwin) {
+ params = ['-c2', '-t3', hostSanitized];
+ filt = 'avg';
+ }
+ util.execSafe('ping', params).then((stdout) => {
+ let result = null;
+ if (stdout) {
+ const lines = stdout.split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
+
+ const line = lines.split('=');
+ if (line.length > 1) {
+ const parts = line[1].split('/');
+ if (parts.length > 1) {
+ result = parseFloat(parts[1]);
+ }
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ const params = ['-s', '-a', hostSanitized, '56', '2'];
+ const filt = 'avg';
+ util.execSafe('ping', params, { timeout: 3000 }).then((stdout) => {
+ let result = null;
+ if (stdout) {
+ const lines = stdout.split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
+ const line = lines.split('=');
+ if (line.length > 1) {
+ const parts = line[1].split('/');
+ if (parts.length > 1) {
+ result = parseFloat(parts[1].replace(',', '.'));
+ }
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_windows) {
+ let result = null;
+ try {
+ const params = [hostSanitized, '-n', '1'];
+ util.execSafe('ping', params, util.execOptsWin).then((stdout) => {
+ if (stdout) {
+ let lines = stdout.split('\r\n');
+ lines.shift();
+ lines.forEach(function (line) {
+ if ((line.toLowerCase().match(/ms/g) || []).length === 3) {
+ let l = line.replace(/ +/g, ' ').split(' ');
+ if (l.length > 6) {
+ result = parseFloat(l[l.length - 1]);
+ }
+ }
+ });
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.inetLatency = inetLatency;
diff --git a/MistyCore/node_modules/systeminformation/lib/memory.js b/MistyCore/node_modules/systeminformation/lib/memory.js
new file mode 100644
index 0000000..bbf7e5c
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/memory.js
@@ -0,0 +1,547 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// memory.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 5. Memory
+// ----------------------------------------------------------------------------------
+
+const os = require('os');
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const util = require('./util');
+const fs = require('fs');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+const OSX_RAM_manufacturers = {
+ '0x014F': 'Transcend Information',
+ '0x2C00': 'Micron Technology Inc.',
+ '0x802C': 'Micron Technology Inc.',
+ '0x80AD': 'Hynix Semiconductor Inc.',
+ '0x80CE': 'Samsung Electronics Inc.',
+ '0xAD00': 'Hynix Semiconductor Inc.',
+ '0xCE00': 'Samsung Electronics Inc.',
+ '0x02FE': 'Elpida',
+ '0x5105': 'Qimonda AG i. In.',
+ '0x8551': 'Qimonda AG i. In.',
+ '0x859B': 'Crucial',
+ '0x04CD': 'G-Skill'
+};
+
+const LINUX_RAM_manufacturers = {
+ '017A': 'Apacer',
+ '0198': 'HyperX',
+ '029E': 'Corsair',
+ '04CB': 'A-DATA',
+ '04CD': 'G-Skill',
+ '059B': 'Crucial',
+ '00CE': 'Samsung',
+ '1315': 'Crutial',
+ '014F': 'Transcend Information',
+ '2C00': 'Micron Technology Inc.',
+ '802C': 'Micron Technology Inc.',
+ '80AD': 'Hynix Semiconductor Inc.',
+ '80CE': 'Samsung Electronics Inc.',
+ 'AD00': 'Hynix Semiconductor Inc.',
+ 'CE00': 'Samsung Electronics Inc.',
+ '02FE': 'Elpida',
+ '5105': 'Qimonda AG i. In.',
+ '8551': 'Qimonda AG i. In.',
+ '859B': 'Crucial'
+};
+
+// _______________________________________________________________________________________
+// | R A M | H D |
+// |______________________|_________________________| | |
+// | active buffers/cache | | |
+// |________________________________________________|___________|_________|______________|
+// | used free | used free |
+// |____________________________________________________________|________________________|
+// | total | swap |
+// |____________________________________________________________|________________________|
+
+// free (older versions)
+// ----------------------------------
+// # free
+// total used free shared buffers cached
+// Mem: 16038 (1) 15653 (2) 384 (3) 0 (4) 236 (5) 14788 (6)
+// -/+ buffers/cache: 628 (7) 15409 (8)
+// Swap: 16371 83 16288
+//
+// |------------------------------------------------------------|
+// | R A M |
+// |______________________|_____________________________________|
+// | active (2-(5+6) = 7) | available (3+5+6 = 8) |
+// |______________________|_________________________|___________|
+// | active | buffers/cache (5+6) | |
+// |________________________________________________|___________|
+// | used (2) | free (3) |
+// |____________________________________________________________|
+// | total (1) |
+// |____________________________________________________________|
+
+//
+// free (since free von procps-ng 3.3.10)
+// ----------------------------------
+// # free
+// total used free shared buffers/cache available
+// Mem: 16038 (1) 628 (2) 386 (3) 0 (4) 15024 (5) 14788 (6)
+// Swap: 16371 83 16288
+//
+// |------------------------------------------------------------|
+// | R A M |
+// |______________________|_____________________________________|
+// | | available (6) estimated |
+// |______________________|_________________________|___________|
+// | active (2) | buffers/cache (5) | free (3) |
+// |________________________________________________|___________|
+// | total (1) |
+// |____________________________________________________________|
+//
+// Reference: http://www.software-architect.net/blog/article/date/2015/06/12/-826c6e5052.html
+
+// /procs/meminfo - sample (all in kB)
+//
+// MemTotal: 32806380 kB
+// MemFree: 17977744 kB
+// MemAvailable: 19768972 kB
+// Buffers: 517028 kB
+// Cached: 2161876 kB
+// SwapCached: 456 kB
+// Active: 12081176 kB
+// Inactive: 2164616 kB
+// Active(anon): 10832884 kB
+// Inactive(anon): 1477272 kB
+// Active(file): 1248292 kB
+// Inactive(file): 687344 kB
+// Unevictable: 0 kB
+// Mlocked: 0 kB
+// SwapTotal: 16768892 kB
+// SwapFree: 16768304 kB
+// Dirty: 268 kB
+// Writeback: 0 kB
+// AnonPages: 11568832 kB
+// Mapped: 719992 kB
+// Shmem: 743272 kB
+// Slab: 335716 kB
+// SReclaimable: 256364 kB
+// SUnreclaim: 79352 kB
+
+function mem(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = {
+ total: os.totalmem(),
+ free: os.freemem(),
+ used: os.totalmem() - os.freemem(),
+
+ active: os.totalmem() - os.freemem(), // temporarily (fallback)
+ available: os.freemem(), // temporarily (fallback)
+ buffers: 0,
+ cached: 0,
+ slab: 0,
+ buffcache: 0,
+
+ swaptotal: 0,
+ swapused: 0,
+ swapfree: 0
+ };
+
+ if (_linux) {
+ fs.readFile('/proc/meminfo', function (error, stdout) {
+ if (!error) {
+ const lines = stdout.toString().split('\n');
+ result.total = parseInt(util.getValue(lines, 'memtotal'), 10);
+ result.total = result.total ? result.total * 1024 : os.totalmem();
+ result.free = parseInt(util.getValue(lines, 'memfree'), 10);
+ result.free = result.free ? result.free * 1024 : os.freemem();
+ result.used = result.total - result.free;
+
+ result.buffers = parseInt(util.getValue(lines, 'buffers'), 10);
+ result.buffers = result.buffers ? result.buffers * 1024 : 0;
+ result.cached = parseInt(util.getValue(lines, 'cached'), 10);
+ result.cached = result.cached ? result.cached * 1024 : 0;
+ result.slab = parseInt(util.getValue(lines, 'slab'), 10);
+ result.slab = result.slab ? result.slab * 1024 : 0;
+ result.buffcache = result.buffers + result.cached + result.slab;
+
+ let available = parseInt(util.getValue(lines, 'memavailable'), 10);
+ result.available = available ? available * 1024 : result.free + result.buffcache;
+ result.active = result.total - result.available;
+
+ result.swaptotal = parseInt(util.getValue(lines, 'swaptotal'), 10);
+ result.swaptotal = result.swaptotal ? result.swaptotal * 1024 : 0;
+ result.swapfree = parseInt(util.getValue(lines, 'swapfree'), 10);
+ result.swapfree = result.swapfree ? result.swapfree * 1024 : 0;
+ result.swapused = result.swaptotal - result.swapfree;
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ exec('/sbin/sysctl hw.realmem hw.physmem vm.stats.vm.v_page_count vm.stats.vm.v_wire_count vm.stats.vm.v_active_count vm.stats.vm.v_inactive_count vm.stats.vm.v_cache_count vm.stats.vm.v_free_count vm.stats.vm.v_page_size', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ const pagesize = parseInt(util.getValue(lines, 'vm.stats.vm.v_page_size'), 10);
+ const inactive = parseInt(util.getValue(lines, 'vm.stats.vm.v_inactive_count'), 10) * pagesize;
+ const cache = parseInt(util.getValue(lines, 'vm.stats.vm.v_cache_count'), 10) * pagesize;
+
+ result.total = parseInt(util.getValue(lines, 'hw.realmem'), 10);
+ if (isNaN(result.total)) { result.total = parseInt(util.getValue(lines, 'hw.physmem'), 10); }
+ result.free = parseInt(util.getValue(lines, 'vm.stats.vm.v_free_count'), 10) * pagesize;
+ result.buffcache = inactive + cache;
+ result.available = result.buffcache + result.free;
+ result.active = result.total - result.free - result.buffcache;
+
+ result.swaptotal = 0;
+ result.swapfree = 0;
+ result.swapused = 0;
+
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_darwin) {
+ let pageSize = 4096;
+ try {
+ let sysPpageSize = util.toInt(execSync('sysctl -n vm.pagesize').toString());
+ pageSize = sysPpageSize || pageSize;
+ } catch (e) {
+ util.noop();
+ }
+ exec('vm_stat 2>/dev/null | grep "Pages active"', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+
+ result.active = parseInt(lines[0].split(':')[1], 10) * pageSize;
+ result.buffcache = result.used - result.active;
+ result.available = result.free + result.buffcache;
+ }
+ exec('sysctl -n vm.swapusage 2>/dev/null', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ if (lines.length > 0) {
+ let line = lines[0].replace(/,/g, '.').replace(/M/g, '');
+ line = line.trim().split(' ');
+ for (let i = 0; i < line.length; i++) {
+ if (line[i].toLowerCase().indexOf('total') !== -1) { result.swaptotal = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024; }
+ if (line[i].toLowerCase().indexOf('used') !== -1) { result.swapused = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024; }
+ if (line[i].toLowerCase().indexOf('free') !== -1) { result.swapfree = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024; }
+ }
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+ }
+ if (_windows) {
+ let swaptotal = 0;
+ let swapused = 0;
+ try {
+ util.powerShell('Get-CimInstance Win32_PageFileUsage | Select AllocatedBaseSize, CurrentUsage').then((stdout, error) => {
+ if (!error) {
+ let lines = stdout.split('\r\n').filter(line => line.trim() !== '').filter((line, idx) => idx > 0);
+ lines.forEach(function (line) {
+ if (line !== '') {
+ line = line.trim().split(/\s\s+/);
+ swaptotal = swaptotal + (parseInt(line[0], 10) || 0);
+ swapused = swapused + (parseInt(line[1], 10) || 0);
+ }
+ });
+ }
+ result.swaptotal = swaptotal * 1024 * 1024;
+ result.swapused = swapused * 1024 * 1024;
+ result.swapfree = result.swaptotal - result.swapused;
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.mem = mem;
+
+function memLayout(callback) {
+
+ function getManufacturerDarwin(manId) {
+ if ({}.hasOwnProperty.call(OSX_RAM_manufacturers, manId)) {
+ return (OSX_RAM_manufacturers[manId]);
+ }
+ return manId;
+ }
+
+ function getManufacturerLinux(manId) {
+ const manIdSearch = manId.replace('0x', '').toUpperCase();
+ if (manIdSearch.length === 4 && {}.hasOwnProperty.call(LINUX_RAM_manufacturers, manIdSearch)) {
+ return (LINUX_RAM_manufacturers[manIdSearch]);
+ }
+ return manId;
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = [];
+
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ exec('export LC_ALL=C; dmidecode -t memory 2>/dev/null | grep -iE "Size:|Type|Speed|Manufacturer|Form Factor|Locator|Memory Device|Serial Number|Voltage|Part Number"; unset LC_ALL', function (error, stdout) {
+ if (!error) {
+ let devices = stdout.toString().split('Memory Device');
+ devices.shift();
+ devices.forEach(function (device) {
+ let lines = device.split('\n');
+ const sizeString = util.getValue(lines, 'Size');
+ const size = sizeString.indexOf('GB') >= 0 ? parseInt(sizeString, 10) * 1024 * 1024 * 1024 : parseInt(sizeString, 10) * 1024 * 1024;
+ if (parseInt(util.getValue(lines, 'Size'), 10) > 0) {
+ const totalWidth = util.toInt(util.getValue(lines, 'Total Width'));
+ const dataWidth = util.toInt(util.getValue(lines, 'Data Width'));
+ result.push({
+ size,
+ bank: util.getValue(lines, 'Bank Locator'),
+ type: util.getValue(lines, 'Type:'),
+ ecc: dataWidth && totalWidth ? totalWidth > dataWidth : false,
+ clockSpeed: (util.getValue(lines, 'Configured Clock Speed:') ? parseInt(util.getValue(lines, 'Configured Clock Speed:'), 10) : (util.getValue(lines, 'Speed:') ? parseInt(util.getValue(lines, 'Speed:'), 10) : null)),
+ formFactor: util.getValue(lines, 'Form Factor:'),
+ manufacturer: getManufacturerLinux(util.getValue(lines, 'Manufacturer:')),
+ partNum: util.getValue(lines, 'Part Number:'),
+ serialNum: util.getValue(lines, 'Serial Number:'),
+ voltageConfigured: parseFloat(util.getValue(lines, 'Configured Voltage:')) || null,
+ voltageMin: parseFloat(util.getValue(lines, 'Minimum Voltage:')) || null,
+ voltageMax: parseFloat(util.getValue(lines, 'Maximum Voltage:')) || null,
+ });
+ } else {
+ result.push({
+ size: 0,
+ bank: util.getValue(lines, 'Bank Locator'),
+ type: 'Empty',
+ ecc: null,
+ clockSpeed: 0,
+ formFactor: util.getValue(lines, 'Form Factor:'),
+ partNum: '',
+ serialNum: '',
+ voltageConfigured: null,
+ voltageMin: null,
+ voltageMax: null,
+ });
+ }
+ });
+ }
+ if (!result.length) {
+ result.push({
+ size: os.totalmem(),
+ bank: '',
+ type: '',
+ ecc: null,
+ clockSpeed: 0,
+ formFactor: '',
+ partNum: '',
+ serialNum: '',
+ voltageConfigured: null,
+ voltageMin: null,
+ voltageMax: null,
+ });
+
+ // Try Raspberry PI
+ try {
+ let stdout = execSync('cat /proc/cpuinfo 2>/dev/null');
+ let lines = stdout.toString().split('\n');
+ let model = util.getValue(lines, 'hardware', ':', true).toUpperCase();
+ let version = util.getValue(lines, 'revision', ':', true).toLowerCase();
+
+ if (model === 'BCM2835' || model === 'BCM2708' || model === 'BCM2709' || model === 'BCM2835' || model === 'BCM2837') {
+
+ const clockSpeed = {
+ '0': 400,
+ '1': 450,
+ '2': 450,
+ '3': 3200
+ };
+ result[0].type = 'LPDDR2';
+ result[0].type = version && version[2] && version[2] === '3' ? 'LPDDR4' : result[0].type;
+ result[0].ecc = false;
+ result[0].clockSpeed = version && version[2] && clockSpeed[version[2]] || 400;
+ result[0].clockSpeed = version && version[4] && version[4] === 'd' ? 500 : result[0].clockSpeed;
+ result[0].formFactor = 'SoC';
+
+ stdout = execSync('vcgencmd get_config sdram_freq 2>/dev/null');
+ lines = stdout.toString().split('\n');
+ let freq = parseInt(util.getValue(lines, 'sdram_freq', '=', true), 10) || 0;
+ if (freq) {
+ result[0].clockSpeed = freq;
+ }
+
+ stdout = execSync('vcgencmd measure_volts sdram_p 2>/dev/null');
+ lines = stdout.toString().split('\n');
+ let voltage = parseFloat(util.getValue(lines, 'volt', '=', true)) || 0;
+ if (voltage) {
+ result[0].voltageConfigured = voltage;
+ result[0].voltageMin = voltage;
+ result[0].voltageMax = voltage;
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+
+ if (_darwin) {
+ exec('system_profiler SPMemoryDataType', function (error, stdout) {
+ if (!error) {
+ const allLines = stdout.toString().split('\n');
+ const eccStatus = util.getValue(allLines, 'ecc', ':', true).toLowerCase();
+ let devices = stdout.toString().split(' BANK ');
+ let hasBank = true;
+ if (devices.length === 1) {
+ devices = stdout.toString().split(' DIMM');
+ hasBank = false;
+ }
+ devices.shift();
+ devices.forEach(function (device) {
+ let lines = device.split('\n');
+ const bank = (hasBank ? 'BANK ' : 'DIMM') + lines[0].trim().split('/')[0];
+ const size = parseInt(util.getValue(lines, ' Size'));
+ if (size) {
+ result.push({
+ size: size * 1024 * 1024 * 1024,
+ bank: bank,
+ type: util.getValue(lines, ' Type:'),
+ ecc: eccStatus ? eccStatus === 'enabled' : null,
+ clockSpeed: parseInt(util.getValue(lines, ' Speed:'), 10),
+ formFactor: '',
+ manufacturer: getManufacturerDarwin(util.getValue(lines, ' Manufacturer:')),
+ partNum: util.getValue(lines, ' Part Number:'),
+ serialNum: util.getValue(lines, ' Serial Number:'),
+ voltageConfigured: null,
+ voltageMin: null,
+ voltageMax: null,
+ });
+ } else {
+ result.push({
+ size: 0,
+ bank: bank,
+ type: 'Empty',
+ ecc: null,
+ clockSpeed: 0,
+ formFactor: '',
+ manufacturer: '',
+ partNum: '',
+ serialNum: '',
+ voltageConfigured: null,
+ voltageMin: null,
+ voltageMax: null,
+ });
+ }
+ });
+ }
+ if (!result.length) {
+ const lines = stdout.toString().split('\n');
+ const size = parseInt(util.getValue(lines, ' Memory:'));
+ const type = util.getValue(lines, ' Type:');
+ if (size && type) {
+ result.push({
+ size: size * 1024 * 1024 * 1024,
+ bank: '0',
+ type,
+ ecc: false,
+ clockSpeed: 0,
+ formFactor: '',
+ manufacturer: 'Apple',
+ partNum: '',
+ serialNum: '',
+ voltageConfigured: null,
+ voltageMin: null,
+ voltageMax: null,
+ });
+
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_windows) {
+ const memoryTypes = 'Unknown|Other|DRAM|Synchronous DRAM|Cache DRAM|EDO|EDRAM|VRAM|SRAM|RAM|ROM|FLASH|EEPROM|FEPROM|EPROM|CDRAM|3DRAM|SDRAM|SGRAM|RDRAM|DDR|DDR2|DDR2 FB-DIMM|Reserved|DDR3|FBD2|DDR4|LPDDR|LPDDR2|LPDDR3|LPDDR4'.split('|');
+ const FormFactors = 'Unknown|Other|SIP|DIP|ZIP|SOJ|Proprietary|SIMM|DIMM|TSOP|PGA|RIMM|SODIMM|SRIMM|SMD|SSMP|QFP|TQFP|SOIC|LCC|PLCC|BGA|FPBGA|LGA'.split('|');
+
+ try {
+ util.powerShell('Get-WmiObject Win32_PhysicalMemory | select DataWidth,TotalWidth,Capacity,BankLabel,MemoryType,SMBIOSMemoryType,ConfiguredClockSpeed,FormFactor,Manufacturer,PartNumber,SerialNumber,ConfiguredVoltage,MinVoltage,MaxVoltage | fl').then((stdout, error) => {
+ if (!error) {
+ let devices = stdout.toString().split(/\n\s*\n/);
+ devices.shift();
+ devices.forEach(function (device) {
+ let lines = device.split('\r\n');
+ const dataWidth = util.toInt(util.getValue(lines, 'DataWidth', ':'));
+ const totalWidth = util.toInt(util.getValue(lines, 'TotalWidth', ':'));
+ const size = parseInt(util.getValue(lines, 'Capacity', ':'), 10) || 0;
+ if (size) {
+ result.push({
+ size,
+ bank: util.getValue(lines, 'BankLabel', ':'), // BankLabel
+ type: memoryTypes[parseInt(util.getValue(lines, 'MemoryType', ':'), 10) || parseInt(util.getValue(lines, 'SMBIOSMemoryType', ':'), 10)],
+ ecc: dataWidth && totalWidth ? totalWidth > dataWidth : false,
+ clockSpeed: parseInt(util.getValue(lines, 'ConfiguredClockSpeed', ':'), 10) || parseInt(util.getValue(lines, 'Speed', ':'), 10) || 0,
+ formFactor: FormFactors[parseInt(util.getValue(lines, 'FormFactor', ':'), 10) || 0],
+ manufacturer: util.getValue(lines, 'Manufacturer', ':'),
+ partNum: util.getValue(lines, 'PartNumber', ':'),
+ serialNum: util.getValue(lines, 'SerialNumber', ':'),
+ voltageConfigured: (parseInt(util.getValue(lines, 'ConfiguredVoltage', ':'), 10) || 0) / 1000.0,
+ voltageMin: (parseInt(util.getValue(lines, 'MinVoltage', ':'), 10) || 0) / 1000.0,
+ voltageMax: (parseInt(util.getValue(lines, 'MaxVoltage', ':'), 10) || 0) / 1000.0,
+ });
+ }
+ });
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.memLayout = memLayout;
+
diff --git a/MistyCore/node_modules/systeminformation/lib/network.js b/MistyCore/node_modules/systeminformation/lib/network.js
new file mode 100644
index 0000000..e3a29e3
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/network.js
@@ -0,0 +1,1736 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// network.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 9. Network
+// ----------------------------------------------------------------------------------
+
+const os = require('os');
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const fs = require('fs');
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+let _network = {};
+let _default_iface = '';
+let _ifaces = {};
+let _dhcpNics = [];
+let _networkInterfaces = [];
+let _mac = {};
+let pathToIp;
+
+function getDefaultNetworkInterface() {
+
+ let ifacename = '';
+ let ifacenameFirst = '';
+ try {
+ let ifaces = os.networkInterfaces();
+
+ let scopeid = 9999;
+
+ // fallback - "first" external interface (sorted by scopeid)
+ for (let dev in ifaces) {
+ if ({}.hasOwnProperty.call(ifaces, dev)) {
+ ifaces[dev].forEach(function (details) {
+ if (details && details.internal === false) {
+ ifacenameFirst = ifacenameFirst || dev; // fallback if no scopeid
+ if (details.scopeid && details.scopeid < scopeid) {
+ ifacename = dev;
+ scopeid = details.scopeid;
+ }
+ }
+ });
+ }
+ }
+ ifacename = ifacename || ifacenameFirst || '';
+
+ if (_windows) {
+ // https://www.inetdaemon.com/tutorials/internet/ip/routing/default_route.shtml
+ let defaultIp = '';
+ const cmd = 'netstat -r';
+ const result = execSync(cmd, util.execOptsWin);
+ const lines = result.toString().split(os.EOL);
+ lines.forEach(line => {
+ line = line.replace(/\s+/g, ' ').trim();
+ if (line.indexOf('0.0.0.0 0.0.0.0') > -1 && !(/[a-zA-Z]/.test(line))) {
+ const parts = line.split(' ');
+ if (parts.length >= 5) {
+ defaultIp = parts[parts.length - 2];
+ }
+ }
+ });
+ if (defaultIp) {
+ for (let dev in ifaces) {
+ if ({}.hasOwnProperty.call(ifaces, dev)) {
+ ifaces[dev].forEach(function (details) {
+ if (details && details.address && details.address === defaultIp) {
+ ifacename = dev;
+ }
+ });
+ }
+ }
+ }
+ }
+ if (_linux) {
+ let cmd = 'ip route 2> /dev/null | grep default';
+ let result = execSync(cmd);
+ let parts = result.toString().split('\n')[0].split(/\s+/);
+ if (parts[0] === 'none' && parts[5]) {
+ ifacename = parts[5];
+ } else if (parts[4]) {
+ ifacename = parts[4];
+ }
+
+ if (ifacename.indexOf(':') > -1) {
+ ifacename = ifacename.split(':')[1].trim();
+ }
+ }
+ if (_darwin || _freebsd || _openbsd || _netbsd || _sunos) {
+ let cmd = '';
+ if (_linux) { cmd = 'ip route 2> /dev/null | grep default | awk \'{print $5}\''; }
+ if (_darwin) { cmd = 'route -n get default 2>/dev/null | grep interface: | awk \'{print $2}\''; }
+ if (_freebsd || _openbsd || _netbsd || _sunos) { cmd = 'route get 0.0.0.0 | grep interface:'; }
+ let result = execSync(cmd);
+ ifacename = result.toString().split('\n')[0];
+ if (ifacename.indexOf(':') > -1) {
+ ifacename = ifacename.split(':')[1].trim();
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+ if (ifacename) { _default_iface = ifacename; }
+ return _default_iface;
+}
+
+exports.getDefaultNetworkInterface = getDefaultNetworkInterface;
+
+function getMacAddresses() {
+ let iface = '';
+ let mac = '';
+ let result = {};
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ if (typeof pathToIp === 'undefined') {
+ try {
+ const lines = execSync('which ip').toString().split('\n');
+ if (lines.length && lines[0].indexOf(':') === -1 && lines[0].indexOf('/') === 0) {
+ pathToIp = lines[0];
+ } else {
+ pathToIp = '';
+ }
+ } catch (e) {
+ pathToIp = '';
+ }
+ }
+ try {
+ const cmd = 'export LC_ALL=C; ' + ((pathToIp) ? pathToIp + ' link show up' : '/sbin/ifconfig') + '; unset LC_ALL';
+ let res = execSync(cmd);
+ const lines = res.toString().split('\n');
+ for (let i = 0; i < lines.length; i++) {
+ if (lines[i] && lines[i][0] !== ' ') {
+ if (pathToIp) {
+ let nextline = lines[i + 1].trim().split(' ');
+ if (nextline[0] === 'link/ether') {
+ iface = lines[i].split(' ')[1];
+ iface = iface.slice(0, iface.length - 1);
+ mac = nextline[1];
+ }
+ } else {
+ iface = lines[i].split(' ')[0];
+ mac = lines[i].split('HWaddr ')[1];
+ }
+
+ if (iface && mac) {
+ result[iface] = mac.trim();
+ iface = '';
+ mac = '';
+ }
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (_darwin) {
+ try {
+ const cmd = '/sbin/ifconfig';
+ let res = execSync(cmd);
+ const lines = res.toString().split('\n');
+ for (let i = 0; i < lines.length; i++) {
+ if (lines[i] && lines[i][0] !== '\t' && lines[i].indexOf(':') > 0) {
+ iface = lines[i].split(':')[0];
+ } else if (lines[i].indexOf('\tether ') === 0) {
+ mac = lines[i].split('\tether ')[1];
+ if (iface && mac) {
+ result[iface] = mac.trim();
+ iface = '';
+ mac = '';
+ }
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ return result;
+}
+
+function networkInterfaceDefault(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = getDefaultNetworkInterface();
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+}
+
+exports.networkInterfaceDefault = networkInterfaceDefault;
+
+// --------------------------
+// NET - interfaces
+
+function parseLinesWindowsNics(sections, nconfigsections) {
+ let nics = [];
+ for (let i in sections) {
+ if ({}.hasOwnProperty.call(sections, i)) {
+
+ if (sections[i].trim() !== '') {
+
+ let lines = sections[i].trim().split('\r\n');
+ let linesNicConfig = nconfigsections && nconfigsections[i] ? nconfigsections[i].trim().split('\r\n') : [];
+ let netEnabled = util.getValue(lines, 'NetEnabled', ':');
+ let adapterType = util.getValue(lines, 'AdapterTypeID', ':') === '9' ? 'wireless' : 'wired';
+ let ifacename = util.getValue(lines, 'Name', ':').replace(/\]/g, ')').replace(/\[/g, '(');
+ let iface = util.getValue(lines, 'NetConnectionID', ':').replace(/\]/g, ')').replace(/\[/g, '(');
+ if (ifacename.toLowerCase().indexOf('wi-fi') >= 0 || ifacename.toLowerCase().indexOf('wireless') >= 0) {
+ adapterType = 'wireless';
+ }
+ if (netEnabled !== '') {
+ const speed = parseInt(util.getValue(lines, 'speed', ':').trim(), 10) / 1000000;
+ nics.push({
+ mac: util.getValue(lines, 'MACAddress', ':').toLowerCase(),
+ dhcp: util.getValue(linesNicConfig, 'dhcpEnabled', ':').toLowerCase() === 'true',
+ name: ifacename,
+ iface,
+ netEnabled: netEnabled === 'TRUE',
+ speed: isNaN(speed) ? null : speed,
+ operstate: util.getValue(lines, 'NetConnectionStatus', ':') === '2' ? 'up' : 'down',
+ type: adapterType
+ });
+ }
+ }
+ }
+ }
+ return nics;
+}
+
+function getWindowsNics() {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let cmd = 'Get-WmiObject Win32_NetworkAdapter | fl *' + '; echo \'#-#-#-#\';';
+ cmd += 'Get-WmiObject Win32_NetworkAdapterConfiguration | fl DHCPEnabled' + '';
+ try {
+ util.powerShell(cmd).then((data) => {
+ data = data.split('#-#-#-#');
+ const nsections = (data[0] || '').split(/\n\s*\n/);
+ const nconfigsections = (data[1] || '').split(/\n\s*\n/);
+ resolve(parseLinesWindowsNics(nsections, nconfigsections));
+ });
+ } catch (e) {
+ resolve([]);
+ }
+ });
+ });
+}
+
+function getWindowsDNSsuffixes() {
+
+ let iface = {};
+
+ let dnsSuffixes = {
+ primaryDNS: '',
+ exitCode: 0,
+ ifaces: [],
+ };
+
+ try {
+ const ipconfig = execSync('ipconfig /all', util.execOptsWin);
+ const ipconfigArray = ipconfig.split('\r\n\r\n');
+
+ ipconfigArray.forEach((element, index) => {
+
+ if (index == 1) {
+ const longPrimaryDNS = element.split('\r\n').filter((element) => {
+ return element.toUpperCase().includes('DNS');
+ });
+ const primaryDNS = longPrimaryDNS[0].substring(longPrimaryDNS[0].lastIndexOf(':') + 1);
+ dnsSuffixes.primaryDNS = primaryDNS.trim();
+ if (!dnsSuffixes.primaryDNS) { dnsSuffixes.primaryDNS = 'Not defined'; }
+ }
+ if (index > 1) {
+ if (index % 2 == 0) {
+ const name = element.substring(element.lastIndexOf(' ') + 1).replace(':', '');
+ iface.name = name;
+ } else {
+ const connectionSpecificDNS = element.split('\r\n').filter((element) => {
+ return element.toUpperCase().includes('DNS');
+ });
+ const dnsSuffix = connectionSpecificDNS[0].substring(connectionSpecificDNS[0].lastIndexOf(':') + 1);
+ iface.dnsSuffix = dnsSuffix.trim();
+ dnsSuffixes.ifaces.push(iface);
+ iface = {};
+ }
+ }
+ });
+
+ return dnsSuffixes;
+ } catch (error) {
+ // console.log('An error occurred trying to bring the Connection-specific DNS suffix', error.message);
+ return {
+ primaryDNS: '',
+ exitCode: 0,
+ ifaces: [],
+ };
+ }
+}
+
+function getWindowsIfaceDNSsuffix(ifaces, ifacename) {
+ let dnsSuffix = '';
+ // Adding (.) to ensure ifacename compatibility when duplicated iface-names
+ const interfaceName = ifacename + '.';
+ try {
+ const connectionDnsSuffix = ifaces.filter((iface) => {
+ return interfaceName.includes(iface.name + '.');
+ }).map((iface) => iface.dnsSuffix);
+ if (connectionDnsSuffix[0]) {
+ dnsSuffix = connectionDnsSuffix[0];
+ }
+ if (!dnsSuffix) { dnsSuffix = ''; }
+ return dnsSuffix;
+ } catch (error) {
+ // console.log('Error getting Connection-specific DNS suffix: ', error.message);
+ return 'Unknown';
+ }
+}
+
+function getWindowsWiredProfilesInformation() {
+ try {
+ const result = execSync('netsh lan show profiles', util.execOptsWin);
+ const profileList = result.split('\r\nProfile on interface');
+ return profileList;
+ } catch (error) {
+ if (error.status === 1 && error.stdout.includes('AutoConfig')) {
+ return 'Disabled';
+ }
+ return [];
+ }
+}
+
+function getWindowsWirelessIfaceSSID(interfaceName) {
+ try {
+ const result = execSync(`netsh wlan show interface name="${interfaceName}" | findstr "SSID"`, util.execOptsWin);
+ const SSID = result.split('\r\n').shift();
+ const parseSSID = SSID.split(':').pop();
+ return parseSSID;
+ } catch (error) {
+ return 'Unknown';
+ }
+}
+function getWindowsIEEE8021x(connectionType, iface, ifaces) {
+ let i8021x = {
+ state: 'Unknown',
+ protocol: 'Unknown',
+ };
+
+ if (ifaces === 'Disabled') {
+ i8021x.state = 'Disabled';
+ i8021x.protocol = 'Not defined';
+ return i8021x;
+ }
+
+ if (connectionType == 'wired' && ifaces.length > 0) {
+ try {
+ // Get 802.1x information by interface name
+ const iface8021xInfo = ifaces.find((element) => {
+ return element.includes(iface + '\r\n');
+ });
+ const arrayIface8021xInfo = iface8021xInfo.split('\r\n');
+ const state8021x = arrayIface8021xInfo.find((element) => {
+ return element.includes('802.1x');
+ });
+
+ if (state8021x.includes('Disabled')) {
+ i8021x.state = 'Disabled';
+ i8021x.protocol = 'Not defined';
+ } else if (state8021x.includes('Enabled')) {
+ const protocol8021x = arrayIface8021xInfo.find((element) => {
+ return element.includes('EAP');
+ });
+ i8021x.protocol = protocol8021x.split(':').pop();
+ i8021x.state = 'Enabled';
+ }
+ } catch (error) {
+ return i8021x;
+ }
+ } else if (connectionType == 'wireless') {
+
+ let i8021xState = '';
+ let i8021xProtocol = '';
+
+
+
+ try {
+ const SSID = getWindowsWirelessIfaceSSID(iface);
+ if (SSID !== 'Unknown') {
+ i8021xState = execSync(`netsh wlan show profiles "${SSID}" | findstr "802.1X"`, util.execOptsWin);
+ i8021xProtocol = execSync(`netsh wlan show profiles "${SSID}" | findstr "EAP"`, util.execOptsWin);
+ }
+
+ if (i8021xState.includes(':') && i8021xProtocol.includes(':')) {
+ i8021x.state = i8021xState.split(':').pop();
+ i8021x.protocol = i8021xProtocol.split(':').pop();
+ }
+ } catch (error) {
+ if (error.status === 1 && error.stdout.includes('AutoConfig')) {
+ i8021x.state = 'Disabled';
+ i8021x.protocol = 'Not defined';
+ }
+ return i8021x;
+ }
+ }
+
+ return i8021x;
+}
+
+function splitSectionsNics(lines) {
+ const result = [];
+ let section = [];
+ lines.forEach(function (line) {
+ if (!line.startsWith('\t') && !line.startsWith(' ')) {
+ if (section.length) {
+ result.push(section);
+ section = [];
+ }
+ }
+ section.push(line);
+ });
+ if (section.length) {
+ result.push(section);
+ }
+ return result;
+}
+
+function parseLinesDarwinNics(sections) {
+ let nics = [];
+ sections.forEach(section => {
+ let nic = {
+ iface: '',
+ mtu: null,
+ mac: '',
+ ip6: '',
+ ip4: '',
+ speed: null,
+ type: '',
+ operstate: '',
+ duplex: '',
+ internal: false
+ };
+ const first = section[0];
+ nic.iface = first.split(':')[0].trim();
+ let parts = first.split('> mtu');
+ nic.mtu = parts.length > 1 ? parseInt(parts[1], 10) : null;
+ if (isNaN(nic.mtu)) {
+ nic.mtu = null;
+ }
+ nic.internal = parts[0].toLowerCase().indexOf('loopback') > -1;
+ section.forEach(line => {
+ if (line.trim().startsWith('ether ')) {
+ nic.mac = line.split('ether ')[1].toLowerCase().trim();
+ }
+ if (line.trim().startsWith('inet6 ') && !nic.ip6) {
+ nic.ip6 = line.split('inet6 ')[1].toLowerCase().split('%')[0].split(' ')[0];
+ }
+ if (line.trim().startsWith('inet ') && !nic.ip4) {
+ nic.ip4 = line.split('inet ')[1].toLowerCase().split(' ')[0];
+ }
+ });
+ let speed = util.getValue(section, 'link rate');
+ nic.speed = speed ? parseFloat(speed) : null;
+ if (nic.speed === null) {
+ speed = util.getValue(section, 'uplink rate');
+ nic.speed = speed ? parseFloat(speed) : null;
+ if (nic.speed !== null && speed.toLowerCase().indexOf('gbps') >= 0) {
+ nic.speed = nic.speed * 1000;
+ }
+ } else {
+ if (speed.toLowerCase().indexOf('gbps') >= 0) {
+ nic.speed = nic.speed * 1000;
+ }
+ }
+ nic.type = util.getValue(section, 'type').toLowerCase().indexOf('wi-fi') > -1 ? 'wireless' : 'wired';
+ const operstate = util.getValue(section, 'status').toLowerCase();
+ nic.operstate = (operstate === 'active' ? 'up' : (operstate === 'inactive' ? 'down' : 'unknown'));
+ nic.duplex = util.getValue(section, 'media').toLowerCase().indexOf('half-duplex') > -1 ? 'half' : 'full';
+ if (nic.ip6 || nic.ip4 || nic.mac) {
+ nics.push(nic);
+ }
+ });
+ return nics;
+}
+
+function getDarwinNics() {
+ const cmd = '/sbin/ifconfig -v';
+ try {
+ // console.log('SYNC - Nics darwin 12');
+ const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
+ const nsections = splitSectionsNics(lines);
+ return (parseLinesDarwinNics(nsections));
+ } catch (e) {
+ return [];
+ }
+}
+
+function getLinuxIfaceConnectionName(interfaceName) {
+ const cmd = `nmcli device status 2>/dev/null | grep ${interfaceName}`;
+
+ try {
+ const result = execSync(cmd).toString();
+ const resultFormat = result.replace(/\s+/g, ' ').trim();
+ const connectionNameLines = resultFormat.split(' ').slice(3);
+ const connectionName = connectionNameLines.join(' ');
+ return connectionName != '--' ? connectionName : '';
+ } catch (e) {
+ return '';
+ }
+}
+
+function checkLinuxDCHPInterfaces(file) {
+ let result = [];
+ try {
+ let cmd = `cat ${file} 2> /dev/null | grep 'iface\\|source'`;
+ const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
+
+ lines.forEach(line => {
+ const parts = line.replace(/\s+/g, ' ').trim().split(' ');
+ if (parts.length >= 4) {
+ if (line.toLowerCase().indexOf(' inet ') >= 0 && line.toLowerCase().indexOf('dhcp') >= 0) {
+ result.push(parts[1]);
+ }
+ }
+ if (line.toLowerCase().includes('source')) {
+ let file = line.split(' ')[1];
+ result = result.concat(checkLinuxDCHPInterfaces(file));
+ }
+ });
+ } catch (e) {
+ util.noop();
+ }
+ return result;
+}
+
+function getLinuxDHCPNics() {
+ // alternate methods getting interfaces using DHCP
+ let cmd = 'ip a 2> /dev/null';
+ let result = [];
+ try {
+ const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
+ const nsections = splitSectionsNics(lines);
+ result = (parseLinuxDHCPNics(nsections));
+ } catch (e) {
+ util.noop();
+ }
+ try {
+ result = checkLinuxDCHPInterfaces('/etc/network/interfaces');
+ } catch (e) {
+ util.noop();
+ }
+ return result;
+}
+
+function parseLinuxDHCPNics(sections) {
+ const result = [];
+ if (sections && sections.length) {
+ sections.forEach(lines => {
+ if (lines && lines.length) {
+ const parts = lines[0].split(':');
+ if (parts.length > 2) {
+ for (let line of lines) {
+ if (line.indexOf(' inet ') >= 0 && line.indexOf(' dynamic ') >= 0) {
+ const parts2 = line.split(' ');
+ const nic = parts2[parts2.length - 1].trim();
+ result.push(nic);
+ break;
+ }
+ }
+ }
+ }
+ });
+ }
+ return result;
+}
+
+function getLinuxIfaceDHCPstatus(iface, connectionName, DHCPNics) {
+ let result = false;
+ if (connectionName) {
+ const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep ipv4.method;`;
+ try {
+ const lines = execSync(cmd).toString();
+ const resultFormat = lines.replace(/\s+/g, ' ').trim();
+
+ let dhcStatus = resultFormat.split(' ').slice(1).toString();
+ switch (dhcStatus) {
+ case 'auto':
+ result = true;
+ break;
+
+ default:
+ result = false;
+ break;
+ }
+ return result;
+ } catch (e) {
+ return (DHCPNics.indexOf(iface) >= 0);
+ }
+ } else {
+ return (DHCPNics.indexOf(iface) >= 0);
+ }
+}
+
+function getDarwinIfaceDHCPstatus(iface) {
+ let result = false;
+ const cmd = `ipconfig getpacket "${iface}" 2>/dev/null | grep lease_time;`;
+ try {
+ // console.log('SYNC - DHCP status darwin 17');
+ const lines = execSync(cmd).toString().split('\n');
+ if (lines.length && lines[0].startsWith('lease_time')) {
+ result = true;
+ }
+ } catch (e) {
+ util.noop();
+ }
+ return result;
+}
+
+function getLinuxIfaceDNSsuffix(connectionName) {
+ if (connectionName) {
+ const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep ipv4.dns-search;`;
+ try {
+ const result = execSync(cmd).toString();
+ const resultFormat = result.replace(/\s+/g, ' ').trim();
+ const dnsSuffix = resultFormat.split(' ').slice(1).toString();
+ return dnsSuffix == '--' ? 'Not defined' : dnsSuffix;
+ } catch (e) {
+ return 'Unknown';
+ }
+ } else {
+ return 'Unknown';
+ }
+}
+
+function getLinuxIfaceIEEE8021xAuth(connectionName) {
+ if (connectionName) {
+ const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep 802-1x.eap;`;
+ try {
+ const result = execSync(cmd).toString();
+ const resultFormat = result.replace(/\s+/g, ' ').trim();
+ const authenticationProtocol = resultFormat.split(' ').slice(1).toString();
+
+
+ return authenticationProtocol == '--' ? '' : authenticationProtocol;
+ } catch (e) {
+ return 'Not defined';
+ }
+ } else {
+ return 'Not defined';
+ }
+}
+
+function getLinuxIfaceIEEE8021xState(authenticationProtocol) {
+ if (authenticationProtocol) {
+ if (authenticationProtocol == 'Not defined') {
+ return 'Disabled';
+ }
+ return 'Enabled';
+ } else {
+ return 'Unknown';
+ }
+}
+
+function testVirtualNic(iface, ifaceName, mac) {
+ const virtualMacs = ['00:00:00:00:00:00', '00:03:FF', '00:05:69', '00:0C:29', '00:0F:4B', '00:0F:4B', '00:13:07', '00:13:BE', '00:15:5d', '00:16:3E', '00:1C:42', '00:21:F6', '00:21:F6', '00:24:0B', '00:24:0B', '00:50:56', '00:A0:B1', '00:E0:C8', '08:00:27', '0A:00:27', '18:92:2C', '16:DF:49', '3C:F3:92', '54:52:00', 'FC:15:97'];
+ if (mac) {
+ return virtualMacs.filter(item => { return mac.toUpperCase().toUpperCase().startsWith(item.substr(0, mac.length)); }).length > 0 ||
+ iface.toLowerCase().indexOf(' virtual ') > -1 ||
+ ifaceName.toLowerCase().indexOf(' virtual ') > -1 ||
+ iface.toLowerCase().indexOf('vethernet ') > -1 ||
+ ifaceName.toLowerCase().indexOf('vethernet ') > -1 ||
+ iface.toLowerCase().startsWith('veth') ||
+ ifaceName.toLowerCase().startsWith('veth') ||
+ iface.toLowerCase().startsWith('vboxnet') ||
+ ifaceName.toLowerCase().startsWith('vboxnet');
+ } else { return false; }
+}
+
+function networkInterfaces(callback, rescan, defaultString) {
+
+ if (typeof callback === 'string') {
+ defaultString = callback;
+ rescan = true;
+ callback = null;
+ }
+
+ if (typeof callback === 'boolean') {
+ rescan = callback;
+ callback = null;
+ defaultString = '';
+ }
+ if (typeof rescan === 'undefined') {
+ rescan = true;
+ }
+ defaultString = defaultString || '';
+ defaultString = '' + defaultString;
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let ifaces = os.networkInterfaces();
+
+ let result = [];
+ let nics = [];
+ let dnsSuffixes = [];
+ let nics8021xInfo = [];
+ // seperate handling in OSX
+ if (_darwin || _freebsd || _openbsd || _netbsd) {
+ if ((JSON.stringify(ifaces) === JSON.stringify(_ifaces)) && !rescan) {
+ // no changes - just return object
+ result = _networkInterfaces;
+
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ const defaultInterface = getDefaultNetworkInterface();
+ _ifaces = JSON.parse(JSON.stringify(ifaces));
+
+ nics = getDarwinNics();
+
+
+ nics.forEach(nic => {
+
+ if ({}.hasOwnProperty.call(ifaces, nic.iface)) {
+ ifaces[nic.iface].forEach(function (details) {
+ if (details.family === 'IPv4' || details.family === 4) {
+ nic.ip4subnet = details.netmask;
+ }
+ if (details.family === 'IPv6' || details.family === 6) {
+ nic.ip6subnet = details.netmask;
+ }
+ });
+ }
+
+ result.push({
+ iface: nic.iface,
+ ifaceName: nic.iface,
+ default: nic.iface === defaultInterface,
+ ip4: nic.ip4,
+ ip4subnet: nic.ip4subnet || '',
+ ip6: nic.ip6,
+ ip6subnet: nic.ip6subnet || '',
+ mac: nic.mac,
+ internal: nic.internal,
+ virtual: nic.internal ? false : testVirtualNic(nic.iface, nic.iface, nic.mac),
+ operstate: nic.operstate,
+ type: nic.type,
+ duplex: nic.duplex,
+ mtu: nic.mtu,
+ speed: nic.speed,
+ dhcp: getDarwinIfaceDHCPstatus(nic.iface),
+ dnsSuffix: '',
+ ieee8021xAuth: '',
+ ieee8021xState: '',
+ carrierChanges: 0
+ });
+ });
+ _networkInterfaces = result;
+ if (defaultString.toLowerCase().indexOf('default') >= 0) {
+ result = result.filter(item => item.default);
+ if (result.length > 0) {
+ result = result[0];
+ } else {
+ result = [];
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_linux) {
+ if ((JSON.stringify(ifaces) === JSON.stringify(_ifaces)) && !rescan) {
+ // no changes - just return object
+ result = _networkInterfaces;
+
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ _ifaces = JSON.parse(JSON.stringify(ifaces));
+ _dhcpNics = getLinuxDHCPNics();
+ const defaultInterface = getDefaultNetworkInterface();
+ for (let dev in ifaces) {
+ let ip4 = '';
+ let ip4subnet = '';
+ let ip6 = '';
+ let ip6subnet = '';
+ let mac = '';
+ let duplex = '';
+ let mtu = '';
+ let speed = null;
+ let carrierChanges = 0;
+ let dhcp = false;
+ let dnsSuffix = '';
+ let ieee8021xAuth = '';
+ let ieee8021xState = '';
+ let type = '';
+
+ if ({}.hasOwnProperty.call(ifaces, dev)) {
+ let ifaceName = dev;
+ ifaces[dev].forEach(function (details) {
+ if (details.family === 'IPv4' || details.family === 4) {
+ ip4 = details.address;
+ ip4subnet = details.netmask;
+ }
+ if (details.family === 'IPv6' || details.family === 6) {
+ if (!ip6 || ip6.match(/^fe80::/i)) {
+ ip6 = details.address;
+ ip6subnet = details.netmask;
+ }
+ }
+ mac = details.mac;
+ // fallback due to https://github.com/nodejs/node/issues/13581 (node 8.1 - node 8.2)
+ const nodeMainVersion = parseInt(process.versions.node.split('.'), 10);
+ if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && (!details.internal) && nodeMainVersion >= 8 && nodeMainVersion <= 11) {
+ if (Object.keys(_mac).length === 0) {
+ _mac = getMacAddresses();
+ }
+ mac = _mac[dev] || '';
+ }
+ });
+ let iface = dev.split(':')[0].trim().toLowerCase();
+ const cmd = `echo -n "addr_assign_type: "; cat /sys/class/net/${iface}/addr_assign_type 2>/dev/null; echo;
+ echo -n "address: "; cat /sys/class/net/${iface}/address 2>/dev/null; echo;
+ echo -n "addr_len: "; cat /sys/class/net/${iface}/addr_len 2>/dev/null; echo;
+ echo -n "broadcast: "; cat /sys/class/net/${iface}/broadcast 2>/dev/null; echo;
+ echo -n "carrier: "; cat /sys/class/net/${iface}/carrier 2>/dev/null; echo;
+ echo -n "carrier_changes: "; cat /sys/class/net/${iface}/carrier_changes 2>/dev/null; echo;
+ echo -n "dev_id: "; cat /sys/class/net/${iface}/dev_id 2>/dev/null; echo;
+ echo -n "dev_port: "; cat /sys/class/net/${iface}/dev_port 2>/dev/null; echo;
+ echo -n "dormant: "; cat /sys/class/net/${iface}/dormant 2>/dev/null; echo;
+ echo -n "duplex: "; cat /sys/class/net/${iface}/duplex 2>/dev/null; echo;
+ echo -n "flags: "; cat /sys/class/net/${iface}/flags 2>/dev/null; echo;
+ echo -n "gro_flush_timeout: "; cat /sys/class/net/${iface}/gro_flush_timeout 2>/dev/null; echo;
+ echo -n "ifalias: "; cat /sys/class/net/${iface}/ifalias 2>/dev/null; echo;
+ echo -n "ifindex: "; cat /sys/class/net/${iface}/ifindex 2>/dev/null; echo;
+ echo -n "iflink: "; cat /sys/class/net/${iface}/iflink 2>/dev/null; echo;
+ echo -n "link_mode: "; cat /sys/class/net/${iface}/link_mode 2>/dev/null; echo;
+ echo -n "mtu: "; cat /sys/class/net/${iface}/mtu 2>/dev/null; echo;
+ echo -n "netdev_group: "; cat /sys/class/net/${iface}/netdev_group 2>/dev/null; echo;
+ echo -n "operstate: "; cat /sys/class/net/${iface}/operstate 2>/dev/null; echo;
+ echo -n "proto_down: "; cat /sys/class/net/${iface}/proto_down 2>/dev/null; echo;
+ echo -n "speed: "; cat /sys/class/net/${iface}/speed 2>/dev/null; echo;
+ echo -n "tx_queue_len: "; cat /sys/class/net/${iface}/tx_queue_len 2>/dev/null; echo;
+ echo -n "type: "; cat /sys/class/net/${iface}/type 2>/dev/null; echo;
+ echo -n "wireless: "; cat /proc/net/wireless 2>/dev/null | grep ${iface}; echo;
+ echo -n "wirelessspeed: "; iw dev ${iface} link 2>&1 | grep bitrate; echo;`;
+
+ let lines = [];
+ try {
+ lines = execSync(cmd).toString().split('\n');
+ const connectionName = getLinuxIfaceConnectionName(iface);
+ dhcp = getLinuxIfaceDHCPstatus(iface, connectionName, _dhcpNics);
+ dnsSuffix = getLinuxIfaceDNSsuffix(connectionName);
+ ieee8021xAuth = getLinuxIfaceIEEE8021xAuth(connectionName);
+ ieee8021xState = getLinuxIfaceIEEE8021xState(ieee8021xAuth);
+ } catch (e) {
+ util.noop();
+ }
+ duplex = util.getValue(lines, 'duplex');
+ duplex = duplex.startsWith('cat') ? '' : duplex;
+ mtu = parseInt(util.getValue(lines, 'mtu'), 10);
+ let myspeed = parseInt(util.getValue(lines, 'speed'), 10);
+ speed = isNaN(myspeed) ? null : myspeed;
+ let wirelessspeed = util.getValue(lines, 'wirelessspeed').split('tx bitrate: ');
+ if (speed === null && wirelessspeed.length === 2) {
+ myspeed = parseFloat(wirelessspeed[1]);
+ speed = isNaN(myspeed) ? null : myspeed;
+ }
+ carrierChanges = parseInt(util.getValue(lines, 'carrier_changes'), 10);
+ const operstate = util.getValue(lines, 'operstate');
+ type = operstate === 'up' ? (util.getValue(lines, 'wireless').trim() ? 'wireless' : 'wired') : 'unknown';
+ if (iface === 'lo' || iface.startsWith('bond')) { type = 'virtual'; }
+
+ let internal = (ifaces[dev] && ifaces[dev][0]) ? ifaces[dev][0].internal : false;
+ if (dev.toLowerCase().indexOf('loopback') > -1 || ifaceName.toLowerCase().indexOf('loopback') > -1) {
+ internal = true;
+ }
+ const virtual = internal ? false : testVirtualNic(dev, ifaceName, mac);
+ result.push({
+ iface,
+ ifaceName,
+ default: iface === defaultInterface,
+ ip4,
+ ip4subnet,
+ ip6,
+ ip6subnet,
+ mac,
+ internal,
+ virtual,
+ operstate,
+ type,
+ duplex,
+ mtu,
+ speed,
+ dhcp,
+ dnsSuffix,
+ ieee8021xAuth,
+ ieee8021xState,
+ carrierChanges,
+ });
+ }
+ }
+ _networkInterfaces = result;
+ if (defaultString.toLowerCase().indexOf('default') >= 0) {
+ result = result.filter(item => item.default);
+ if (result.length > 0) {
+ result = result[0];
+ } else {
+ result = [];
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_windows) {
+ if ((JSON.stringify(ifaces) === JSON.stringify(_ifaces)) && !rescan) {
+ // no changes - just return object
+ result = _networkInterfaces;
+
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ _ifaces = JSON.parse(JSON.stringify(ifaces));
+ const defaultInterface = getDefaultNetworkInterface();
+
+ getWindowsNics().then(function (nics) {
+ nics.forEach(nic => {
+ let found = false;
+ Object.keys(ifaces).forEach(key => {
+ if (!found) {
+ ifaces[key].forEach(value => {
+ if (Object.keys(value).indexOf('mac') >= 0) {
+ found = value['mac'] === nic.mac;
+ }
+ });
+ }
+ });
+
+ if (!found) {
+ ifaces[nic.name] = [{ mac: nic.mac }];
+ }
+ });
+ nics8021xInfo = getWindowsWiredProfilesInformation();
+ dnsSuffixes = getWindowsDNSsuffixes();
+ for (let dev in ifaces) {
+ let iface = dev;
+ let ip4 = '';
+ let ip4subnet = '';
+ let ip6 = '';
+ let ip6subnet = '';
+ let mac = '';
+ let duplex = '';
+ let mtu = '';
+ let speed = null;
+ let carrierChanges = 0;
+ let operstate = 'down';
+ let dhcp = false;
+ let dnsSuffix = '';
+ let ieee8021xAuth = '';
+ let ieee8021xState = '';
+ let type = '';
+
+ if ({}.hasOwnProperty.call(ifaces, dev)) {
+ let ifaceName = dev;
+ ifaces[dev].forEach(function (details) {
+ if (details.family === 'IPv4' || details.family === 4) {
+ ip4 = details.address;
+ ip4subnet = details.netmask;
+ }
+ if (details.family === 'IPv6' || details.family === 6) {
+ if (!ip6 || ip6.match(/^fe80::/i)) {
+ ip6 = details.address;
+ ip6subnet = details.netmask;
+ }
+ }
+ mac = details.mac;
+ // fallback due to https://github.com/nodejs/node/issues/13581 (node 8.1 - node 8.2)
+ const nodeMainVersion = parseInt(process.versions.node.split('.'), 10);
+ if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && (!details.internal) && nodeMainVersion >= 8 && nodeMainVersion <= 11) {
+ if (Object.keys(_mac).length === 0) {
+ _mac = getMacAddresses();
+ }
+ mac = _mac[dev] || '';
+ }
+ });
+
+
+
+ dnsSuffix = getWindowsIfaceDNSsuffix(dnsSuffixes.ifaces, dev);
+ let foundFirst = false;
+ nics.forEach(detail => {
+ if (detail.mac === mac && !foundFirst) {
+ iface = detail.iface || iface;
+ ifaceName = detail.name;
+ dhcp = detail.dhcp;
+ operstate = detail.operstate;
+ speed = detail.speed;
+ type = detail.type;
+ foundFirst = true;
+ }
+ });
+
+ if (dev.toLowerCase().indexOf('wlan') >= 0 || ifaceName.toLowerCase().indexOf('wlan') >= 0 || ifaceName.toLowerCase().indexOf('802.11n') >= 0 || ifaceName.toLowerCase().indexOf('wireless') >= 0 || ifaceName.toLowerCase().indexOf('wi-fi') >= 0 || ifaceName.toLowerCase().indexOf('wifi') >= 0) {
+ type = 'wireless';
+ }
+
+ const IEEE8021x = getWindowsIEEE8021x(type, dev, nics8021xInfo);
+ ieee8021xAuth = IEEE8021x.protocol;
+ ieee8021xState = IEEE8021x.state;
+ let internal = (ifaces[dev] && ifaces[dev][0]) ? ifaces[dev][0].internal : false;
+ if (dev.toLowerCase().indexOf('loopback') > -1 || ifaceName.toLowerCase().indexOf('loopback') > -1) {
+ internal = true;
+ }
+ const virtual = internal ? false : testVirtualNic(dev, ifaceName, mac);
+ result.push({
+ iface,
+ ifaceName,
+ default: iface === defaultInterface,
+ ip4,
+ ip4subnet,
+ ip6,
+ ip6subnet,
+ mac,
+ internal,
+ virtual,
+ operstate,
+ type,
+ duplex,
+ mtu,
+ speed,
+ dhcp,
+ dnsSuffix,
+ ieee8021xAuth,
+ ieee8021xState,
+ carrierChanges,
+ });
+ }
+ }
+ _networkInterfaces = result;
+ if (defaultString.toLowerCase().indexOf('default') >= 0) {
+ result = result.filter(item => item.default);
+ if (result.length > 0) {
+ result = result[0];
+ } else {
+ result = [];
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ }
+ });
+ });
+}
+
+exports.networkInterfaces = networkInterfaces;
+
+// --------------------------
+// NET - Speed
+
+function calcNetworkSpeed(iface, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors) {
+ let result = {
+ iface,
+ operstate,
+ rx_bytes,
+ rx_dropped,
+ rx_errors,
+ tx_bytes,
+ tx_dropped,
+ tx_errors,
+ rx_sec: null,
+ tx_sec: null,
+ ms: 0
+ };
+
+ if (_network[iface] && _network[iface].ms) {
+ result.ms = Date.now() - _network[iface].ms;
+ result.rx_sec = (rx_bytes - _network[iface].rx_bytes) >= 0 ? (rx_bytes - _network[iface].rx_bytes) / (result.ms / 1000) : 0;
+ result.tx_sec = (tx_bytes - _network[iface].tx_bytes) >= 0 ? (tx_bytes - _network[iface].tx_bytes) / (result.ms / 1000) : 0;
+ _network[iface].rx_bytes = rx_bytes;
+ _network[iface].tx_bytes = tx_bytes;
+ _network[iface].rx_sec = result.rx_sec;
+ _network[iface].tx_sec = result.tx_sec;
+ _network[iface].ms = Date.now();
+ _network[iface].last_ms = result.ms;
+ _network[iface].operstate = operstate;
+ } else {
+ if (!_network[iface]) { _network[iface] = {}; }
+ _network[iface].rx_bytes = rx_bytes;
+ _network[iface].tx_bytes = tx_bytes;
+ _network[iface].rx_sec = null;
+ _network[iface].tx_sec = null;
+ _network[iface].ms = Date.now();
+ _network[iface].last_ms = 0;
+ _network[iface].operstate = operstate;
+ }
+ return result;
+}
+
+function networkStats(ifaces, callback) {
+
+ let ifacesArray = [];
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ // fallback - if only callback is given
+ if (util.isFunction(ifaces) && !callback) {
+ callback = ifaces;
+ ifacesArray = [getDefaultNetworkInterface()];
+ } else {
+ if (typeof ifaces !== 'string' && ifaces !== undefined) {
+ if (callback) { callback([]); }
+ return resolve([]);
+ }
+ ifaces = ifaces || getDefaultNetworkInterface();
+
+ ifaces.__proto__.toLowerCase = util.stringToLower;
+ ifaces.__proto__.replace = util.stringReplace;
+ ifaces.__proto__.trim = util.stringTrim;
+
+ ifaces = ifaces.trim().toLowerCase().replace(/,+/g, '|');
+ ifacesArray = ifaces.split('|');
+ }
+
+ const result = [];
+
+ const workload = [];
+ if (ifacesArray.length && ifacesArray[0].trim() === '*') {
+ ifacesArray = [];
+ networkInterfaces(false).then(allIFaces => {
+ for (let iface of allIFaces) {
+ ifacesArray.push(iface.iface);
+ }
+ networkStats(ifacesArray.join(',')).then(result => {
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ });
+ } else {
+ for (let iface of ifacesArray) {
+ workload.push(networkStatsSingle(iface.trim()));
+ }
+ if (workload.length) {
+ Promise.all(
+ workload
+ ).then((data) => {
+ if (callback) { callback(data); }
+ resolve(data);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+function networkStatsSingle(iface) {
+
+ function parseLinesWindowsPerfData(sections) {
+ let perfData = [];
+ for (let i in sections) {
+ if ({}.hasOwnProperty.call(sections, i)) {
+ if (sections[i].trim() !== '') {
+ let lines = sections[i].trim().split('\r\n');
+ perfData.push({
+ name: util.getValue(lines, 'Name', ':').replace(/[()[\] ]+/g, '').replace(/#|\//g, '_').toLowerCase(),
+ rx_bytes: parseInt(util.getValue(lines, 'BytesReceivedPersec', ':'), 10),
+ rx_errors: parseInt(util.getValue(lines, 'PacketsReceivedErrors', ':'), 10),
+ rx_dropped: parseInt(util.getValue(lines, 'PacketsReceivedDiscarded', ':'), 10),
+ tx_bytes: parseInt(util.getValue(lines, 'BytesSentPersec', ':'), 10),
+ tx_errors: parseInt(util.getValue(lines, 'PacketsOutboundErrors', ':'), 10),
+ tx_dropped: parseInt(util.getValue(lines, 'PacketsOutboundDiscarded', ':'), 10)
+ });
+ }
+ }
+ }
+ return perfData;
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let ifaceSanitized = '';
+ const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(iface);
+ for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
+ if (s[i] !== undefined) {
+ ifaceSanitized = ifaceSanitized + s[i];
+ }
+ }
+
+ let result = {
+ iface: ifaceSanitized,
+ operstate: 'unknown',
+ rx_bytes: 0,
+ rx_dropped: 0,
+ rx_errors: 0,
+ tx_bytes: 0,
+ tx_dropped: 0,
+ tx_errors: 0,
+ rx_sec: null,
+ tx_sec: null,
+ ms: 0
+ };
+
+ let operstate = 'unknown';
+ let rx_bytes = 0;
+ let tx_bytes = 0;
+ let rx_dropped = 0;
+ let rx_errors = 0;
+ let tx_dropped = 0;
+ let tx_errors = 0;
+
+ let cmd, lines, stats;
+ if (!_network[ifaceSanitized] || (_network[ifaceSanitized] && !_network[ifaceSanitized].ms) || (_network[ifaceSanitized] && _network[ifaceSanitized].ms && Date.now() - _network[ifaceSanitized].ms >= 500)) {
+ if (_linux) {
+ if (fs.existsSync('/sys/class/net/' + ifaceSanitized)) {
+ cmd =
+ 'cat /sys/class/net/' + ifaceSanitized + '/operstate; ' +
+ 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_bytes; ' +
+ 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_bytes; ' +
+ 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_dropped; ' +
+ 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_errors; ' +
+ 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_dropped; ' +
+ 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_errors; ';
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ lines = stdout.toString().split('\n');
+ operstate = lines[0].trim();
+ rx_bytes = parseInt(lines[1], 10);
+ tx_bytes = parseInt(lines[2], 10);
+ rx_dropped = parseInt(lines[3], 10);
+ rx_errors = parseInt(lines[4], 10);
+ tx_dropped = parseInt(lines[5], 10);
+ tx_errors = parseInt(lines[6], 10);
+
+ result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
+
+ }
+ resolve(result);
+ });
+ } else {
+ resolve(result);
+ }
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ cmd = 'netstat -ibndI ' + ifaceSanitized; // lgtm [js/shell-command-constructed-from-input]
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ lines = stdout.toString().split('\n');
+ for (let i = 1; i < lines.length; i++) {
+ const line = lines[i].replace(/ +/g, ' ').split(' ');
+ if (line && line[0] && line[7] && line[10]) {
+ rx_bytes = rx_bytes + parseInt(line[7]);
+ if (line[6].trim() !== '-') { rx_dropped = rx_dropped + parseInt(line[6]); }
+ if (line[5].trim() !== '-') { rx_errors = rx_errors + parseInt(line[5]); }
+ tx_bytes = tx_bytes + parseInt(line[10]);
+ if (line[12].trim() !== '-') { tx_dropped = tx_dropped + parseInt(line[12]); }
+ if (line[9].trim() !== '-') { tx_errors = tx_errors + parseInt(line[9]); }
+ operstate = 'up';
+ }
+ }
+ result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
+ }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ cmd = 'ifconfig ' + ifaceSanitized + ' | grep "status"'; // lgtm [js/shell-command-constructed-from-input]
+ exec(cmd, function (error, stdout) {
+ result.operstate = (stdout.toString().split(':')[1] || '').trim();
+ result.operstate = (result.operstate || '').toLowerCase();
+ result.operstate = (result.operstate === 'active' ? 'up' : (result.operstate === 'inactive' ? 'down' : 'unknown'));
+ cmd = 'netstat -bdI ' + ifaceSanitized; // lgtm [js/shell-command-constructed-from-input]
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ lines = stdout.toString().split('\n');
+ // if there is less than 2 lines, no information for this interface was found
+ if (lines.length > 1 && lines[1].trim() !== '') {
+ // skip header line
+ // use the second line because it is tied to the NIC instead of the ipv4 or ipv6 address
+ stats = lines[1].replace(/ +/g, ' ').split(' ');
+ const offset = stats.length > 11 ? 1 : 0;
+ rx_bytes = parseInt(stats[offset + 5]);
+ rx_dropped = parseInt(stats[offset + 10]);
+ rx_errors = parseInt(stats[offset + 4]);
+ tx_bytes = parseInt(stats[offset + 8]);
+ tx_dropped = parseInt(stats[offset + 10]);
+ tx_errors = parseInt(stats[offset + 7]);
+ result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, result.operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
+ }
+ }
+ resolve(result);
+ });
+ });
+ }
+ if (_windows) {
+ let perfData = [];
+ let ifaceName = ifaceSanitized;
+
+ // Performance Data
+ util.powerShell('Get-WmiObject Win32_PerfRawData_Tcpip_NetworkInterface | select Name,BytesReceivedPersec,PacketsReceivedErrors,PacketsReceivedDiscarded,BytesSentPersec,PacketsOutboundErrors,PacketsOutboundDiscarded | fl').then((stdout, error) => {
+ if (!error) {
+ const psections = stdout.toString().split(/\n\s*\n/);
+ perfData = parseLinesWindowsPerfData(psections);
+ }
+
+ // Network Interfaces
+ networkInterfaces(false).then(interfaces => {
+ // get bytes sent, received from perfData by name
+ rx_bytes = 0;
+ tx_bytes = 0;
+ perfData.forEach(detail => {
+ interfaces.forEach(det => {
+ if ((det.iface.toLowerCase() === ifaceSanitized.toLowerCase() ||
+ det.mac.toLowerCase() === ifaceSanitized.toLowerCase() ||
+ det.ip4.toLowerCase() === ifaceSanitized.toLowerCase() ||
+ det.ip6.toLowerCase() === ifaceSanitized.toLowerCase() ||
+ det.ifaceName.replace(/[()[\] ]+/g, '').replace(/#|\//g, '_').toLowerCase() === ifaceSanitized.replace(/[()[\] ]+/g, '').replace('#', '_').toLowerCase()) &&
+ (det.ifaceName.replace(/[()[\] ]+/g, '').replace(/#|\//g, '_').toLowerCase() === detail.name)) {
+ ifaceName = det.iface;
+ rx_bytes = detail.rx_bytes;
+ rx_dropped = detail.rx_dropped;
+ rx_errors = detail.rx_errors;
+ tx_bytes = detail.tx_bytes;
+ tx_dropped = detail.tx_dropped;
+ tx_errors = detail.tx_errors;
+ operstate = det.operstate;
+ }
+ });
+ });
+ if (rx_bytes && tx_bytes) {
+ result = calcNetworkSpeed(ifaceName, parseInt(rx_bytes), parseInt(tx_bytes), operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
+ }
+ resolve(result);
+ });
+ });
+ }
+ } else {
+ result.rx_bytes = _network[ifaceSanitized].rx_bytes;
+ result.tx_bytes = _network[ifaceSanitized].tx_bytes;
+ result.rx_sec = _network[ifaceSanitized].rx_sec;
+ result.tx_sec = _network[ifaceSanitized].tx_sec;
+ result.ms = _network[ifaceSanitized].last_ms;
+ result.operstate = _network[ifaceSanitized].operstate;
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.networkStats = networkStats;
+
+// --------------------------
+// NET - connections (sockets)
+
+function networkConnections(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = [];
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ let cmd = 'export LC_ALL=C; netstat -tunap | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN"; unset LC_ALL';
+ if (_freebsd || _openbsd || _netbsd) { cmd = 'export LC_ALL=C; netstat -na | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN"; unset LC_ALL'; }
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ if (!error && (lines.length > 1 || lines[0] != '')) {
+ lines.forEach(function (line) {
+ line = line.replace(/ +/g, ' ').split(' ');
+ if (line.length >= 7) {
+ let localip = line[3];
+ let localport = '';
+ let localaddress = line[3].split(':');
+ if (localaddress.length > 1) {
+ localport = localaddress[localaddress.length - 1];
+ localaddress.pop();
+ localip = localaddress.join(':');
+ }
+ let peerip = line[4];
+ let peerport = '';
+ let peeraddress = line[4].split(':');
+ if (peeraddress.length > 1) {
+ peerport = peeraddress[peeraddress.length - 1];
+ peeraddress.pop();
+ peerip = peeraddress.join(':');
+ }
+ let connstate = line[5];
+ let proc = line[6].split('/');
+
+ if (connstate) {
+ result.push({
+ protocol: line[0],
+ localAddress: localip,
+ localPort: localport,
+ peerAddress: peerip,
+ peerPort: peerport,
+ state: connstate,
+ pid: proc[0] && proc[0] !== '-' ? parseInt(proc[0], 10) : null,
+ process: proc[1] ? proc[1].split(' ')[0] : ''
+ });
+ }
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else {
+ cmd = 'ss -tunap | grep "ESTAB\\|SYN-SENT\\|SYN-RECV\\|FIN-WAIT1\\|FIN-WAIT2\\|TIME-WAIT\\|CLOSE\\|CLOSE-WAIT\\|LAST-ACK\\|LISTEN\\|CLOSING"';
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.replace(/ +/g, ' ').split(' ');
+ if (line.length >= 6) {
+ let localip = line[4];
+ let localport = '';
+ let localaddress = line[4].split(':');
+ if (localaddress.length > 1) {
+ localport = localaddress[localaddress.length - 1];
+ localaddress.pop();
+ localip = localaddress.join(':');
+ }
+ let peerip = line[5];
+ let peerport = '';
+ let peeraddress = line[5].split(':');
+ if (peeraddress.length > 1) {
+ peerport = peeraddress[peeraddress.length - 1];
+ peeraddress.pop();
+ peerip = peeraddress.join(':');
+ }
+ let connstate = line[1];
+ if (connstate === 'ESTAB') { connstate = 'ESTABLISHED'; }
+ if (connstate === 'TIME-WAIT') { connstate = 'TIME_WAIT'; }
+ let pid = null;
+ let process = '';
+ if (line.length >= 7 && line[6].indexOf('users:') > -1) {
+ let proc = line[6].replace('users:(("', '').replace(/"/g, '').split(',');
+ if (proc.length > 2) {
+ process = proc[0].split(' ')[0];
+ pid = parseInt(proc[1], 10);
+ }
+ }
+ if (connstate) {
+ result.push({
+ protocol: line[0],
+ localAddress: localip,
+ localPort: localport,
+ peerAddress: peerip,
+ peerPort: peerport,
+ state: connstate,
+ pid,
+ process
+ });
+ }
+ }
+ });
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ });
+ }
+ if (_darwin) {
+ let cmd = 'netstat -natv | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN"';
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ if (!error) {
+
+ let lines = stdout.toString().split('\n');
+
+ lines.forEach(function (line) {
+ line = line.replace(/ +/g, ' ').split(' ');
+ if (line.length >= 8) {
+ let localip = line[3];
+ let localport = '';
+ let localaddress = line[3].split('.');
+ if (localaddress.length > 1) {
+ localport = localaddress[localaddress.length - 1];
+ localaddress.pop();
+ localip = localaddress.join('.');
+ }
+ let peerip = line[4];
+ let peerport = '';
+ let peeraddress = line[4].split('.');
+ if (peeraddress.length > 1) {
+ peerport = peeraddress[peeraddress.length - 1];
+ peeraddress.pop();
+ peerip = peeraddress.join('.');
+ }
+ let connstate = line[5];
+ let pid = parseInt(line[8], 10);
+ if (connstate) {
+ result.push({
+ protocol: line[0],
+ localAddress: localip,
+ localPort: localport,
+ peerAddress: peerip,
+ peerPort: peerport,
+ state: connstate,
+ pid: pid,
+ process: ''
+ });
+ }
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ }
+ if (_windows) {
+ let cmd = 'netstat -nao';
+ try {
+ exec(cmd, util.execOptsWin, function (error, stdout) {
+ if (!error) {
+
+ let lines = stdout.toString().split('\r\n');
+
+ lines.forEach(function (line) {
+ line = line.trim().replace(/ +/g, ' ').split(' ');
+ if (line.length >= 4) {
+ let localip = line[1];
+ let localport = '';
+ let localaddress = line[1].split(':');
+ if (localaddress.length > 1) {
+ localport = localaddress[localaddress.length - 1];
+ localaddress.pop();
+ localip = localaddress.join(':');
+ }
+ localip = localip.replace(/\[/g, '').replace(/\]/g, '');
+ let peerip = line[2];
+ let peerport = '';
+ let peeraddress = line[2].split(':');
+ if (peeraddress.length > 1) {
+ peerport = peeraddress[peeraddress.length - 1];
+ peeraddress.pop();
+ peerip = peeraddress.join(':');
+ }
+ peerip = peerip.replace(/\[/g, '').replace(/\]/g, '');
+ let pid = util.toInt(line[4]);
+ let connstate = line[3];
+ if (connstate === 'HERGESTELLT') { connstate = 'ESTABLISHED'; }
+ if (connstate.startsWith('ABH')) { connstate = 'LISTEN'; }
+ if (connstate === 'SCHLIESSEN_WARTEN') { connstate = 'CLOSE_WAIT'; }
+ if (connstate === 'WARTEND') { connstate = 'TIME_WAIT'; }
+ if (connstate === 'SYN_GESENDET') { connstate = 'SYN_SENT'; }
+
+ if (connstate === 'LISTENING') { connstate = 'LISTEN'; }
+ if (connstate === 'SYN_RECEIVED') { connstate = 'SYN_RECV'; }
+ if (connstate === 'FIN_WAIT_1') { connstate = 'FIN_WAIT1'; }
+ if (connstate === 'FIN_WAIT_2') { connstate = 'FIN_WAIT2'; }
+ if (line[0].toLowerCase() !== 'udp' && connstate) {
+ result.push({
+ protocol: line[0].toLowerCase(),
+ localAddress: localip,
+ localPort: localport,
+ peerAddress: peerip,
+ peerPort: peerport,
+ state: connstate,
+ pid,
+ process: ''
+ });
+ } else if (line[0].toLowerCase() === 'udp') {
+ result.push({
+ protocol: line[0].toLowerCase(),
+ localAddress: localip,
+ localPort: localport,
+ peerAddress: peerip,
+ peerPort: peerport,
+ state: '',
+ pid: parseInt(line[3], 10),
+ process: ''
+ });
+ }
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.networkConnections = networkConnections;
+
+function networkGatewayDefault(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = '';
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ let cmd = 'ip route get 1';
+ try {
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ const line = lines && lines[0] ? lines[0] : '';
+ let parts = line.split(' via ');
+ if (parts && parts[1]) {
+ parts = parts[1].split(' ');
+ result = parts[0];
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_darwin) {
+ let cmd = 'route -n get default';
+ try {
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ if (!error) {
+ const lines = stdout.toString().split('\n').map(line => line.trim());
+ result = util.getValue(lines, 'gateway');
+ }
+ if (!result) {
+ cmd = 'netstat -rn | awk \'/default/ {print $2}\'';
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ const lines = stdout.toString().split('\n').map(line => line.trim());
+ result = lines.find(line => (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(line)));
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_windows) {
+ try {
+ exec('netstat -r', util.execOptsWin, function (error, stdout) {
+ const lines = stdout.toString().split(os.EOL);
+ lines.forEach(line => {
+ line = line.replace(/\s+/g, ' ').trim();
+ if (line.indexOf('0.0.0.0 0.0.0.0') > -1 && !(/[a-zA-Z]/.test(line))) {
+ const parts = line.split(' ');
+ if (parts.length >= 5 && (parts[parts.length - 3]).indexOf('.') > -1) {
+ result = parts[parts.length - 3];
+ }
+ }
+ });
+ if (!result) {
+ util.powerShell('Get-CimInstance -ClassName Win32_IP4RouteTable | Where-Object { $_.Destination -eq \'0.0.0.0\' -and $_.Mask -eq \'0.0.0.0\' }')
+ .then((data) => {
+ let lines = data.toString().split('\r\n');
+ if (lines.length > 1 && !result) {
+ result = util.getValue(lines, 'NextHop');
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ // } else {
+ // exec('ipconfig', util.execOptsWin, function (error, stdout) {
+ // let lines = stdout.toString().split('\r\n');
+ // lines.forEach(function (line) {
+ // line = line.trim().replace(/\. /g, '');
+ // line = line.trim().replace(/ +/g, '');
+ // const parts = line.split(':');
+ // if ((parts[0].toLowerCase().startsWith('standardgate') || parts[0].toLowerCase().indexOf('gateway') > -1 || parts[0].toLowerCase().indexOf('enlace') > -1) && parts[1]) {
+ // result = parts[1];
+ // }
+ // });
+ // if (callback) { callback(result); }
+ // resolve(result);
+ // });
+ }
+ });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.networkGatewayDefault = networkGatewayDefault;
diff --git a/MistyCore/node_modules/systeminformation/lib/osinfo.js b/MistyCore/node_modules/systeminformation/lib/osinfo.js
new file mode 100644
index 0000000..e79cbcf
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/osinfo.js
@@ -0,0 +1,1154 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// osinfo.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 3. Operating System
+// ----------------------------------------------------------------------------------
+
+const os = require('os');
+const fs = require('fs');
+const util = require('./util');
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+// --------------------------
+// Get current time and OS uptime
+
+function time() {
+ let t = new Date().toString().split(' ');
+ return {
+ current: Date.now(),
+ uptime: os.uptime(),
+ timezone: (t.length >= 7) ? t[5] : '',
+ timezoneName: Intl ? Intl.DateTimeFormat().resolvedOptions().timeZone : (t.length >= 7) ? t.slice(6).join(' ').replace(/\(/g, '').replace(/\)/g, '') : ''
+ };
+}
+
+exports.time = time;
+
+// --------------------------
+// Get logo filename of OS distribution
+
+function getLogoFile(distro) {
+ distro = distro || '';
+ distro = distro.toLowerCase();
+ let result = _platform;
+ if (_windows) {
+ result = 'windows';
+ }
+ else if (distro.indexOf('mac os') !== -1) {
+ result = 'apple';
+ }
+ else if (distro.indexOf('arch') !== -1) {
+ result = 'arch';
+ }
+ else if (distro.indexOf('centos') !== -1) {
+ result = 'centos';
+ }
+ else if (distro.indexOf('coreos') !== -1) {
+ result = 'coreos';
+ }
+ else if (distro.indexOf('debian') !== -1) {
+ result = 'debian';
+ }
+ else if (distro.indexOf('deepin') !== -1) {
+ result = 'deepin';
+ }
+ else if (distro.indexOf('elementary') !== -1) {
+ result = 'elementary';
+ }
+ else if (distro.indexOf('fedora') !== -1) {
+ result = 'fedora';
+ }
+ else if (distro.indexOf('gentoo') !== -1) {
+ result = 'gentoo';
+ }
+ else if (distro.indexOf('mageia') !== -1) {
+ result = 'mageia';
+ }
+ else if (distro.indexOf('mandriva') !== -1) {
+ result = 'mandriva';
+ }
+ else if (distro.indexOf('manjaro') !== -1) {
+ result = 'manjaro';
+ }
+ else if (distro.indexOf('mint') !== -1) {
+ result = 'mint';
+ }
+ else if (distro.indexOf('mx') !== -1) {
+ result = 'mx';
+ }
+ else if (distro.indexOf('openbsd') !== -1) {
+ result = 'openbsd';
+ }
+ else if (distro.indexOf('freebsd') !== -1) {
+ result = 'freebsd';
+ }
+ else if (distro.indexOf('opensuse') !== -1) {
+ result = 'opensuse';
+ }
+ else if (distro.indexOf('pclinuxos') !== -1) {
+ result = 'pclinuxos';
+ }
+ else if (distro.indexOf('puppy') !== -1) {
+ result = 'puppy';
+ }
+ else if (distro.indexOf('raspbian') !== -1) {
+ result = 'raspbian';
+ }
+ else if (distro.indexOf('reactos') !== -1) {
+ result = 'reactos';
+ }
+ else if (distro.indexOf('redhat') !== -1) {
+ result = 'redhat';
+ }
+ else if (distro.indexOf('slackware') !== -1) {
+ result = 'slackware';
+ }
+ else if (distro.indexOf('sugar') !== -1) {
+ result = 'sugar';
+ }
+ else if (distro.indexOf('steam') !== -1) {
+ result = 'steam';
+ }
+ else if (distro.indexOf('suse') !== -1) {
+ result = 'suse';
+ }
+ else if (distro.indexOf('mate') !== -1) {
+ result = 'ubuntu-mate';
+ }
+ else if (distro.indexOf('lubuntu') !== -1) {
+ result = 'lubuntu';
+ }
+ else if (distro.indexOf('xubuntu') !== -1) {
+ result = 'xubuntu';
+ }
+ else if (distro.indexOf('ubuntu') !== -1) {
+ result = 'ubuntu';
+ }
+ else if (distro.indexOf('solaris') !== -1) {
+ result = 'solaris';
+ }
+ else if (distro.indexOf('tails') !== -1) {
+ result = 'tails';
+ }
+ else if (distro.indexOf('feren') !== -1) {
+ result = 'ferenos';
+ }
+ else if (distro.indexOf('robolinux') !== -1) {
+ result = 'robolinux';
+ } else if (_linux && distro) {
+ result = distro.toLowerCase().trim().replace(/\s+/g, '-');
+ }
+ return result;
+}
+
+// --------------------------
+// FQDN
+
+function getFQDN() {
+ let fqdn = os.hostname;
+ if (_linux || _darwin) {
+ try {
+ const stdout = execSync('hostname -f');
+ fqdn = stdout.toString().split(os.EOL)[0];
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ try {
+ const stdout = execSync('hostname');
+ fqdn = stdout.toString().split(os.EOL)[0];
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (_windows) {
+ try {
+ const stdout = execSync('echo %COMPUTERNAME%.%USERDNSDOMAIN%', util.execOptsWin);
+ fqdn = stdout.toString().replace('.%USERDNSDOMAIN%', '').split(os.EOL)[0];
+ } catch (e) {
+ util.noop();
+ }
+ }
+ return fqdn;
+}
+
+// --------------------------
+// OS Information
+
+function osInfo(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = {
+
+ platform: (_platform === 'win32' ? 'Windows' : _platform),
+ distro: 'unknown',
+ release: 'unknown',
+ codename: '',
+ kernel: os.release(),
+ arch: os.arch(),
+ hostname: os.hostname(),
+ fqdn: getFQDN(),
+ codepage: '',
+ logofile: '',
+ serial: '',
+ build: '',
+ servicepack: '',
+ uefi: false
+ };
+
+ if (_linux) {
+
+ exec('cat /etc/*-release; cat /usr/lib/os-release; cat /etc/openwrt_release', function (error, stdout) {
+ /**
+ * @namespace
+ * @property {string} DISTRIB_ID
+ * @property {string} NAME
+ * @property {string} DISTRIB_RELEASE
+ * @property {string} VERSION_ID
+ * @property {string} DISTRIB_CODENAME
+ */
+ let release = {};
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ if (line.indexOf('=') !== -1) {
+ release[line.split('=')[0].trim().toUpperCase()] = line.split('=')[1].trim();
+ }
+ });
+ let releaseVersion = (release.VERSION || '').replace(/"/g, '');
+ let codename = (release.DISTRIB_CODENAME || release.VERSION_CODENAME || '').replace(/"/g, '');
+ if (releaseVersion.indexOf('(') >= 0) {
+ codename = releaseVersion.split('(')[1].replace(/[()]/g, '').trim();
+ releaseVersion = releaseVersion.split('(')[0].trim();
+ }
+ result.distro = (release.DISTRIB_ID || release.NAME || 'unknown').replace(/"/g, '');
+ result.logofile = getLogoFile(result.distro);
+ result.release = (releaseVersion || release.DISTRIB_RELEASE || release.VERSION_ID || 'unknown').replace(/"/g, '');
+ result.codename = codename;
+ result.codepage = util.getCodepage();
+ result.build = (release.BUILD_ID || '').replace(/"/g, '').trim();
+ isUefiLinux().then(uefi => {
+ result.uefi = uefi;
+ uuid().then((data) => {
+ result.serial = data.os;
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ });
+ });
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+
+ exec('sysctl kern.ostype kern.osrelease kern.osrevision kern.hostuuid machdep.bootmethod', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.distro = util.getValue(lines, 'kern.ostype');
+ result.logofile = getLogoFile(result.distro);
+ result.release = util.getValue(lines, 'kern.osrelease').split('-')[0];
+ result.serial = util.getValue(lines, 'kern.uuid');
+ result.codename = '';
+ result.codepage = util.getCodepage();
+ result.uefi = util.getValue(lines, 'machdep.bootmethod').toLowerCase().indexOf('uefi') >= 0;
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ exec('sw_vers; sysctl kern.ostype kern.osrelease kern.osrevision kern.uuid', function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ result.serial = util.getValue(lines, 'kern.uuid');
+ result.distro = util.getValue(lines, 'ProductName');
+ result.release = util.getValue(lines, 'ProductVersion');
+ result.build = util.getValue(lines, 'BuildVersion');
+ result.logofile = getLogoFile(result.distro);
+ result.codename = 'macOS';
+ result.codename = (result.release.indexOf('10.4') > -1 ? 'Mac OS X Tiger' : result.codename);
+ result.codename = (result.release.indexOf('10.4') > -1 ? 'Mac OS X Tiger' : result.codename);
+ result.codename = (result.release.indexOf('10.4') > -1 ? 'Mac OS X Tiger' : result.codename);
+ result.codename = (result.release.indexOf('10.5') > -1 ? 'Mac OS X Leopard' : result.codename);
+ result.codename = (result.release.indexOf('10.6') > -1 ? 'Mac OS X Snow Leopard' : result.codename);
+ result.codename = (result.release.indexOf('10.7') > -1 ? 'Mac OS X Lion' : result.codename);
+ result.codename = (result.release.indexOf('10.8') > -1 ? 'OS X Mountain Lion' : result.codename);
+ result.codename = (result.release.indexOf('10.9') > -1 ? 'OS X Mavericks' : result.codename);
+ result.codename = (result.release.indexOf('10.10') > -1 ? 'OS X Yosemite' : result.codename);
+ result.codename = (result.release.indexOf('10.11') > -1 ? 'OS X El Capitan' : result.codename);
+ result.codename = (result.release.indexOf('10.12') > -1 ? 'macOS Sierra' : result.codename);
+ result.codename = (result.release.indexOf('10.13') > -1 ? 'macOS High Sierra' : result.codename);
+ result.codename = (result.release.indexOf('10.14') > -1 ? 'macOS Mojave' : result.codename);
+ result.codename = (result.release.indexOf('10.15') > -1 ? 'macOS Catalina' : result.codename);
+ result.codename = (result.release.startsWith('11.') ? 'macOS Big Sur' : result.codename);
+ result.codename = (result.release.startsWith('12.') ? 'macOS Monterey' : result.codename);
+ result.codename = (result.release.startsWith('13.') ? 'macOS Ventura' : result.codename);
+ result.uefi = true;
+ result.codepage = util.getCodepage();
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ result.release = result.kernel;
+ exec('uname -o', function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ result.distro = lines[0];
+ result.logofile = getLogoFile(result.distro);
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_windows) {
+ result.logofile = getLogoFile();
+ result.release = result.kernel;
+ try {
+ const workload = [];
+ workload.push(util.powerShell('Get-WmiObject Win32_OperatingSystem | select Caption,SerialNumber,BuildNumber,ServicePackMajorVersion,ServicePackMinorVersion | fl'));
+ workload.push(util.powerShell('(Get-CimInstance Win32_ComputerSystem).HypervisorPresent'));
+ workload.push(util.powerShell('Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SystemInformation]::TerminalServerSession'));
+ util.promiseAll(
+ workload
+ ).then((data) => {
+ let lines = data.results[0] ? data.results[0].toString().split('\r\n') : [''];
+ result.distro = util.getValue(lines, 'Caption', ':').trim();
+ result.serial = util.getValue(lines, 'SerialNumber', ':').trim();
+ result.build = util.getValue(lines, 'BuildNumber', ':').trim();
+ result.servicepack = util.getValue(lines, 'ServicePackMajorVersion', ':').trim() + '.' + util.getValue(lines, 'ServicePackMinorVersion', ':').trim();
+ result.codepage = util.getCodepage();
+ const hyperv = data.results[1] ? data.results[1].toString().toLowerCase() : '';
+ result.hypervisor = hyperv.indexOf('true') !== -1;
+ const term = data.results[2] ? data.results[2].toString() : '';
+ result.remoteSession = (term.toString().toLowerCase().indexOf('true') >= 0);
+ isUefiWindows().then(uefi => {
+ result.uefi = uefi;
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.osInfo = osInfo;
+
+function isUefiLinux() {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ fs.stat('/sys/firmware/efi', function (err) {
+ if (!err) {
+ return resolve(true);
+ } else {
+ exec('dmesg | grep -E "EFI v"', function (error, stdout) {
+ if (!error) {
+ const lines = stdout.toString().split('\n');
+ return resolve(lines.length > 0);
+ }
+ return resolve(false);
+ });
+ }
+ });
+ });
+ });
+}
+
+function isUefiWindows() {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ try {
+ exec('findstr /C:"Detected boot environment" "%windir%\\Panther\\setupact.log"', util.execOptsWin, function (error, stdout) {
+ if (!error) {
+ const line = stdout.toString().split('\n\r')[0];
+ return resolve(line.toLowerCase().indexOf('efi') >= 0);
+ } else {
+ exec('echo %firmware_type%', util.execOptsWin, function (error, stdout) {
+ if (!error) {
+ const line = stdout.toString() || '';
+ return resolve(line.toLowerCase().indexOf('efi') >= 0);
+ } else {
+ return resolve(false);
+ }
+ });
+ }
+ });
+ } catch (e) {
+ return resolve(false);
+ }
+ });
+ });
+}
+
+function versions(apps, callback) {
+ let versionObject = {
+ kernel: os.release(),
+ openssl: '',
+ systemOpenssl: '',
+ systemOpensslLib: '',
+ node: process.versions.node,
+ v8: process.versions.v8,
+ npm: '',
+ yarn: '',
+ pm2: '',
+ gulp: '',
+ grunt: '',
+ git: '',
+ tsc: '',
+ mysql: '',
+ redis: '',
+ mongodb: '',
+ apache: '',
+ nginx: '',
+ php: '',
+ docker: '',
+ postfix: '',
+ postgresql: '',
+ perl: '',
+ python: '',
+ python3: '',
+ pip: '',
+ pip3: '',
+ java: '',
+ gcc: '',
+ virtualbox: '',
+ bash: '',
+ zsh: '',
+ fish: '',
+ powershell: '',
+ dotnet: ''
+ };
+
+ function checkVersionParam(apps) {
+ if (apps === '*') {
+ return {
+ versions: versionObject,
+ counter: 30
+ };
+ }
+ if (!Array.isArray(apps)) {
+ apps = apps.trim().toLowerCase().replace(/,+/g, '|').replace(/ /g, '|');
+ apps = apps.split('|');
+ const result = {
+ versions: {},
+ counter: 0
+ };
+ apps.forEach(el => {
+ if (el) {
+ for (let key in versionObject) {
+ if ({}.hasOwnProperty.call(versionObject, key)) {
+ if (key.toLowerCase() === el.toLowerCase() && !{}.hasOwnProperty.call(result.versions, key)) {
+ result.versions[key] = versionObject[key];
+ if (key === 'openssl') {
+ result.versions.systemOpenssl = '';
+ result.versions.systemOpensslLib = '';
+ }
+
+ if (!result.versions[key]) { result.counter++; }
+ }
+ }
+ }
+ }
+ });
+ return result;
+ }
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (util.isFunction(apps) && !callback) {
+ callback = apps;
+ apps = '*';
+ } else {
+ apps = apps || '*';
+ if (typeof apps !== 'string') {
+ if (callback) { callback({}); }
+ return resolve({});
+ }
+ }
+ const appsObj = checkVersionParam(apps);
+ let totalFunctions = appsObj.counter;
+
+ let functionProcessed = (function () {
+ return function () {
+ if (--totalFunctions === 0) {
+ if (callback) {
+ callback(appsObj.versions);
+ }
+ resolve(appsObj.versions);
+ }
+ };
+ })();
+
+ let cmd = '';
+ try {
+ if ({}.hasOwnProperty.call(appsObj.versions, 'openssl')) {
+ appsObj.versions.openssl = process.versions.openssl;
+ exec('openssl version', function (error, stdout) {
+ if (!error) {
+ let openssl_string = stdout.toString().split('\n')[0].trim();
+ let openssl = openssl_string.split(' ');
+ appsObj.versions.systemOpenssl = openssl.length > 0 ? openssl[1] : openssl[0];
+ appsObj.versions.systemOpensslLib = openssl.length > 0 ? openssl[0] : 'openssl';
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'npm')) {
+ exec('npm -v', function (error, stdout) {
+ if (!error) {
+ appsObj.versions.npm = stdout.toString().split('\n')[0];
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'pm2')) {
+ cmd = 'pm2';
+ if (_windows) {
+ cmd += '.cmd';
+ }
+ exec(`${cmd} -v`, function (error, stdout) {
+ if (!error) {
+ let pm2 = stdout.toString().split('\n')[0].trim();
+ if (!pm2.startsWith('[PM2]')) {
+ appsObj.versions.pm2 = pm2;
+ }
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'yarn')) {
+ exec('yarn --version', function (error, stdout) {
+ if (!error) {
+ appsObj.versions.yarn = stdout.toString().split('\n')[0];
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'gulp')) {
+ cmd = 'gulp';
+ if (_windows) {
+ cmd += '.cmd';
+ }
+ exec(`${cmd} --version`, function (error, stdout) {
+ if (!error) {
+ const gulp = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.gulp = (gulp.toLowerCase().split('version')[1] || '').trim();
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'tsc')) {
+ cmd = 'tsc';
+ if (_windows) {
+ cmd += '.cmd';
+ }
+ exec(`${cmd} --version`, function (error, stdout) {
+ if (!error) {
+ const tsc = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.tsc = (tsc.toLowerCase().split('version')[1] || '').trim();
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'grunt')) {
+ cmd = 'grunt';
+ if (_windows) {
+ cmd += '.cmd';
+ }
+ exec(`${cmd} --version`, function (error, stdout) {
+ if (!error) {
+ const grunt = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.grunt = (grunt.toLowerCase().split('cli v')[1] || '').trim();
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'git')) {
+ if (_darwin) {
+ const gitHomebrewExists = fs.existsSync('/usr/local/Cellar/git') || fs.existsSync('/opt/homebrew/bin/git');
+ if (util.darwinXcodeExists() || gitHomebrewExists) {
+ exec('git --version', function (error, stdout) {
+ if (!error) {
+ let git = stdout.toString().split('\n')[0] || '';
+ git = (git.toLowerCase().split('version')[1] || '').trim();
+ appsObj.versions.git = (git.split(' ')[0] || '').trim();
+ }
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ } else {
+ exec('git --version', function (error, stdout) {
+ if (!error) {
+ let git = stdout.toString().split('\n')[0] || '';
+ git = (git.toLowerCase().split('version')[1] || '').trim();
+ appsObj.versions.git = (git.split(' ')[0] || '').trim();
+ }
+ functionProcessed();
+ });
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'apache')) {
+ exec('apachectl -v 2>&1', function (error, stdout) {
+ if (!error) {
+ const apache = (stdout.toString().split('\n')[0] || '').split(':');
+ appsObj.versions.apache = (apache.length > 1 ? apache[1].replace('Apache', '').replace('/', '').split('(')[0].trim() : '');
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'nginx')) {
+ exec('nginx -v 2>&1', function (error, stdout) {
+ if (!error) {
+ const nginx = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.nginx = (nginx.toLowerCase().split('/')[1] || '').trim();
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'mysql')) {
+ exec('mysql -V', function (error, stdout) {
+ if (!error) {
+ let mysql = stdout.toString().split('\n')[0] || '';
+ mysql = mysql.toLowerCase();
+ if (mysql.indexOf(',') > -1) {
+ mysql = (mysql.split(',')[0] || '').trim();
+ const parts = mysql.split(' ');
+ appsObj.versions.mysql = (parts[parts.length - 1] || '').trim();
+ } else {
+ if (mysql.indexOf(' ver ') > -1) {
+ mysql = mysql.split(' ver ')[1];
+ appsObj.versions.mysql = mysql.split(' ')[0];
+ }
+ }
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'php')) {
+ exec('php -v', function (error, stdout) {
+ if (!error) {
+ const php = stdout.toString().split('\n')[0] || '';
+ let parts = php.split('(');
+ if (parts[0].indexOf('-')) {
+ parts = parts[0].split('-');
+ }
+ appsObj.versions.php = parts[0].replace(/[^0-9.]/g, '');
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'redis')) {
+ exec('redis-server --version', function (error, stdout) {
+ if (!error) {
+ const redis = stdout.toString().split('\n')[0] || '';
+ const parts = redis.split(' ');
+ appsObj.versions.redis = util.getValue(parts, 'v', '=', true);
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'docker')) {
+ exec('docker --version', function (error, stdout) {
+ if (!error) {
+ const docker = stdout.toString().split('\n')[0] || '';
+ const parts = docker.split(' ');
+ appsObj.versions.docker = parts.length > 2 && parts[2].endsWith(',') ? parts[2].slice(0, -1) : '';
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'postfix')) {
+ exec('postconf -d | grep mail_version', function (error, stdout) {
+ if (!error) {
+ const postfix = stdout.toString().split('\n') || [];
+ appsObj.versions.postfix = util.getValue(postfix, 'mail_version', '=', true);
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'mongodb')) {
+ exec('mongod --version', function (error, stdout) {
+ if (!error) {
+ const mongodb = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.mongodb = (mongodb.toLowerCase().split(',')[0] || '').replace(/[^0-9.]/g, '');
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'postgresql')) {
+ if (_linux) {
+ exec('locate bin/postgres', function (error, stdout) {
+ if (!error) {
+ const postgresqlBin = stdout.toString().split('\n').sort();
+ if (postgresqlBin.length) {
+ exec(postgresqlBin[postgresqlBin.length - 1] + ' -V', function (error, stdout) {
+ if (!error) {
+ const postgresql = stdout.toString().split('\n')[0].split(' ') || [];
+ appsObj.versions.postgresql = postgresql.length ? postgresql[postgresql.length - 1] : '';
+ }
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ } else {
+ exec('psql -V', function (error, stdout) {
+ if (!error) {
+ const postgresql = stdout.toString().split('\n')[0].split(' ') || [];
+ appsObj.versions.postgresql = postgresql.length ? postgresql[postgresql.length - 1] : '';
+ appsObj.versions.postgresql = appsObj.versions.postgresql.split('-')[0];
+ }
+ functionProcessed();
+ });
+ }
+ });
+ } else {
+ if (_windows) {
+ util.powerShell('Get-WmiObject Win32_Service | select caption | fl').then((stdout) => {
+ let serviceSections = stdout.split(/\n\s*\n/);
+ for (let i = 0; i < serviceSections.length; i++) {
+ if (serviceSections[i].trim() !== '') {
+ let lines = serviceSections[i].trim().split('\r\n');
+ let srvCaption = util.getValue(lines, 'caption', ':', true).toLowerCase();
+ if (srvCaption.indexOf('postgresql') > -1) {
+ const parts = srvCaption.split(' server ');
+ if (parts.length > 1) {
+ appsObj.versions.postgresql = parts[1];
+ }
+ }
+ }
+ }
+ functionProcessed();
+ });
+ } else {
+ exec('postgres -V', function (error, stdout) {
+ if (!error) {
+ const postgresql = stdout.toString().split('\n')[0].split(' ') || [];
+ appsObj.versions.postgresql = postgresql.length ? postgresql[postgresql.length - 1] : '';
+ }
+ functionProcessed();
+ });
+ }
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'perl')) {
+ exec('perl -v', function (error, stdout) {
+ if (!error) {
+ const perl = stdout.toString().split('\n') || '';
+ while (perl.length > 0 && perl[0].trim() === '') {
+ perl.shift();
+ }
+ if (perl.length > 0) {
+ appsObj.versions.perl = perl[0].split('(').pop().split(')')[0].replace('v', '');
+ }
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'python')) {
+ if (_darwin) {
+ const stdout = execSync('sw_vers');
+ const lines = stdout.toString().split('\n');
+ const osVersion = util.getValue(lines, 'ProductVersion', ':');
+ const gitHomebrewExists1 = fs.existsSync('/usr/local/Cellar/python');
+ const gitHomebrewExists2 = fs.existsSync('/opt/homebrew/bin/python');
+ if ((util.darwinXcodeExists() && util.semverCompare('12.0.1', osVersion) < 0) || gitHomebrewExists1 || gitHomebrewExists2) {
+ const cmd = gitHomebrewExists1 ? '/usr/local/Cellar/python -V 2>&1' : (gitHomebrewExists2 ? '/opt/homebrew/bin/python -V 2>&1' : 'python -V 2>&1');
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ const python = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.python = python.toLowerCase().replace('python', '').trim();
+ }
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ } else {
+ exec('python -V 2>&1', function (error, stdout) {
+ if (!error) {
+ const python = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.python = python.toLowerCase().replace('python', '').trim();
+ }
+ functionProcessed();
+ });
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'python3')) {
+ if (_darwin) {
+ const gitHomebrewExists = fs.existsSync('/usr/local/Cellar/python3') || fs.existsSync('/opt/homebrew/bin/python3');
+ if (util.darwinXcodeExists() || gitHomebrewExists) {
+ exec('python3 -V 2>&1', function (error, stdout) {
+ if (!error) {
+ const python = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.python3 = python.toLowerCase().replace('python', '').trim();
+ }
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ } else {
+ exec('python3 -V 2>&1', function (error, stdout) {
+ if (!error) {
+ const python = stdout.toString().split('\n')[0] || '';
+ appsObj.versions.python3 = python.toLowerCase().replace('python', '').trim();
+ }
+ functionProcessed();
+ });
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'pip')) {
+ if (_darwin) {
+ const gitHomebrewExists = fs.existsSync('/usr/local/Cellar/pip') || fs.existsSync('/opt/homebrew/bin/pip');
+ if (util.darwinXcodeExists() || gitHomebrewExists) {
+ exec('pip -V 2>&1', function (error, stdout) {
+ if (!error) {
+ const pip = stdout.toString().split('\n')[0] || '';
+ const parts = pip.split(' ');
+ appsObj.versions.pip = parts.length >= 2 ? parts[1] : '';
+ }
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ } else {
+ exec('pip -V 2>&1', function (error, stdout) {
+ if (!error) {
+ const pip = stdout.toString().split('\n')[0] || '';
+ const parts = pip.split(' ');
+ appsObj.versions.pip = parts.length >= 2 ? parts[1] : '';
+ }
+ functionProcessed();
+ });
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'pip3')) {
+ if (_darwin) {
+ const gitHomebrewExists = fs.existsSync('/usr/local/Cellar/pip3') || fs.existsSync('/opt/homebrew/bin/pip3');
+ if (util.darwinXcodeExists() || gitHomebrewExists) {
+ exec('pip3 -V 2>&1', function (error, stdout) {
+ if (!error) {
+ const pip = stdout.toString().split('\n')[0] || '';
+ const parts = pip.split(' ');
+ appsObj.versions.pip3 = parts.length >= 2 ? parts[1] : '';
+ }
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ } else {
+ exec('pip3 -V 2>&1', function (error, stdout) {
+ if (!error) {
+ const pip = stdout.toString().split('\n')[0] || '';
+ const parts = pip.split(' ');
+ appsObj.versions.pip3 = parts.length >= 2 ? parts[1] : '';
+ }
+ functionProcessed();
+ });
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'java')) {
+ if (_darwin) {
+ // check if any JVM is installed but avoid dialog box that Java needs to be installed
+ exec('/usr/libexec/java_home -V 2>&1', function (error, stdout) {
+ if (!error && stdout.toString().toLowerCase().indexOf('no java runtime') === -1) {
+ // now this can be done savely
+ exec('java -version 2>&1', function (error, stdout) {
+ if (!error) {
+ const java = stdout.toString().split('\n')[0] || '';
+ const parts = java.split('"');
+ appsObj.versions.java = parts.length === 3 ? parts[1].trim() : '';
+ }
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ });
+ } else {
+ exec('java -version 2>&1', function (error, stdout) {
+ if (!error) {
+ const java = stdout.toString().split('\n')[0] || '';
+ const parts = java.split('"');
+ appsObj.versions.java = parts.length === 3 ? parts[1].trim() : '';
+ }
+ functionProcessed();
+ });
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'gcc')) {
+ if ((_darwin && util.darwinXcodeExists()) || !_darwin) {
+ exec('gcc -dumpversion', function (error, stdout) {
+ if (!error) {
+ appsObj.versions.gcc = stdout.toString().split('\n')[0].trim() || '';
+ }
+ if (appsObj.versions.gcc.indexOf('.') > -1) {
+ functionProcessed();
+ } else {
+ exec('gcc --version', function (error, stdout) {
+ if (!error) {
+ const gcc = stdout.toString().split('\n')[0].trim();
+ if (gcc.indexOf('gcc') > -1 && gcc.indexOf(')') > -1) {
+ const parts = gcc.split(')');
+ appsObj.versions.gcc = parts[1].trim() || appsObj.versions.gcc;
+ }
+ }
+ functionProcessed();
+ });
+ }
+ });
+ } else {
+ functionProcessed();
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'virtualbox')) {
+ exec(util.getVboxmanage() + ' -v 2>&1', function (error, stdout) {
+ if (!error) {
+ const vbox = stdout.toString().split('\n')[0] || '';
+ const parts = vbox.split('r');
+ appsObj.versions.virtualbox = parts[0];
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'bash')) {
+ exec('bash --version', function (error, stdout) {
+ if (!error) {
+ const line = stdout.toString().split('\n')[0];
+ const parts = line.split(' version ');
+ if (parts.length > 1) {
+ appsObj.versions.bash = parts[1].split(' ')[0].split('(')[0];
+ }
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'zsh')) {
+ exec('zsh --version', function (error, stdout) {
+ if (!error) {
+ const line = stdout.toString().split('\n')[0];
+ const parts = line.split('zsh ');
+ if (parts.length > 1) {
+ appsObj.versions.zsh = parts[1].split(' ')[0];
+ }
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'fish')) {
+ exec('fish --version', function (error, stdout) {
+ if (!error) {
+ const line = stdout.toString().split('\n')[0];
+ const parts = line.split(' version ');
+ if (parts.length > 1) {
+ appsObj.versions.fish = parts[1].split(' ')[0];
+ }
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'powershell')) {
+ if (_windows) {
+ util.powerShell('$PSVersionTable').then(stdout => {
+ const lines = stdout.toString().split('\n').map(line => line.replace(/ +/g, ' ').replace(/ +/g, ':'));
+ appsObj.versions.powershell = util.getValue(lines, 'psversion');
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'dotnet')) {
+ if (_windows) {
+ util.powerShell('gci "HKLM:\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP" -recurse | gp -name Version,Release -EA 0 | where { $_.PSChildName -match "^(?!S)\\p{L}"} | select PSChildName, Version, Release').then(stdout => {
+ const lines = stdout.toString().split('\r\n');
+ let dotnet = '';
+ lines.forEach(line => {
+ line = line.replace(/ +/g, ' ');
+ const parts = line.split(' ');
+ dotnet = dotnet || (parts[0].toLowerCase().startsWith('client') && parts.length > 2 ? parts[1].trim() : (parts[0].toLowerCase().startsWith('full') && parts.length > 2 ? parts[1].trim() : ''));
+ });
+ appsObj.versions.dotnet = dotnet.trim();
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ }
+ } catch (e) {
+ if (callback) { callback(appsObj.versions); }
+ resolve(appsObj.versions);
+ }
+ });
+ });
+}
+
+exports.versions = versions;
+
+function shell(callback) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (_windows) {
+ resolve('cmd');
+ } else {
+ let result = '';
+ exec('echo $SHELL', function (error, stdout) {
+ if (!error) {
+ result = stdout.toString().split('\n')[0];
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ });
+ });
+}
+
+exports.shell = shell;
+
+function getUniqueMacAdresses() {
+ const ifaces = os.networkInterfaces();
+ let macs = [];
+ for (let dev in ifaces) {
+ if ({}.hasOwnProperty.call(ifaces, dev)) {
+ ifaces[dev].forEach(function (details) {
+ if (details && details.mac && details.mac !== '00:00:00:00:00:00') {
+ const mac = details.mac.toLowerCase();
+ if (macs.indexOf(mac) === -1) {
+ macs.push(mac);
+ }
+ }
+ });
+ }
+ }
+ macs = macs.sort(function (a, b) {
+ if (a < b) { return -1; }
+ if (a > b) { return 1; }
+ return 0;
+ });
+ return macs;
+}
+
+function uuid(callback) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = {
+ os: '',
+ hardware: '',
+ macs: getUniqueMacAdresses()
+ };
+ let parts;
+
+ if (_darwin) {
+ exec('system_profiler SPHardwareDataType -json', function (error, stdout) {
+ if (!error) {
+ try {
+ const jsonObj = JSON.parse(stdout.toString());
+ if (jsonObj.SPHardwareDataType && jsonObj.SPHardwareDataType.length > 0) {
+ const spHardware = jsonObj.SPHardwareDataType[0];
+ result.os = spHardware.platform_UUID.toLowerCase();
+ result.hardware = spHardware.serial_number;
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_linux) {
+ const cmd = `echo -n "os: "; cat /var/lib/dbus/machine-id 2> /dev/null; echo;
+echo -n "os: "; cat /etc/machine-id 2> /dev/null; echo;
+echo -n "hardware: "; cat /sys/class/dmi/id/product_uuid 2> /dev/null; echo;`;
+ exec(cmd, function (error, stdout) {
+ const lines = stdout.toString().split('\n');
+ result.os = util.getValue(lines, 'os').toLowerCase();
+ result.hardware = util.getValue(lines, 'hardware').toLowerCase();
+ if (!result.hardware) {
+ const lines = fs.readFileSync('/proc/cpuinfo', { encoding: 'utf8' }).toString().split('\n');
+ const serial = util.getValue(lines, 'serial');
+ result.hardware = serial || '';
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ exec('sysctl -i kern.hostid kern.hostuuid', function (error, stdout) {
+ const lines = stdout.toString().split('\n');
+ result.os = util.getValue(lines, 'kern.hostid', ':').toLowerCase();
+ result.hardware = util.getValue(lines, 'kern.hostuuid', ':').toLowerCase();
+ if (result.os.indexOf('unknown') >= 0) { result.os = ''; }
+ if (result.hardware.indexOf('unknown') >= 0) { result.hardware = ''; }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_windows) {
+ let sysdir = '%windir%\\System32';
+ if (process.arch === 'ia32' && Object.prototype.hasOwnProperty.call(process.env, 'PROCESSOR_ARCHITEW6432')) {
+ sysdir = '%windir%\\sysnative\\cmd.exe /c %windir%\\System32';
+ }
+ util.powerShell('Get-WmiObject Win32_ComputerSystemProduct | select UUID | fl').then((stdout) => {
+ let lines = stdout.split('\r\n');
+ result.hardware = util.getValue(lines, 'uuid', ':').toLowerCase();
+ exec(`${sysdir}\\reg query "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid`, util.execOptsWin, function (error, stdout) {
+ parts = stdout.toString().split('\n\r')[0].split('REG_SZ');
+ result.os = parts.length > 1 ? parts[1].replace(/\r+|\n+|\s+/ig, '').toLowerCase() : '';
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ });
+ }
+ });
+ });
+}
+
+exports.uuid = uuid;
diff --git a/MistyCore/node_modules/systeminformation/lib/printer.js b/MistyCore/node_modules/systeminformation/lib/printer.js
new file mode 100644
index 0000000..b437489
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/printer.js
@@ -0,0 +1,210 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// printers.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 15. printers
+// ----------------------------------------------------------------------------------
+
+const exec = require('child_process').exec;
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+const winPrinterStatus = {
+ 1: 'Other',
+ 2: 'Unknown',
+ 3: 'Idle',
+ 4: 'Printing',
+ 5: 'Warmup',
+ 6: 'Stopped Printing',
+ 7: 'Offline',
+};
+
+function parseLinuxCupsHeader(lines) {
+ const result = {};
+ if (lines && lines.length) {
+ if (lines[0].indexOf(' CUPS v') > 0) {
+ const parts = lines[0].split(' CUPS v');
+ result.cupsVersion = parts[1];
+ }
+ }
+ return result;
+}
+
+function parseLinuxCupsPrinter(lines) {
+ const result = {};
+ const printerId = util.getValue(lines, 'PrinterId', ' ');
+ result.id = printerId ? parseInt(printerId, 10) : null;
+ result.name = util.getValue(lines, 'Info', ' ');
+ result.model = lines.length > 0 && lines[0] ? lines[0].split(' ')[0] : '';
+ result.uri = util.getValue(lines, 'DeviceURI', ' ');
+ result.uuid = util.getValue(lines, 'UUID', ' ');
+ result.status = util.getValue(lines, 'State', ' ');
+ result.local = util.getValue(lines, 'Location', ' ').toLowerCase().startsWith('local');
+ result.default = null;
+ result.shared = util.getValue(lines, 'Shared', ' ').toLowerCase().startsWith('yes');
+
+ return result;
+}
+
+function parseLinuxLpstatPrinter(lines, id) {
+ const result = {};
+ result.id = id;
+ result.name = util.getValue(lines, 'Description', ':', true);
+ result.model = lines.length > 0 && lines[0] ? lines[0].split(' ')[0] : '';
+ result.uri = null;
+ result.uuid = null;
+ result.status = lines.length > 0 && lines[0] ? (lines[0].indexOf(' idle') > 0 ? 'idle' : (lines[0].indexOf(' printing') > 0 ? 'printing' : 'unknown')) : null;
+ result.local = util.getValue(lines, 'Location', ':', true).toLowerCase().startsWith('local');
+ result.default = null;
+ result.shared = util.getValue(lines, 'Shared', ' ').toLowerCase().startsWith('yes');
+
+ return result;
+}
+
+function parseDarwinPrinters(printerObject, id) {
+ const result = {};
+ const uriParts = printerObject.uri.split('/');
+ result.id = id;
+ result.name = printerObject._name;
+ result.model = uriParts.length ? uriParts[uriParts.length - 1] : '';
+ result.uri = printerObject.uri;
+ result.uuid = null;
+ result.status = printerObject.status;
+ result.local = printerObject.printserver === 'local';
+ result.default = printerObject.default === 'yes';
+ result.shared = printerObject.shared === 'yes';
+
+ return result;
+}
+
+function parseWindowsPrinters(lines, id) {
+ const result = {};
+ const status = parseInt(util.getValue(lines, 'PrinterStatus', ':'), 10);
+
+ result.id = id;
+ result.name = util.getValue(lines, 'name', ':');
+ result.model = util.getValue(lines, 'DriverName', ':');
+ result.uri = null;
+ result.uuid = null;
+ result.status = winPrinterStatus[status] ? winPrinterStatus[status] : null;
+ result.local = util.getValue(lines, 'Local', ':').toUpperCase() === 'TRUE';
+ result.default = util.getValue(lines, 'Default', ':').toUpperCase() === 'TRUE';
+ result.shared = util.getValue(lines, 'Shared', ':').toUpperCase() === 'TRUE';
+
+ return result;
+}
+
+function printer(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = [];
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ let cmd = 'cat /etc/cups/printers.conf 2>/dev/null';
+ exec(cmd, function (error, stdout) {
+ // printers.conf
+ if (!error) {
+ const parts = stdout.toString().split('<Printer ');
+ const printerHeader = parseLinuxCupsHeader(parts[0]);
+ for (let i = 1; i < parts.length; i++) {
+ const printers = parseLinuxCupsPrinter(parts[i].split('\n'));
+ if (printers.name) {
+ printers.engine = 'CUPS';
+ printers.engineVersion = printerHeader.cupsVersion;
+ result.push(printers);
+ }
+ }
+ }
+ if (result.length === 0) {
+ if (_linux) {
+ cmd = 'export LC_ALL=C; lpstat -lp 2>/dev/null; unset LC_ALL';
+ // lpstat
+ exec(cmd, function (error, stdout) {
+ const parts = ('\n' + stdout.toString()).split('\nprinter ');
+ for (let i = 1; i < parts.length; i++) {
+ const printers = parseLinuxLpstatPrinter(parts[i].split('\n'), i);
+ result.push(printers);
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ }
+ if (_darwin) {
+ let cmd = 'system_profiler SPPrintersDataType -json';
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ try {
+ const outObj = JSON.parse(stdout.toString());
+ if (outObj.SPPrintersDataType && outObj.SPPrintersDataType.length) {
+ for (let i = 0; i < outObj.SPPrintersDataType.length; i++) {
+ const printer = parseDarwinPrinters(outObj.SPPrintersDataType[i], i);
+ result.push(printer);
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_windows) {
+ util.powerShell('Get-WmiObject Win32_Printer | select PrinterStatus,Name,DriverName,Local,Default,Shared | fl').then((stdout, error) => {
+ if (!error) {
+ const parts = stdout.toString().split(/\n\s*\n/);
+ for (let i = 0; i < parts.length; i++) {
+ const printer = parseWindowsPrinters(parts[i].split('\n'), i);
+ if (printer.name || printer.model) {
+ result.push(parseWindowsPrinters(parts[i].split('\n'), i));
+ }
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ resolve(null);
+ }
+ });
+ });
+}
+
+exports.printer = printer;
diff --git a/MistyCore/node_modules/systeminformation/lib/processes.js b/MistyCore/node_modules/systeminformation/lib/processes.js
new file mode 100644
index 0000000..f52a3d1
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/processes.js
@@ -0,0 +1,1274 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// processes.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 10. Processes
+// ----------------------------------------------------------------------------------
+
+const os = require('os');
+const fs = require('fs');
+const path = require('path');
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+const _processes_cpu = {
+ all: 0,
+ all_utime: 0,
+ all_stime: 0,
+ list: {},
+ ms: 0,
+ result: {}
+};
+const _services_cpu = {
+ all: 0,
+ all_utime: 0,
+ all_stime: 0,
+ list: {},
+ ms: 0,
+ result: {}
+};
+const _process_cpu = {
+ all: 0,
+ all_utime: 0,
+ all_stime: 0,
+ list: {},
+ ms: 0,
+ result: {}
+};
+
+const _winStatusValues = {
+ '0': 'unknown',
+ '1': 'other',
+ '2': 'ready',
+ '3': 'running',
+ '4': 'blocked',
+ '5': 'suspended blocked',
+ '6': 'suspended ready',
+ '7': 'terminated',
+ '8': 'stopped',
+ '9': 'growing',
+};
+
+
+function parseTimeWin(time) {
+ time = time || '';
+ if (time) {
+ return (time.substr(0, 4) + '-' + time.substr(4, 2) + '-' + time.substr(6, 2) + ' ' + time.substr(8, 2) + ':' + time.substr(10, 2) + ':' + time.substr(12, 2));
+ } else {
+ return '';
+ }
+}
+
+function parseTimeUnix(time) {
+ let result = time;
+ let parts = time.replace(/ +/g, ' ').split(' ');
+ if (parts.length === 5) {
+ result = parts[4] + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(parts[1].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + parts[2]).slice(-2) + ' ' + parts[3];
+ }
+ return result;
+}
+
+function parseElapsedTime(etime) {
+ let current = new Date();
+ current = new Date(current.getTime() - current.getTimezoneOffset() * 60000);
+
+ const elapsed = etime.split('-');
+
+ const timeIndex = elapsed.length - 1;
+ const days = timeIndex > 0 ? parseInt(elapsed[timeIndex - 1]) : 0;
+
+ const timeStr = elapsed[timeIndex].split(':');
+ const hours = timeStr.length === 3 ? parseInt(timeStr[0] || 0) : 0;
+ const mins = parseInt(timeStr[timeStr.length === 3 ? 1 : 0] || 0);
+ const secs = parseInt(timeStr[timeStr.length === 3 ? 2 : 1] || 0);
+ const ms = (((((days * 24 + hours) * 60) + mins) * 60 + secs) * 1000);
+
+ const res = new Date(current.getTime() - ms);
+ return res.toISOString().substring(0, 10) + ' ' + res.toISOString().substring(11, 19);
+}
+
+// --------------------------
+// PS - services
+// pass a comma separated string with services to check (mysql, apache, postgresql, ...)
+// this function gives an array back, if the services are running.
+
+function services(srv, callback) {
+
+ // fallback - if only callback is given
+ if (util.isFunction(srv) && !callback) {
+ callback = srv;
+ srv = '';
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ if (typeof srv !== 'string') {
+ if (callback) { callback([]); }
+ return resolve([]);
+ }
+
+ if (srv) {
+ let srvString = '';
+ srvString.__proto__.toLowerCase = util.stringToLower;
+ srvString.__proto__.replace = util.stringReplace;
+ srvString.__proto__.trim = util.stringTrim;
+
+ const s = util.sanitizeShellString(srv);
+ for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
+ if (s[i] !== undefined) {
+ srvString = srvString + s[i];
+ }
+ }
+
+ srvString = srvString.trim().toLowerCase().replace(/, /g, '|').replace(/,+/g, '|');
+ if (srvString === '') {
+ srvString = '*';
+ }
+ if (util.isPrototypePolluted() && srvString !== '*') {
+ srvString = '------';
+ }
+ let srvs = srvString.split('|');
+ let result = [];
+ let dataSrv = [];
+
+ if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
+ if ((_linux || _freebsd || _openbsd || _netbsd) && srvString === '*') {
+ try {
+ const tmpsrv = execSync('systemctl --type=service --no-legend 2> /dev/null').toString().split('\n');
+ srvs = [];
+ for (const s of tmpsrv) {
+ const name = s.split('.service')[0];
+ if (name) {
+ srvs.push(name.trim());
+ }
+ }
+ srvString = srvs.join('|');
+ } catch (d) {
+ try {
+ srvString = '';
+ const tmpsrv = execSync('service --status-all 2> /dev/null').toString().split('\n');
+ for (const s of tmpsrv) {
+ const parts = s.split(']');
+ if (parts.length === 2) {
+ srvString += (srvString !== '' ? '|' : '') + parts[1].trim();
+ }
+ }
+ srvs = srvString.split('|');
+ } catch (e) {
+ try {
+ const srvStr = execSync('ls /etc/init.d/ -m 2> /dev/null').toString().split('\n').join('');
+ srvString = '';
+ if (srvStr) {
+ const tmpsrv = srvStr.split(',');
+ for (const s of tmpsrv) {
+ const name = s.trim();
+ if (name) {
+ srvString += (srvString !== '' ? '|' : '') + name;
+ }
+ }
+ srvs = srvString.split('|');
+ }
+ } catch (f) {
+ srvString = '';
+ srvs = [];
+ }
+ }
+ }
+ }
+ if ((_darwin) && srvString === '*') { // service enumeration not yet suported on mac OS
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ let args = (_darwin) ? ['-caxo', 'pcpu,pmem,pid,command'] : ['-axo', 'pcpu,pmem,pid,command'];
+ if (srvString !== '' && srvs.length > 0) {
+ util.execSafe('ps', args).then((stdout) => {
+ if (stdout) {
+ let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
+ srvs.forEach(function (srv) {
+ let ps;
+ if (_darwin) {
+ ps = lines.filter(function (e) {
+ return (e.toLowerCase().indexOf(srv) !== -1);
+ });
+
+ } else {
+ ps = lines.filter(function (e) {
+ return (e.toLowerCase().indexOf(' ' + srv + ':') !== -1) || (e.toLowerCase().indexOf('/' + srv) !== -1);
+ });
+ }
+ const pids = [];
+ for (const p of ps) {
+ const pid = p.trim().split(' ')[2];
+ if (pid) {
+ pids.push(parseInt(pid, 10));
+ }
+ }
+ result.push({
+ name: srv,
+ running: ps.length > 0,
+ startmode: '',
+ pids: pids,
+ cpu: parseFloat((ps.reduce(function (pv, cv) {
+ return pv + parseFloat(cv.trim().split(' ')[0]);
+ }, 0)).toFixed(2)),
+ mem: parseFloat((ps.reduce(function (pv, cv) {
+ return pv + parseFloat(cv.trim().split(' ')[1]);
+ }, 0)).toFixed(2))
+ });
+ });
+ if (_linux) {
+ // calc process_cpu - ps is not accurate in linux!
+ let cmd = 'cat /proc/stat | grep "cpu "';
+ for (let i in result) {
+ for (let j in result[i].pids) {
+ cmd += (';cat /proc/' + result[i].pids[j] + '/stat');
+ }
+ }
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ let curr_processes = stdout.toString().split('\n');
+
+ // first line (all - /proc/stat)
+ let all = parseProcStat(curr_processes.shift());
+
+ // process
+ let list_new = {};
+ let resultProcess = {};
+ curr_processes.forEach((element) => {
+ resultProcess = calcProcStatLinux(element, all, _services_cpu);
+
+ if (resultProcess.pid) {
+ let listPos = -1;
+ for (let i in result) {
+ for (let j in result[i].pids) {
+ if (parseInt(result[i].pids[j]) === parseInt(resultProcess.pid)) {
+ listPos = i;
+ }
+ }
+ }
+ if (listPos >= 0) {
+ result[listPos].cpu += resultProcess.cpuu + resultProcess.cpus;
+ }
+
+ // save new values
+ list_new[resultProcess.pid] = {
+ cpuu: resultProcess.cpuu,
+ cpus: resultProcess.cpus,
+ utime: resultProcess.utime,
+ stime: resultProcess.stime,
+ cutime: resultProcess.cutime,
+ cstime: resultProcess.cstime
+ };
+ }
+ });
+
+ // store old values
+ _services_cpu.all = all;
+ _services_cpu.list = Object.assign({}, list_new);
+ _services_cpu.ms = Date.now() - _services_cpu.ms;
+ _services_cpu.result = Object.assign({}, result);
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } else {
+ args = ['-o', 'comm'];
+ util.execSafe('ps', args).then((stdout) => {
+ if (stdout) {
+ let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
+ srvs.forEach(function (srv) {
+ let ps = lines.filter(function (e) {
+ return e.indexOf(srv) !== -1;
+ });
+ result.push({
+ name: srv,
+ running: ps.length > 0,
+ startmode: '',
+ cpu: 0,
+ mem: 0
+ });
+ });
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ srvs.forEach(function (srv) {
+ result.push({
+ name: srv,
+ running: false,
+ startmode: '',
+ cpu: 0,
+ mem: 0
+ });
+ });
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ }
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ if (_windows) {
+ try {
+ let wincommand = 'Get-WmiObject Win32_Service';
+ if (srvs[0] !== '*') {
+ wincommand += ' -Filter "';
+ srvs.forEach((srv) => {
+ wincommand += `Name='${srv}' or `;
+ });
+ wincommand = `${wincommand.slice(0, -4)}"`;
+ }
+ wincommand += ' | select Name,Caption,Started,StartMode,ProcessId | fl';
+ util.powerShell(wincommand).then((stdout, error) => {
+ if (!error) {
+ let serviceSections = stdout.split(/\n\s*\n/);
+ serviceSections.forEach((element) => {
+ if (element.trim() !== '') {
+ let lines = element.trim().split('\r\n');
+ let srvName = util.getValue(lines, 'Name', ':', true).toLowerCase();
+ let srvCaption = util.getValue(lines, 'Caption', ':', true).toLowerCase();
+ let started = util.getValue(lines, 'Started', ':', true);
+ let startMode = util.getValue(lines, 'StartMode', ':', true);
+ let pid = util.getValue(lines, 'ProcessId', ':', true);
+ if (srvString === '*' || srvs.indexOf(srvName) >= 0 || srvs.indexOf(srvCaption) >= 0) {
+ result.push({
+ name: srvName,
+ running: (started.toLowerCase() === 'true'),
+ startmode: startMode,
+ pids: [pid],
+ cpu: 0,
+ mem: 0
+ });
+ dataSrv.push(srvName);
+ dataSrv.push(srvCaption);
+ }
+ }
+
+ });
+
+ if (srvString !== '*') {
+ let srvsMissing = srvs.filter(function (e) {
+ return dataSrv.indexOf(e) === -1;
+ });
+ srvsMissing.forEach(function (srvName) {
+ result.push({
+ name: srvName,
+ running: false,
+ startmode: '',
+ pids: [],
+ cpu: 0,
+ mem: 0
+ });
+ });
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ srvs.forEach(function (srvName) {
+ result.push({
+ name: srvName,
+ running: false,
+ startmode: '',
+ cpu: 0,
+ mem: 0
+ });
+ });
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ } else {
+ if (callback) { callback([]); }
+ resolve([]);
+ }
+ });
+ });
+}
+
+exports.services = services;
+
+function parseProcStat(line) {
+ let parts = line.replace(/ +/g, ' ').split(' ');
+ let user = (parts.length >= 2 ? parseInt(parts[1]) : 0);
+ let nice = (parts.length >= 3 ? parseInt(parts[2]) : 0);
+ let system = (parts.length >= 4 ? parseInt(parts[3]) : 0);
+ let idle = (parts.length >= 5 ? parseInt(parts[4]) : 0);
+ let iowait = (parts.length >= 6 ? parseInt(parts[5]) : 0);
+ let irq = (parts.length >= 7 ? parseInt(parts[6]) : 0);
+ let softirq = (parts.length >= 8 ? parseInt(parts[7]) : 0);
+ let steal = (parts.length >= 9 ? parseInt(parts[8]) : 0);
+ let guest = (parts.length >= 10 ? parseInt(parts[9]) : 0);
+ let guest_nice = (parts.length >= 11 ? parseInt(parts[10]) : 0);
+ return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
+}
+
+function calcProcStatLinux(line, all, _cpu_old) {
+ let statparts = line.replace(/ +/g, ' ').split(')');
+ if (statparts.length >= 2) {
+ let parts = statparts[1].split(' ');
+ if (parts.length >= 16) {
+ let pid = parseInt(statparts[0].split(' ')[0]);
+ let utime = parseInt(parts[12]);
+ let stime = parseInt(parts[13]);
+ let cutime = parseInt(parts[14]);
+ let cstime = parseInt(parts[15]);
+
+ // calc
+ let cpuu = 0;
+ let cpus = 0;
+ if (_cpu_old.all > 0 && _cpu_old.list[pid]) {
+ cpuu = (utime + cutime - _cpu_old.list[pid].utime - _cpu_old.list[pid].cutime) / (all - _cpu_old.all) * 100; // user
+ cpus = (stime + cstime - _cpu_old.list[pid].stime - _cpu_old.list[pid].cstime) / (all - _cpu_old.all) * 100; // system
+ } else {
+ cpuu = (utime + cutime) / (all) * 100; // user
+ cpus = (stime + cstime) / (all) * 100; // system
+ }
+ return {
+ pid: pid,
+ utime: utime,
+ stime: stime,
+ cutime: cutime,
+ cstime: cstime,
+ cpuu: cpuu,
+ cpus: cpus
+ };
+ } else {
+ return {
+ pid: 0,
+ utime: 0,
+ stime: 0,
+ cutime: 0,
+ cstime: 0,
+ cpuu: 0,
+ cpus: 0
+ };
+ }
+ } else {
+ return {
+ pid: 0,
+ utime: 0,
+ stime: 0,
+ cutime: 0,
+ cstime: 0,
+ cpuu: 0,
+ cpus: 0
+ };
+ }
+}
+
+function calcProcStatWin(procStat, all, _cpu_old) {
+ // calc
+ let cpuu = 0;
+ let cpus = 0;
+ if (_cpu_old.all > 0 && _cpu_old.list[procStat.pid]) {
+ cpuu = (procStat.utime - _cpu_old.list[procStat.pid].utime) / (all - _cpu_old.all) * 100; // user
+ cpus = (procStat.stime - _cpu_old.list[procStat.pid].stime) / (all - _cpu_old.all) * 100; // system
+ } else {
+ cpuu = (procStat.utime) / (all) * 100; // user
+ cpus = (procStat.stime) / (all) * 100; // system
+ }
+ return {
+ pid: procStat.pid,
+ utime: cpuu > 0 ? procStat.utime : 0,
+ stime: cpus > 0 ? procStat.stime : 0,
+ cpuu: cpuu > 0 ? cpuu : 0,
+ cpus: cpus > 0 ? cpus : 0
+ };
+}
+
+
+
+// --------------------------
+// running processes
+
+function processes(callback) {
+
+ let parsedhead = [];
+
+ function getName(command) {
+ command = command || '';
+ let result = command.split(' ')[0];
+ if (result.substr(-1) === ':') {
+ result = result.substr(0, result.length - 1);
+ }
+ if (result.substr(0, 1) !== '[') {
+ let parts = result.split('/');
+ if (isNaN(parseInt(parts[parts.length - 1]))) {
+ result = parts[parts.length - 1];
+ } else {
+ result = parts[0];
+ }
+ }
+ return result;
+ }
+
+ function parseLine(line) {
+
+ let offset = 0;
+ let offset2 = 0;
+
+ function checkColumn(i) {
+ offset = offset2;
+ if (parsedhead[i]) {
+ offset2 = line.substring(parsedhead[i].to + offset, 10000).indexOf(' ');
+ } else {
+ offset2 = 10000;
+ }
+ }
+
+ checkColumn(0);
+ const pid = parseInt(line.substring(parsedhead[0].from + offset, parsedhead[0].to + offset2));
+ checkColumn(1);
+ const ppid = parseInt(line.substring(parsedhead[1].from + offset, parsedhead[1].to + offset2));
+ checkColumn(2);
+ const cpu = parseFloat(line.substring(parsedhead[2].from + offset, parsedhead[2].to + offset2).replace(/,/g, '.'));
+ checkColumn(3);
+ const mem = parseFloat(line.substring(parsedhead[3].from + offset, parsedhead[3].to + offset2).replace(/,/g, '.'));
+ checkColumn(4);
+ const priority = parseInt(line.substring(parsedhead[4].from + offset, parsedhead[4].to + offset2));
+ checkColumn(5);
+ const vsz = parseInt(line.substring(parsedhead[5].from + offset, parsedhead[5].to + offset2));
+ checkColumn(6);
+ const rss = parseInt(line.substring(parsedhead[6].from + offset, parsedhead[6].to + offset2));
+ checkColumn(7);
+ const nice = parseInt(line.substring(parsedhead[7].from + offset, parsedhead[7].to + offset2)) || 0;
+ checkColumn(8);
+ const started = !_sunos ? parseElapsedTime(line.substring(parsedhead[8].from + offset, parsedhead[8].to + offset2).trim()) : parseTimeUnix(line.substring(parsedhead[8].from + offset, parsedhead[8].to + offset2).trim());
+ checkColumn(9);
+ let state = line.substring(parsedhead[9].from + offset, parsedhead[9].to + offset2).trim();
+ state = (state[0] === 'R' ? 'running' : (state[0] === 'S' ? 'sleeping' : (state[0] === 'T' ? 'stopped' : (state[0] === 'W' ? 'paging' : (state[0] === 'X' ? 'dead' : (state[0] === 'Z' ? 'zombie' : ((state[0] === 'D' || state[0] === 'U') ? 'blocked' : 'unknown')))))));
+ checkColumn(10);
+ let tty = line.substring(parsedhead[10].from + offset, parsedhead[10].to + offset2).trim();
+ if (tty === '?' || tty === '??') { tty = ''; }
+ checkColumn(11);
+ const user = line.substring(parsedhead[11].from + offset, parsedhead[11].to + offset2).trim();
+ checkColumn(12);
+ let cmdPath = '';
+ let command = '';
+ let params = '';
+ let fullcommand = line.substring(parsedhead[12].from + offset, parsedhead[12].to + offset2).trim();
+ if (fullcommand.substr(fullcommand.length - 1) === ']') { fullcommand = fullcommand.slice(0, -1); }
+ if (fullcommand.substr(0, 1) === '[') { command = fullcommand.substring(1); }
+ else {
+ const p1 = fullcommand.indexOf('(');
+ const p2 = fullcommand.indexOf(')');
+ const p3 = fullcommand.indexOf('/');
+ const p4 = fullcommand.indexOf(':');
+ if (p1 < p2 && p1 < p3 && p3 < p2) {
+ command = fullcommand.split(' ')[0];
+ command = command.replace(/:/g, '');
+ } else {
+ if (p4 > 0 && (p3 === -1 || p3 > 3)) {
+ command = fullcommand.split(' ')[0];
+ command = command.replace(/:/g, '');
+ } else {
+ // try to figure out where parameter starts
+ let firstParamPos = fullcommand.indexOf(' -');
+ let firstParamPathPos = fullcommand.indexOf(' /');
+ firstParamPos = (firstParamPos >= 0 ? firstParamPos : 10000);
+ firstParamPathPos = (firstParamPathPos >= 0 ? firstParamPathPos : 10000);
+ const firstPos = Math.min(firstParamPos, firstParamPathPos);
+ let tmpCommand = fullcommand.substr(0, firstPos);
+ const tmpParams = fullcommand.substr(firstPos);
+ const lastSlashPos = tmpCommand.lastIndexOf('/');
+ if (lastSlashPos >= 0) {
+ cmdPath = tmpCommand.substr(0, lastSlashPos);
+ tmpCommand = tmpCommand.substr(lastSlashPos + 1);
+ }
+
+ if (firstPos === 10000 && tmpCommand.indexOf(' ') > -1) {
+ const parts = tmpCommand.split(' ');
+ if (fs.existsSync(path.join(cmdPath, parts[0]))) {
+ command = parts.shift();
+ params = (parts.join(' ') + ' ' + tmpParams).trim();
+ } else {
+ command = tmpCommand.trim();
+ params = tmpParams.trim();
+ }
+ } else {
+ command = tmpCommand.trim();
+ params = tmpParams.trim();
+ }
+ }
+ }
+
+ }
+
+ return ({
+ pid: pid,
+ parentPid: ppid,
+ name: _linux ? getName(command) : command,
+ cpu: cpu,
+ cpuu: 0,
+ cpus: 0,
+ mem: mem,
+ priority: priority,
+ memVsz: vsz,
+ memRss: rss,
+ nice: nice,
+ started: started,
+ state: state,
+ tty: tty,
+ user: user,
+ command: command,
+ params: params,
+ path: cmdPath
+ });
+ }
+
+ function parseProcesses(lines) {
+ let result = [];
+ if (lines.length > 1) {
+ let head = lines[0];
+ parsedhead = util.parseHead(head, 8);
+ lines.shift();
+ lines.forEach(function (line) {
+ if (line.trim() !== '') {
+ result.push(parseLine(line));
+ }
+ });
+ }
+ return result;
+ }
+ function parseProcesses2(lines) {
+
+ function formatDateTime(time) {
+ const month = ('0' + (time.getMonth() + 1).toString()).substr(-2);
+ const year = time.getFullYear().toString();
+ const day = ('0' + time.getDay().toString()).substr(-2);
+ const hours = time.getHours().toString();
+ const mins = time.getMinutes().toString();
+ const secs = ('0' + time.getSeconds().toString()).substr(-2);
+
+ return (year + '-' + month + '-' + day + ' ' + hours + ':' + mins + ':' + secs);
+ }
+
+ let result = [];
+ lines.forEach(function (line) {
+ if (line.trim() !== '') {
+ line = line.trim().replace(/ +/g, ' ').replace(/,+/g, '.');
+ const parts = line.split(' ');
+ const command = parts.slice(9).join(' ');
+ const pmem = parseFloat((1.0 * parseInt(parts[3]) * 1024 / os.totalmem()).toFixed(1));
+ const elapsed_parts = parts[5].split(':');
+ const started = formatDateTime(new Date(Date.now() - (elapsed_parts.length > 1 ? (elapsed_parts[0] * 60 + elapsed_parts[1]) * 1000 : elapsed_parts[0] * 1000)));
+
+ result.push({
+ pid: parseInt(parts[0]),
+ parentPid: parseInt(parts[1]),
+ name: getName(command),
+ cpu: 0,
+ cpuu: 0,
+ cpus: 0,
+ mem: pmem,
+ priority: 0,
+ memVsz: parseInt(parts[2]),
+ memRss: parseInt(parts[3]),
+ nice: parseInt(parts[4]),
+ started: started,
+ state: (parts[6] === 'R' ? 'running' : (parts[6] === 'S' ? 'sleeping' : (parts[6] === 'T' ? 'stopped' : (parts[6] === 'W' ? 'paging' : (parts[6] === 'X' ? 'dead' : (parts[6] === 'Z' ? 'zombie' : ((parts[6] === 'D' || parts[6] === 'U') ? 'blocked' : 'unknown'))))))),
+ tty: parts[7],
+ user: parts[8],
+ command: command
+ });
+ }
+ });
+ return result;
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = {
+ all: 0,
+ running: 0,
+ blocked: 0,
+ sleeping: 0,
+ unknown: 0,
+ list: []
+ };
+
+ let cmd = '';
+
+ if ((_processes_cpu.ms && Date.now() - _processes_cpu.ms >= 500) || _processes_cpu.ms === 0) {
+ if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) {
+ if (_linux) { cmd = 'export LC_ALL=C; ps -axo pid:11,ppid:11,pcpu:6,pmem:6,pri:5,vsz:11,rss:11,ni:5,etime:30,state:5,tty:15,user:20,command; unset LC_ALL'; }
+ if (_freebsd || _openbsd || _netbsd) { cmd = 'export LC_ALL=C; ps -axo pid,ppid,pcpu,pmem,pri,vsz,rss,ni,etime,state,tty,user,command; unset LC_ALL'; }
+ if (_darwin) { cmd = 'ps -axo pid,ppid,pcpu,pmem,pri,vsz=temp_title_1,rss=temp_title_2,nice,etime=temp_title_3,state,tty,user,command -r'; }
+ if (_sunos) { cmd = 'ps -Ao pid,ppid,pcpu,pmem,pri,vsz,rss,nice,stime,s,tty,user,comm'; }
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ if (!error && stdout.toString().trim()) {
+ result.list = (parseProcesses(stdout.toString().split('\n'))).slice();
+ result.all = result.list.length;
+ result.running = result.list.filter(function (e) {
+ return e.state === 'running';
+ }).length;
+ result.blocked = result.list.filter(function (e) {
+ return e.state === 'blocked';
+ }).length;
+ result.sleeping = result.list.filter(function (e) {
+ return e.state === 'sleeping';
+ }).length;
+
+ if (_linux) {
+ // calc process_cpu - ps is not accurate in linux!
+ cmd = 'cat /proc/stat | grep "cpu "';
+ result.list.forEach((element) => {
+ cmd += (';cat /proc/' + element.pid + '/stat');
+ });
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ let curr_processes = stdout.toString().split('\n');
+
+ // first line (all - /proc/stat)
+ let all = parseProcStat(curr_processes.shift());
+
+ // process
+ let list_new = {};
+ let resultProcess = {};
+ curr_processes.forEach((element) => {
+ resultProcess = calcProcStatLinux(element, all, _processes_cpu);
+
+ if (resultProcess.pid) {
+
+ // store pcpu in outer array
+ let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
+ if (listPos >= 0) {
+ result.list[listPos].cpu = resultProcess.cpuu + resultProcess.cpus;
+ result.list[listPos].cpuu = resultProcess.cpuu;
+ result.list[listPos].cpus = resultProcess.cpus;
+ }
+
+ // save new values
+ list_new[resultProcess.pid] = {
+ cpuu: resultProcess.cpuu,
+ cpus: resultProcess.cpus,
+ utime: resultProcess.utime,
+ stime: resultProcess.stime,
+ cutime: resultProcess.cutime,
+ cstime: resultProcess.cstime
+ };
+ }
+ });
+
+ // store old values
+ _processes_cpu.all = all;
+ _processes_cpu.list = Object.assign({}, list_new);
+ _processes_cpu.ms = Date.now() - _processes_cpu.ms;
+ _processes_cpu.result = Object.assign({}, result);
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } else {
+ cmd = 'ps -o pid,ppid,vsz,rss,nice,etime,stat,tty,user,comm';
+ if (_sunos) {
+ cmd = 'ps -o pid,ppid,vsz,rss,nice,etime,s,tty,user,comm';
+ }
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.shift();
+
+ result.list = parseProcesses2(lines).slice();
+ result.all = result.list.length;
+ result.running = result.list.filter(function (e) {
+ return e.state === 'running';
+ }).length;
+ result.blocked = result.list.filter(function (e) {
+ return e.state === 'blocked';
+ }).length;
+ result.sleeping = result.list.filter(function (e) {
+ return e.state === 'sleeping';
+ }).length;
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ }
+ });
+ } else if (_windows) {
+ try {
+ util.powerShell('Get-WmiObject Win32_Process | select ProcessId,ParentProcessId,ExecutionState,Caption,CommandLine,ExecutablePath,UserModeTime,KernelModeTime,WorkingSetSize,Priority,PageFileUsage,CreationDate | fl').then((stdout, error) => {
+ if (!error) {
+ let processSections = stdout.split(/\n\s*\n/);
+ let procs = [];
+ let procStats = [];
+ let list_new = {};
+ let allcpuu = 0;
+ let allcpus = 0;
+ processSections.forEach((element) => {
+ if (element.trim() !== '') {
+ let lines = element.trim().split('\r\n');
+ let pid = parseInt(util.getValue(lines, 'ProcessId', ':', true), 10);
+ let parentPid = parseInt(util.getValue(lines, 'ParentProcessId', ':', true), 10);
+ let statusValue = util.getValue(lines, 'ExecutionState', ':');
+ let name = util.getValue(lines, 'Caption', ':', true);
+ let commandLine = util.getValue(lines, 'CommandLine', ':', true);
+ // get additional command line data
+ let additionalCommand = false;
+ lines.forEach((line) => {
+ if (additionalCommand && line.toLowerCase().startsWith(' ')) {
+ commandLine = commandLine + line.trim();
+ } else {
+ additionalCommand = false;
+ }
+ if (line.toLowerCase().startsWith('commandline')) {
+ additionalCommand = true;
+ }
+ });
+ let commandPath = util.getValue(lines, 'ExecutablePath', ':', true);
+ let utime = parseInt(util.getValue(lines, 'UserModeTime', ':', true), 10);
+ let stime = parseInt(util.getValue(lines, 'KernelModeTime', ':', true), 10);
+ let memw = parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10);
+ allcpuu = allcpuu + utime;
+ allcpus = allcpus + stime;
+ result.all++;
+ if (!statusValue) { result.unknown++; }
+ if (statusValue === '3') { result.running++; }
+ if (statusValue === '4' || statusValue === '5') { result.blocked++; }
+
+ procStats.push({
+ pid: pid,
+ utime: utime,
+ stime: stime,
+ cpu: 0,
+ cpuu: 0,
+ cpus: 0,
+ });
+ procs.push({
+ pid: pid,
+ parentPid: parentPid,
+ name: name,
+ cpu: 0,
+ cpuu: 0,
+ cpus: 0,
+ mem: memw / os.totalmem() * 100,
+ priority: parseInt(util.getValue(lines, 'Priority', ':', true), 10),
+ memVsz: parseInt(util.getValue(lines, 'PageFileUsage', ':', true), 10),
+ memRss: Math.floor(parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10) / 1024),
+ nice: 0,
+ started: parseTimeWin(util.getValue(lines, 'CreationDate', ':', true)),
+ state: (!statusValue ? _winStatusValues[0] : _winStatusValues[statusValue]),
+ tty: '',
+ user: '',
+ command: commandLine || name,
+ path: commandPath,
+ params: ''
+ });
+ }
+ });
+
+ result.sleeping = result.all - result.running - result.blocked - result.unknown;
+ result.list = procs;
+ procStats.forEach((element) => {
+ let resultProcess = calcProcStatWin(element, allcpuu + allcpus, _processes_cpu);
+
+ // store pcpu in outer array
+ let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
+ if (listPos >= 0) {
+ result.list[listPos].cpu = resultProcess.cpuu + resultProcess.cpus;
+ result.list[listPos].cpuu = resultProcess.cpuu;
+ result.list[listPos].cpus = resultProcess.cpus;
+ }
+
+ // save new values
+ list_new[resultProcess.pid] = {
+ cpuu: resultProcess.cpuu,
+ cpus: resultProcess.cpus,
+ utime: resultProcess.utime,
+ stime: resultProcess.stime
+ };
+ });
+
+ // store old values
+ _processes_cpu.all = allcpuu + allcpus;
+ _processes_cpu.all_utime = allcpuu;
+ _processes_cpu.all_stime = allcpus;
+ _processes_cpu.list = Object.assign({}, list_new);
+ _processes_cpu.ms = Date.now() - _processes_cpu.ms;
+ _processes_cpu.result = Object.assign({}, result);
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } else {
+ if (callback) { callback(_processes_cpu.result); }
+ resolve(_processes_cpu.result);
+ }
+ });
+ });
+}
+
+exports.processes = processes;
+
+// --------------------------
+// PS - process load
+// get detailed information about a certain process
+// (PID, CPU-Usage %, Mem-Usage %)
+
+function processLoad(proc, callback) {
+
+ // fallback - if only callback is given
+ if (util.isFunction(proc) && !callback) {
+ callback = proc;
+ proc = '';
+ }
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ proc = proc || '';
+
+ if (typeof proc !== 'string') {
+ if (callback) { callback([]); }
+ return resolve([]);
+ }
+
+ let processesString = '';
+ processesString.__proto__.toLowerCase = util.stringToLower;
+ processesString.__proto__.replace = util.stringReplace;
+ processesString.__proto__.trim = util.stringTrim;
+
+ const s = util.sanitizeShellString(proc);
+ for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
+ if (s[i] !== undefined) {
+ processesString = processesString + s[i];
+ }
+ }
+
+ processesString = processesString.trim().toLowerCase().replace(/, /g, '|').replace(/,+/g, '|');
+ if (processesString === '') {
+ processesString = '*';
+ }
+ if (util.isPrototypePolluted() && processesString !== '*') {
+ processesString = '------';
+ }
+ let processes = processesString.split('|');
+ let result = [];
+
+ const procSanitized = util.isPrototypePolluted() ? '' : util.sanitizeShellString(proc);
+
+ // from here new
+ // let result = {
+ // 'proc': procSanitized,
+ // 'pid': null,
+ // 'cpu': 0,
+ // 'mem': 0
+ // };
+ if (procSanitized && processes.length && processes[0] !== '------') {
+ if (_windows) {
+ try {
+ util.powerShell('Get-WmiObject Win32_Process | select ProcessId,Caption,UserModeTime,KernelModeTime,WorkingSetSize | fl').then((stdout, error) => {
+ if (!error) {
+ let processSections = stdout.split(/\n\s*\n/);
+ let procStats = [];
+ let list_new = {};
+ let allcpuu = 0;
+ let allcpus = 0;
+
+ // go through all processes
+ processSections.forEach((element) => {
+ if (element.trim() !== '') {
+ let lines = element.trim().split('\r\n');
+ let pid = parseInt(util.getValue(lines, 'ProcessId', ':', true), 10);
+ let name = util.getValue(lines, 'Caption', ':', true);
+ let utime = parseInt(util.getValue(lines, 'UserModeTime', ':', true), 10);
+ let stime = parseInt(util.getValue(lines, 'KernelModeTime', ':', true), 10);
+ let mem = parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10);
+ allcpuu = allcpuu + utime;
+ allcpus = allcpus + stime;
+
+ procStats.push({
+ pid: pid,
+ name,
+ utime: utime,
+ stime: stime,
+ cpu: 0,
+ cpuu: 0,
+ cpus: 0,
+ mem
+ });
+ let pname = '';
+ let inList = false;
+ processes.forEach(function (proc) {
+ if (name.toLowerCase().indexOf(proc.toLowerCase()) >= 0 && !inList) {
+ inList = true;
+ pname = proc;
+ }
+ });
+
+ if (processesString === '*' || inList) {
+ let processFound = false;
+ result.forEach(function (item) {
+ if (item.proc.toLowerCase() === pname.toLowerCase()) {
+ item.pids.push(pid);
+ item.mem += mem / os.totalmem() * 100;
+ processFound = true;
+ }
+ });
+ if (!processFound) {
+ result.push({
+ proc: pname,
+ pid: pid,
+ pids: [pid],
+ cpu: 0,
+ mem: mem / os.totalmem() * 100
+ });
+ }
+ }
+ }
+ });
+
+ // add missing processes
+ if (processesString !== '*') {
+ let processesMissing = processes.filter(function (name) {
+ return procStats.filter(function (item) { return item.name.toLowerCase().indexOf(name) >= 0; }).length === 0;
+
+ });
+ processesMissing.forEach(function (procName) {
+ result.push({
+ proc: procName,
+ pid: null,
+ pids: [],
+ cpu: 0,
+ mem: 0
+ });
+ });
+ }
+
+ // calculate proc stats for each proc
+ procStats.forEach((element) => {
+ let resultProcess = calcProcStatWin(element, allcpuu + allcpus, _process_cpu);
+
+ let listPos = -1;
+ for (let j = 0; j < result.length; j++) {
+ if (result[j].pid === resultProcess.pid || result[j].pids.indexOf(resultProcess.pid) >= 0) { listPos = j; }
+ }
+ if (listPos >= 0) {
+ result[listPos].cpu += resultProcess.cpuu + resultProcess.cpus;
+ }
+
+ // save new values
+ list_new[resultProcess.pid] = {
+ cpuu: resultProcess.cpuu,
+ cpus: resultProcess.cpus,
+ utime: resultProcess.utime,
+ stime: resultProcess.stime
+ };
+ });
+
+ // store old values
+ _process_cpu.all = allcpuu + allcpus;
+ _process_cpu.all_utime = allcpuu;
+ _process_cpu.all_stime = allcpus;
+ _process_cpu.list = Object.assign({}, list_new);
+ _process_cpu.ms = Date.now() - _process_cpu.ms;
+ _process_cpu.result = JSON.parse(JSON.stringify(result));
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+
+ if (_darwin || _linux || _freebsd || _openbsd || _netbsd) {
+ const params = ['-axo', 'pid,pcpu,pmem,comm'];
+ util.execSafe('ps', params).then((stdout) => {
+ if (stdout) {
+ let procStats = [];
+ let lines = stdout.toString().split('\n').filter(function (line) {
+ if (processesString === '*') { return true; }
+ if (line.toLowerCase().indexOf('grep') !== -1) { return false; } // remove this??
+ let found = false;
+ processes.forEach(function (item) {
+ found = found || (line.toLowerCase().indexOf(item.toLowerCase()) >= 0);
+ });
+ return found;
+ });
+
+ lines.forEach(function (line) {
+ let data = line.trim().replace(/ +/g, ' ').split(' ');
+ if (data.length > 3) {
+ procStats.push({
+ name: data[3].substring(data[3].lastIndexOf('/') + 1),
+ pid: parseInt(data[0]) || 0,
+ cpu: parseFloat(data[1].replace(',', '.')),
+ mem: parseFloat(data[2].replace(',', '.'))
+ });
+ }
+ });
+
+ procStats.forEach(function (item) {
+ let listPos = -1;
+ let inList = false;
+ let name = '';
+ for (let j = 0; j < result.length; j++) {
+ if (item.name.toLowerCase().indexOf(result[j].proc.toLowerCase()) >= 0) {
+ listPos = j;
+ }
+ }
+ processes.forEach(function (proc) {
+
+ if (item.name.toLowerCase().indexOf(proc.toLowerCase()) >= 0 && !inList) {
+ inList = true;
+ name = proc;
+ }
+ });
+ if ((processesString === '*') || inList) {
+ if (listPos < 0) {
+ result.push({
+ proc: name,
+ pid: item.pid,
+ pids: [item.pid],
+ cpu: item.cpu,
+ mem: item.mem
+ });
+ } else {
+ result[listPos].pids.push(item.pid);
+ result[listPos].cpu += item.cpu;
+ result[listPos].mem += item.mem;
+ }
+ }
+ });
+
+ if (processesString !== '*') {
+ // add missing processes
+ let processesMissing = processes.filter(function (name) {
+ return procStats.filter(function (item) { return item.name.toLowerCase().indexOf(name) >= 0; }).length === 0;
+ });
+ processesMissing.forEach(function (procName) {
+ result.push({
+ proc: procName,
+ pid: null,
+ pids: [],
+ cpu: 0,
+ mem: 0
+ });
+ });
+ }
+ if (_linux) {
+ // calc process_cpu - ps is not accurate in linux!
+ result.forEach(function (item) {
+ item.cpu = 0;
+ });
+ let cmd = 'cat /proc/stat | grep "cpu "';
+ for (let i in result) {
+ for (let j in result[i].pids) {
+ cmd += (';cat /proc/' + result[i].pids[j] + '/stat');
+ }
+ }
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
+ let curr_processes = stdout.toString().split('\n');
+
+ // first line (all - /proc/stat)
+ let all = parseProcStat(curr_processes.shift());
+
+ // process
+ let list_new = {};
+ let resultProcess = {};
+ curr_processes.forEach((element) => {
+ resultProcess = calcProcStatLinux(element, all, _process_cpu);
+
+ if (resultProcess.pid) {
+
+ // find result item
+ let resultItemId = -1;
+ for (let i in result) {
+ if (result[i].pids.indexOf(resultProcess.pid) >= 0) {
+ resultItemId = i;
+ }
+ }
+ // store pcpu in outer result
+ if (resultItemId >= 0) {
+ result[resultItemId].cpu += resultProcess.cpuu + resultProcess.cpus;
+ }
+
+ // save new values
+ list_new[resultProcess.pid] = {
+ cpuu: resultProcess.cpuu,
+ cpus: resultProcess.cpus,
+ utime: resultProcess.utime,
+ stime: resultProcess.stime,
+ cutime: resultProcess.cutime,
+ cstime: resultProcess.cstime
+ };
+ }
+ });
+
+ result.forEach(function (item) {
+ item.cpu = Math.round(item.cpu * 100) / 100;
+ });
+
+ _process_cpu.all = all;
+ _process_cpu.list = Object.assign({}, list_new);
+ _process_cpu.ms = Date.now() - _process_cpu.ms;
+ _process_cpu.result = Object.assign({}, result);
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ }
+ }
+ });
+ });
+}
+
+exports.processLoad = processLoad;
diff --git a/MistyCore/node_modules/systeminformation/lib/system.js b/MistyCore/node_modules/systeminformation/lib/system.js
new file mode 100644
index 0000000..f5d21c6
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/system.js
@@ -0,0 +1,831 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// system.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 2. System (Hardware, BIOS, Base Board)
+// ----------------------------------------------------------------------------------
+
+const fs = require('fs');
+const os = require('os');
+const util = require('./util');
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const execPromise = util.promisify(require('child_process').exec);
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+function system(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = {
+ manufacturer: '',
+ model: 'Computer',
+ version: '',
+ serial: '-',
+ uuid: '-',
+ sku: '-',
+ virtual: false
+ };
+
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ exec('export LC_ALL=C; dmidecode -t system 2>/dev/null; unset LC_ALL', function (error, stdout) {
+ // if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.manufacturer = util.getValue(lines, 'manufacturer');
+ result.model = util.getValue(lines, 'product name');
+ result.version = util.getValue(lines, 'version');
+ result.serial = util.getValue(lines, 'serial number');
+ result.uuid = util.getValue(lines, 'uuid').toLowerCase();
+ result.sku = util.getValue(lines, 'sku number');
+ // }
+ // Non-Root values
+ const cmd = `echo -n "product_name: "; cat /sys/devices/virtual/dmi/id/product_name 2>/dev/null; echo;
+ echo -n "product_serial: "; cat /sys/devices/virtual/dmi/id/product_serial 2>/dev/null; echo;
+ echo -n "product_uuid: "; cat /sys/devices/virtual/dmi/id/product_uuid 2>/dev/null; echo;
+ echo -n "product_version: "; cat /sys/devices/virtual/dmi/id/product_version 2>/dev/null; echo;
+ echo -n "sys_vendor: "; cat /sys/devices/virtual/dmi/id/sys_vendor 2>/dev/null; echo;`;
+ try {
+ lines = execSync(cmd).toString().split('\n');
+ result.manufacturer = result.manufacturer === '' ? util.getValue(lines, 'sys_vendor') : result.manufacturer;
+ result.model = result.model === '' ? util.getValue(lines, 'product_name') : result.model;
+ result.version = result.version === '' ? util.getValue(lines, 'product_version') : result.version;
+ result.serial = result.serial === '' ? util.getValue(lines, 'product_serial') : result.serial;
+ result.uuid = result.uuid === '' ? util.getValue(lines, 'product_uuid').toLowerCase() : result.uuid;
+ } catch (e) {
+ util.noop();
+ }
+ if (!result.serial || result.serial.toLowerCase().indexOf('o.e.m.') !== -1) { result.serial = '-'; }
+ if (!result.manufacturer || result.manufacturer.toLowerCase().indexOf('o.e.m.') !== -1) { result.manufacturer = ''; }
+ if (!result.model || result.model.toLowerCase().indexOf('o.e.m.') !== -1) { result.model = 'Computer'; }
+ if (!result.version || result.version.toLowerCase().indexOf('o.e.m.') !== -1) { result.version = ''; }
+ if (!result.sku || result.sku.toLowerCase().indexOf('o.e.m.') !== -1) { result.sku = '-'; }
+
+ // detect virtual (1)
+ if (result.model.toLowerCase() === 'virtualbox' || result.model.toLowerCase() === 'kvm' || result.model.toLowerCase() === 'virtual machine' || result.model.toLowerCase() === 'bochs' || result.model.toLowerCase().startsWith('vmware') || result.model.toLowerCase().startsWith('droplet')) {
+ result.virtual = true;
+ switch (result.model.toLowerCase()) {
+ case 'virtualbox':
+ result.virtualHost = 'VirtualBox';
+ break;
+ case 'vmware':
+ result.virtualHost = 'VMware';
+ break;
+ case 'kvm':
+ result.virtualHost = 'KVM';
+ break;
+ case 'bochs':
+ result.virtualHost = 'bochs';
+ break;
+ }
+ }
+ if (result.manufacturer.toLowerCase().startsWith('vmware') || result.manufacturer.toLowerCase() === 'xen') {
+ result.virtual = true;
+ switch (result.manufacturer.toLowerCase()) {
+ case 'vmware':
+ result.virtualHost = 'VMware';
+ break;
+ case 'xen':
+ result.virtualHost = 'Xen';
+ break;
+ }
+ }
+ if (!result.virtual) {
+ try {
+ const disksById = execSync('ls -1 /dev/disk/by-id/ 2>/dev/null').toString();
+ if (disksById.indexOf('_QEMU_') >= 0) {
+ result.virtual = true;
+ result.virtualHost = 'QEMU';
+ }
+ if (disksById.indexOf('_VBOX_') >= 0) {
+ result.virtual = true;
+ result.virtualHost = 'VirtualBox';
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ if (!result.virtual && (os.release().toLowerCase().indexOf('microsoft') >= 0 || os.release().toLowerCase().endsWith('wsl2'))) {
+ const kernelVersion = parseFloat(os.release().toLowerCase());
+ result.virtual = true;
+ result.manufacturer = 'Microsoft';
+ result.model = 'WSL';
+ result.version = kernelVersion < 4.19 ? '1' : '2';
+ }
+ if ((_freebsd || _openbsd || _netbsd) && !result.virtualHost) {
+ try {
+ const procInfo = execSync('dmidecode -t 4');
+ const procLines = procInfo.toString().split('\n');
+ const procManufacturer = util.getValue(procLines, 'manufacturer', ':', true);
+ switch (procManufacturer.toLowerCase()) {
+ case 'virtualbox':
+ result.virtualHost = 'VirtualBox';
+ break;
+ case 'vmware':
+ result.virtualHost = 'VMware';
+ break;
+ case 'kvm':
+ result.virtualHost = 'KVM';
+ break;
+ case 'bochs':
+ result.virtualHost = 'bochs';
+ break;
+ }
+ } catch (e) {
+ util.noop();
+ }
+ }
+ // detect docker
+ if (fs.existsSync('/.dockerenv') || fs.existsSync('/.dockerinit')) {
+ result.model = 'Docker Container';
+ }
+ try {
+ const stdout = execSync('dmesg 2>/dev/null | grep -iE "virtual|hypervisor" | grep -iE "vmware|qemu|kvm|xen" | grep -viE "Nested Virtualization|/virtual/"');
+ // detect virtual machines
+ let lines = stdout.toString().split('\n');
+ if (lines.length > 0) {
+ if (result.model === 'Computer') { result.model = 'Virtual machine'; }
+ result.virtual = true;
+ if (stdout.toString().toLowerCase().indexOf('vmware') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'VMware';
+ }
+ if (stdout.toString().toLowerCase().indexOf('qemu') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'QEMU';
+ }
+ if (stdout.toString().toLowerCase().indexOf('xen') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'Xen';
+ }
+ if (stdout.toString().toLowerCase().indexOf('kvm') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'KVM';
+ }
+ }
+ } catch (e) {
+ util.noop();
+ }
+
+ if (result.manufacturer === '' && result.model === 'Computer' && result.version === '') {
+ // Check Raspberry Pi
+ fs.readFile('/proc/cpuinfo', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.model = util.getValue(lines, 'hardware', ':', true).toUpperCase();
+ result.version = util.getValue(lines, 'revision', ':', true).toLowerCase();
+ result.serial = util.getValue(lines, 'serial', ':', true);
+ const model = util.getValue(lines, 'model:', ':', true);
+ // reference values: https://elinux.org/RPi_HardwareHistory
+ // https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
+ if ((result.model === 'BCM2835' || result.model === 'BCM2708' || result.model === 'BCM2709' || result.model === 'BCM2710' || result.model === 'BCM2711' || result.model === 'BCM2836' || result.model === 'BCM2837') && model.toLowerCase().indexOf('raspberry') >= 0) {
+ const rPIRevision = util.decodePiCpuinfo(lines);
+ result.model = rPIRevision.model;
+ result.version = rPIRevision.revisionCode;
+ result.manufacturer = 'Raspberry Pi Foundation';
+ result.raspberry = {
+ manufacturer: rPIRevision.manufacturer,
+ processor: rPIRevision.processor,
+ type: rPIRevision.type,
+ revision: rPIRevision.revision
+ };
+ }
+
+ // if (result.model === 'BCM2835' || result.model === 'BCM2708' || result.model === 'BCM2709' || result.model === 'BCM2835' || result.model === 'BCM2837') {
+
+
+ // // Pi 4
+ // if (['d03114'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 4 Model B';
+ // result.version = result.version + ' - Rev. 1.4';
+ // }
+ // if (['b03112', 'c03112'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 4 Model B';
+ // result.version = result.version + ' - Rev. 1.2';
+ // }
+ // if (['a03111', 'b03111', 'c03111'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 4 Model B';
+ // result.version = result.version + ' - Rev. 1.1';
+ // }
+ // // Pi 3
+ // if (['a02082', 'a22082', 'a32082', 'a52082'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 3 Model B';
+ // result.version = result.version + ' - Rev. 1.2';
+ // }
+ // if (['a22083'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 3 Model B';
+ // result.version = result.version + ' - Rev. 1.3';
+ // }
+ // if (['a020d3'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 3 Model B+';
+ // result.version = result.version + ' - Rev. 1.3';
+ // }
+ // if (['9020e0'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 3 Model A+';
+ // result.version = result.version + ' - Rev. 1.3';
+ // }
+ // // Pi 2 Model B
+ // if (['a01040'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 2 Model B';
+ // result.version = result.version + ' - Rev. 1.0';
+ // }
+ // if (['a01041', 'a21041'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 2 Model B';
+ // result.version = result.version + ' - Rev. 1.1';
+ // }
+ // if (['a22042', 'a02042'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi 2 Model B';
+ // result.version = result.version + ' - Rev. 1.2';
+ // }
+
+ // // Compute Model
+ // if (['a02100'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi CM3+';
+ // result.version = result.version + ' - Rev 1.0';
+ // }
+ // if (['a020a0', 'a220a0'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi CM3';
+ // result.version = result.version + ' - Rev 1.0';
+ // }
+ // if (['900061'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi CM';
+ // result.version = result.version + ' - Rev 1.1';
+ // }
+
+ // // Pi Zero
+ // if (['900092', '920092'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Zero';
+ // result.version = result.version + ' - Rev 1.2';
+ // }
+ // if (['900093', '920093'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Zero';
+ // result.version = result.version + ' - Rev 1.3';
+ // }
+ // if (['9000c1'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Zero W';
+ // result.version = result.version + ' - Rev 1.1';
+ // }
+
+ // // A, B, A+ B+
+ // if (['0002', '0003'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Model B';
+ // result.version = result.version + ' - Rev 1.0';
+ // }
+ // if (['0004', '0005', '0006', '000d', '000e', '000f'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Model B';
+ // result.version = result.version + ' - Rev 2.0';
+ // }
+ // if (['0007', '0008', '0009'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Model A';
+ // result.version = result.version + ' - Rev 2.0';
+ // }
+ // if (['0010'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Model B+';
+ // result.version = result.version + ' - Rev 1.0';
+ // }
+ // if (['0012'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Model A+';
+ // result.version = result.version + ' - Rev 1.0';
+ // }
+ // if (['0013', '900032'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Model B+';
+ // result.version = result.version + ' - Rev 1.2';
+ // }
+ // if (['0015', '900021'].indexOf(result.version) >= 0) {
+ // result.model = result.model + ' - Pi Model A+';
+ // result.version = result.version + ' - Rev 1.1';
+ // }
+ // if (result.model.indexOf('Pi') !== -1 && result.version) { // Pi, Pi Zero
+ // result.manufacturer = 'Raspberry Pi Foundation';
+ // }
+ // }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ }
+ if (_darwin) {
+ exec('ioreg -c IOPlatformExpertDevice -d 2', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().replace(/[<>"]/g, '').split('\n');
+ result.manufacturer = util.getValue(lines, 'manufacturer', '=', true);
+ result.model = util.getValue(lines, 'model', '=', true);
+ result.version = util.getValue(lines, 'version', '=', true);
+ result.serial = util.getValue(lines, 'ioplatformserialnumber', '=', true);
+ result.uuid = util.getValue(lines, 'ioplatformuuid', '=', true).toLowerCase();
+ result.sku = util.getValue(lines, 'board-id', '=', true);
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_windows) {
+ try {
+ util.powerShell('Get-WmiObject Win32_ComputerSystemProduct | select Name,Vendor,Version,IdentifyingNumber,UUID | fl').then((stdout, error) => {
+ if (!error) {
+ // let lines = stdout.split('\r\n').filter(line => line.trim() !== '').filter((line, idx) => idx > 0)[0].trim().split(/\s\s+/);
+ let lines = stdout.split('\r\n');
+ result.manufacturer = util.getValue(lines, 'vendor', ':');
+ result.model = util.getValue(lines, 'name', ':');
+ result.version = util.getValue(lines, 'version', ':');
+ result.serial = util.getValue(lines, 'identifyingnumber', ':');
+ result.uuid = util.getValue(lines, 'uuid', ':').toLowerCase();
+ // detect virtual (1)
+ const model = result.model.toLowerCase();
+ if (model === 'virtualbox' || model === 'kvm' || model === 'virtual machine' || model === 'bochs' || model.startsWith('vmware') || model.startsWith('qemu')) {
+ result.virtual = true;
+ if (model.startsWith('virtualbox')) { result.virtualHost = 'VirtualBox'; }
+ if (model.startsWith('vmware')) { result.virtualHost = 'VMware'; }
+ if (model.startsWith('kvm')) { result.virtualHost = 'KVM'; }
+ if (model.startsWith('bochs')) { result.virtualHost = 'bochs'; }
+ if (model.startsWith('qemu')) { result.virtualHost = 'KVM'; }
+ }
+ const manufacturer = result.manufacturer.toLowerCase();
+ if (manufacturer.startsWith('vmware') || manufacturer.startsWith('qemu') || manufacturer === 'xen') {
+ result.virtual = true;
+ if (manufacturer.startsWith('vmware')) { result.virtualHost = 'VMware'; }
+ if (manufacturer.startsWith('xen')) { result.virtualHost = 'Xen'; }
+ if (manufacturer.startsWith('qemu')) { result.virtualHost = 'KVM'; }
+ }
+ util.powerShell('Get-WmiObject MS_Systeminformation -Namespace "root/wmi" | select systemsku | fl ').then((stdout, error) => {
+ if (!error) {
+ let lines = stdout.split('\r\n');
+ result.sku = util.getValue(lines, 'systemsku', ':');
+ }
+ if (!result.virtual) {
+ util.powerShell('Get-WmiObject Win32_bios | select Version, SerialNumber, SMBIOSBIOSVersion').then((stdout, error) => {
+ if (!error) {
+ let lines = stdout.toString();
+ if (lines.indexOf('VRTUAL') >= 0 || lines.indexOf('A M I ') >= 0 || lines.indexOf('VirtualBox') >= 0 || lines.indexOf('VMWare') >= 0 || lines.indexOf('Xen') >= 0) {
+ result.virtual = true;
+ if (lines.indexOf('VirtualBox') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'VirtualBox';
+ }
+ if (lines.indexOf('VMware') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'VMware';
+ }
+ if (lines.indexOf('Xen') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'Xen';
+ }
+ if (lines.indexOf('VRTUAL') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'Hyper-V';
+ }
+ if (lines.indexOf('A M I') >= 0 && !result.virtualHost) {
+ result.virtualHost = 'Virtual PC';
+ }
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.system = system;
+
+function bios(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = {
+ vendor: '',
+ version: '',
+ releaseDate: '',
+ revision: '',
+ };
+ let cmd = '';
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ if (process.arch === 'arm') {
+ cmd = 'cat /proc/cpuinfo | grep Serial';
+ } else {
+ cmd = 'export LC_ALL=C; dmidecode -t bios 2>/dev/null; unset LC_ALL';
+ }
+ exec(cmd, function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ result.vendor = util.getValue(lines, 'Vendor');
+ result.version = util.getValue(lines, 'Version');
+ let datetime = util.getValue(lines, 'Release Date');
+ result.releaseDate = util.parseDateTime(datetime).date;
+ result.revision = util.getValue(lines, 'BIOS Revision');
+ result.serial = util.getValue(lines, 'SerialNumber');
+ let language = util.getValue(lines, 'Currently Installed Language').split('|')[0];
+ if (language) {
+ result.language = language;
+ }
+ if (lines.length && stdout.toString().indexOf('Characteristics:') >= 0) {
+ const features = [];
+ lines.forEach(line => {
+ if (line.indexOf(' is supported') >= 0) {
+ const feature = line.split(' is supported')[0].trim();
+ features.push(feature);
+ }
+ });
+ result.features = features;
+ }
+ // Non-Root values
+ const cmd = `echo -n "bios_date: "; cat /sys/devices/virtual/dmi/id/bios_date 2>/dev/null; echo;
+ echo -n "bios_vendor: "; cat /sys/devices/virtual/dmi/id/bios_vendor 2>/dev/null; echo;
+ echo -n "bios_version: "; cat /sys/devices/virtual/dmi/id/bios_version 2>/dev/null; echo;`;
+ try {
+ lines = execSync(cmd).toString().split('\n');
+ result.vendor = !result.vendor ? util.getValue(lines, 'bios_vendor') : result.vendor;
+ result.version = !result.version ? util.getValue(lines, 'bios_version') : result.version;
+ datetime = util.getValue(lines, 'bios_date');
+ result.releaseDate = !result.releaseDate ? util.parseDateTime(datetime).date : result.releaseDate;
+ } catch (e) {
+ util.noop();
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ result.vendor = 'Apple Inc.';
+ exec(
+ 'system_profiler SPHardwareDataType -json', function (error, stdout) {
+ try {
+ const hardwareData = JSON.parse(stdout.toString());
+ if (hardwareData && hardwareData.SPHardwareDataType && hardwareData.SPHardwareDataType.length) {
+ let bootRomVersion = hardwareData.SPHardwareDataType[0].boot_rom_version;
+ bootRomVersion = bootRomVersion ? bootRomVersion.split('(')[0].trim() : null;
+ result.version = bootRomVersion;
+ }
+ } catch (e) {
+ util.noop();
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ result.vendor = 'Sun Microsystems';
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_windows) {
+ try {
+ util.powerShell('Get-WmiObject Win32_bios | select Description,Version,Manufacturer,ReleaseDate,BuildNumber,SerialNumber | fl').then((stdout, error) => {
+ if (!error) {
+ let lines = stdout.toString().split('\r\n');
+ const description = util.getValue(lines, 'description', ':');
+ if (description.indexOf(' Version ') !== -1) {
+ // ... Phoenix ROM BIOS PLUS Version 1.10 A04
+ result.vendor = description.split(' Version ')[0].trim();
+ result.version = description.split(' Version ')[1].trim();
+ } else if (description.indexOf(' Ver: ') !== -1) {
+ // ... BIOS Date: 06/27/16 17:50:16 Ver: 1.4.5
+ result.vendor = util.getValue(lines, 'manufacturer', ':');
+ result.version = description.split(' Ver: ')[1].trim();
+ } else {
+ result.vendor = util.getValue(lines, 'manufacturer', ':');
+ result.version = util.getValue(lines, 'version', ':');
+ }
+ result.releaseDate = util.getValue(lines, 'releasedate', ':');
+ if (result.releaseDate.length >= 10) {
+ result.releaseDate = result.releaseDate.substr(0, 4) + '-' + result.releaseDate.substr(4, 2) + '-' + result.releaseDate.substr(6, 2);
+ }
+ result.revision = util.getValue(lines, 'buildnumber', ':');
+ result.serial = util.getValue(lines, 'serialnumber', ':');
+ }
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.bios = bios;
+
+function baseboard(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = {
+ manufacturer: '',
+ model: '',
+ version: '',
+ serial: '-',
+ assetTag: '-',
+ memMax: null,
+ memSlots: null
+ };
+ let cmd = '';
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ if (process.arch === 'arm') {
+ cmd = 'cat /proc/cpuinfo | grep Serial';
+ // 'BCM2709', 'BCM2835', 'BCM2708' -->
+ } else {
+ cmd = 'export LC_ALL=C; dmidecode -t 2 2>/dev/null; unset LC_ALL';
+ }
+ const workload = [];
+ workload.push(execPromise(cmd));
+ workload.push(execPromise('export LC_ALL=C; dmidecode -t memory 2>/dev/null'));
+ util.promiseAll(
+ workload
+ ).then((data) => {
+ let lines = data.results[0] ? data.results[0].toString().split('\n') : [''];
+ result.manufacturer = util.getValue(lines, 'Manufacturer');
+ result.model = util.getValue(lines, 'Product Name');
+ result.version = util.getValue(lines, 'Version');
+ result.serial = util.getValue(lines, 'Serial Number');
+ result.assetTag = util.getValue(lines, 'Asset Tag');
+ // Non-Root values
+ const cmd = `echo -n "board_asset_tag: "; cat /sys/devices/virtual/dmi/id/board_asset_tag 2>/dev/null; echo;
+ echo -n "board_name: "; cat /sys/devices/virtual/dmi/id/board_name 2>/dev/null; echo;
+ echo -n "board_serial: "; cat /sys/devices/virtual/dmi/id/board_serial 2>/dev/null; echo;
+ echo -n "board_vendor: "; cat /sys/devices/virtual/dmi/id/board_vendor 2>/dev/null; echo;
+ echo -n "board_version: "; cat /sys/devices/virtual/dmi/id/board_version 2>/dev/null; echo;`;
+ try {
+ lines = execSync(cmd).toString().split('\n');
+ result.manufacturer = !result.manufacturer ? util.getValue(lines, 'board_vendor') : result.manufacturer;
+ result.model = !result.model ? util.getValue(lines, 'board_name') : result.model;
+ result.version = !result.version ? util.getValue(lines, 'board_version') : result.version;
+ result.serial = !result.serial ? util.getValue(lines, 'board_serial') : result.serial;
+ result.assetTag = !result.assetTag ? util.getValue(lines, 'board_asset_tag') : result.assetTag;
+ } catch (e) {
+ util.noop();
+ }
+ if (result.serial.toLowerCase().indexOf('o.e.m.') !== -1) { result.serial = '-'; }
+ if (result.assetTag.toLowerCase().indexOf('o.e.m.') !== -1) { result.assetTag = '-'; }
+
+ // mem
+ lines = data.results[1] ? data.results[1].toString().split('\n') : [''];
+ result.memMax = util.toInt(util.getValue(lines, 'Maximum Capacity')) * 1024 * 1024 * 1024 || null;
+ result.memSlots = util.toInt(util.getValue(lines, 'Number Of Devices')) || null;
+
+ // raspberry
+ let linesRpi = '';
+ try {
+ linesRpi = fs.readFileSync('/proc/cpuinfo').toString().split('\n');
+ } catch (e) {
+ util.noop();
+ }
+ const hardware = util.getValue(linesRpi, 'hardware');
+ if (hardware.startsWith('BCM')) {
+ const rpi = util.decodePiCpuinfo(linesRpi);
+ result.manufacturer = rpi.manufacturer;
+ result.model = 'Raspberry Pi';
+ result.serial = rpi.serial;
+ result.version = rpi.type + ' - ' + rpi.revision;
+ result.memMax = os.totalmem();
+ result.memSlots = 0;
+ }
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ const workload = [];
+ workload.push(execPromise('ioreg -c IOPlatformExpertDevice -d 2'));
+ workload.push(execPromise('system_profiler SPMemoryDataType'));
+ util.promiseAll(
+ workload
+ ).then((data) => {
+ let lines = data.results[0] ? data.results[0].toString().replace(/[<>"]/g, '').split('\n') : [''];
+ result.manufacturer = util.getValue(lines, 'manufacturer', '=', true);
+ result.model = util.getValue(lines, 'model', '=', true);
+ result.version = util.getValue(lines, 'version', '=', true);
+ result.serial = util.getValue(lines, 'ioplatformserialnumber', '=', true);
+ result.assetTag = util.getValue(lines, 'board-id', '=', true);
+
+ // mem
+ let devices = data.results[1] ? data.results[1].toString().split(' BANK ') : [''];
+ if (devices.length === 1) {
+ devices = data.results[1] ? data.results[1].toString().split(' DIMM') : [''];
+ }
+ devices.shift();
+ result.memSlots = devices.length;
+
+ if (os.arch() === 'arm64') {
+ result.memSlots = 0;
+ result.memMax = os.totalmem();
+ }
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_windows) {
+ try {
+ const workload = [];
+ const win10plus = parseInt(os.release()) >= 10;
+ const maxCapacityAttribute = win10plus ? 'MaxCapacityEx' : 'MaxCapacity';
+ workload.push(util.powerShell('Get-WmiObject Win32_baseboard | select Model,Manufacturer,Product,Version,SerialNumber,PartNumber,SKU | fl'));
+ workload.push(util.powerShell(`Get-WmiObject Win32_physicalmemoryarray | select ${maxCapacityAttribute}, MemoryDevices | fl`));
+ util.promiseAll(
+ workload
+ ).then((data) => {
+ let lines = data.results[0] ? data.results[0].toString().split('\r\n') : [''];
+
+ result.manufacturer = util.getValue(lines, 'manufacturer', ':');
+ result.model = util.getValue(lines, 'model', ':');
+ if (!result.model) {
+ result.model = util.getValue(lines, 'product', ':');
+ }
+ result.version = util.getValue(lines, 'version', ':');
+ result.serial = util.getValue(lines, 'serialnumber', ':');
+ result.assetTag = util.getValue(lines, 'partnumber', ':');
+ if (!result.assetTag) {
+ result.assetTag = util.getValue(lines, 'sku', ':');
+ }
+
+ // memphysical
+ lines = data.results[1] ? data.results[1].toString().split('\r\n') : [''];
+ result.memMax = util.toInt(util.getValue(lines, maxCapacityAttribute, ':')) * (win10plus ? 1024 : 1) || null;
+ result.memSlots = util.toInt(util.getValue(lines, 'MemoryDevices', ':')) || null;
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.baseboard = baseboard;
+
+function chassis(callback) {
+ const chassisTypes = ['Other',
+ 'Unknown',
+ 'Desktop',
+ 'Low Profile Desktop',
+ 'Pizza Box',
+ 'Mini Tower',
+ 'Tower',
+ 'Portable',
+ 'Laptop',
+ 'Notebook',
+ 'Hand Held',
+ 'Docking Station',
+ 'All in One',
+ 'Sub Notebook',
+ 'Space-Saving',
+ 'Lunch Box',
+ 'Main System Chassis',
+ 'Expansion Chassis',
+ 'SubChassis',
+ 'Bus Expansion Chassis',
+ 'Peripheral Chassis',
+ 'Storage Chassis',
+ 'Rack Mount Chassis',
+ 'Sealed-Case PC',
+ 'Multi-System Chassis',
+ 'Compact PCI',
+ 'Advanced TCA',
+ 'Blade',
+ 'Blade Enclosure',
+ 'Tablet',
+ 'Convertible',
+ 'Detachable',
+ 'IoT Gateway ',
+ 'Embedded PC',
+ 'Mini PC',
+ 'Stick PC',
+ ];
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = {
+ manufacturer: '',
+ model: '',
+ type: '',
+ version: '',
+ serial: '-',
+ assetTag: '-',
+ sku: '',
+ };
+ if (_linux || _freebsd || _openbsd || _netbsd) {
+ const cmd = `echo -n "chassis_asset_tag: "; cat /sys/devices/virtual/dmi/id/chassis_asset_tag 2>/dev/null; echo;
+ echo -n "chassis_serial: "; cat /sys/devices/virtual/dmi/id/chassis_serial 2>/dev/null; echo;
+ echo -n "chassis_type: "; cat /sys/devices/virtual/dmi/id/chassis_type 2>/dev/null; echo;
+ echo -n "chassis_vendor: "; cat /sys/devices/virtual/dmi/id/chassis_vendor 2>/dev/null; echo;
+ echo -n "chassis_version: "; cat /sys/devices/virtual/dmi/id/chassis_version 2>/dev/null; echo;`;
+ exec(cmd, function (error, stdout) {
+ let lines = stdout.toString().split('\n');
+ result.manufacturer = util.getValue(lines, 'chassis_vendor');
+ const ctype = parseInt(util.getValue(lines, 'chassis_type').replace(/\D/g, ''));
+ result.type = (ctype && !isNaN(ctype) && ctype < chassisTypes.length) ? chassisTypes[ctype - 1] : '';
+ result.version = util.getValue(lines, 'chassis_version');
+ result.serial = util.getValue(lines, 'chassis_serial');
+ result.assetTag = util.getValue(lines, 'chassis_asset_tag');
+ if (result.manufacturer.toLowerCase().indexOf('o.e.m.') !== -1) { result.manufacturer = '-'; }
+ if (result.version.toLowerCase().indexOf('o.e.m.') !== -1) { result.version = '-'; }
+ if (result.serial.toLowerCase().indexOf('o.e.m.') !== -1) { result.serial = '-'; }
+ if (result.assetTag.toLowerCase().indexOf('o.e.m.') !== -1) { result.assetTag = '-'; }
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ exec('ioreg -c IOPlatformExpertDevice -d 2', function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().replace(/[<>"]/g, '').split('\n');
+ result.manufacturer = util.getValue(lines, 'manufacturer', '=', true);
+ result.model = util.getValue(lines, 'model', '=', true);
+ result.version = util.getValue(lines, 'version', '=', true);
+ result.serial = util.getValue(lines, 'ioplatformserialnumber', '=', true);
+ result.assetTag = util.getValue(lines, 'board-id', '=', true);
+ }
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ if (_windows) {
+ try {
+ util.powerShell('Get-WmiObject Win32_SystemEnclosure | select Model,Manufacturer,ChassisTypes,Version,SerialNumber,PartNumber,SKU | fl').then((stdout, error) => {
+ if (!error) {
+ let lines = stdout.toString().split('\r\n');
+
+ result.manufacturer = util.getValue(lines, 'manufacturer', ':');
+ result.model = util.getValue(lines, 'model', ':');
+ const ctype = parseInt(util.getValue(lines, 'ChassisTypes', ':').replace(/\D/g, ''));
+ result.type = (ctype && !isNaN(ctype) && ctype < chassisTypes.length) ? chassisTypes[ctype - 1] : '';
+ result.version = util.getValue(lines, 'version', ':');
+ result.serial = util.getValue(lines, 'serialnumber', ':');
+ result.assetTag = util.getValue(lines, 'partnumber', ':');
+ result.sku = util.getValue(lines, 'sku', ':');
+ if (result.manufacturer.toLowerCase().indexOf('o.e.m.') !== -1) { result.manufacturer = '-'; }
+ if (result.version.toLowerCase().indexOf('o.e.m.') !== -1) { result.version = '-'; }
+ if (result.serial.toLowerCase().indexOf('o.e.m.') !== -1) { result.serial = '-'; }
+ if (result.assetTag.toLowerCase().indexOf('o.e.m.') !== -1) { result.assetTag = '-'; }
+ }
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+ });
+ });
+}
+
+exports.chassis = chassis;
+
diff --git a/MistyCore/node_modules/systeminformation/lib/usb.js b/MistyCore/node_modules/systeminformation/lib/usb.js
new file mode 100644
index 0000000..d7c1fa3
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/usb.js
@@ -0,0 +1,258 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// usb.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 16. usb
+// ----------------------------------------------------------------------------------
+
+const exec = require('child_process').exec;
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+function getLinuxUsbType(type, name) {
+ let result = type;
+ const str = (name + ' ' + type).toLowerCase();
+ if (str.indexOf('camera') >= 0) { result = 'Camera'; }
+ else if (str.indexOf('hub') >= 0) { result = 'Hub'; }
+ else if (str.indexOf('keybrd') >= 0) { result = 'Keyboard'; }
+ else if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
+ else if (str.indexOf('mouse') >= 0) { result = 'Mouse'; }
+ else if (str.indexOf('stora') >= 0) { result = 'Storage'; }
+ else if (str.indexOf('mic') >= 0) { result = 'Microphone'; }
+ else if (str.indexOf('headset') >= 0) { result = 'Audio'; }
+ else if (str.indexOf('audio') >= 0) { result = 'Audio'; }
+
+ return result;
+}
+
+function parseLinuxUsb(usb) {
+ const result = {};
+ const lines = usb.split('\n');
+ if (lines && lines.length && lines[0].indexOf('Device') >= 0) {
+ const parts = lines[0].split(' ');
+ result.bus = parseInt(parts[0], 10);
+ if (parts[2]) {
+ result.deviceId = parseInt(parts[2], 10);
+ } else {
+ result.deviceId = null;
+ }
+ } else {
+ result.bus = null;
+ result.deviceId = null;
+ }
+ const idVendor = util.getValue(lines, 'idVendor', ' ', true).trim();
+ let vendorParts = idVendor.split(' ');
+ vendorParts.shift();
+ const vendor = vendorParts.join(' ');
+
+ const idProduct = util.getValue(lines, 'idProduct', ' ', true).trim();
+ let productParts = idProduct.split(' ');
+ productParts.shift();
+ const product = productParts.join(' ');
+
+ const interfaceClass = util.getValue(lines, 'bInterfaceClass', ' ', true).trim();
+ let interfaceClassParts = interfaceClass.split(' ');
+ interfaceClassParts.shift();
+ const usbType = interfaceClassParts.join(' ');
+
+ const iManufacturer = util.getValue(lines, 'iManufacturer', ' ', true).trim();
+ let iManufacturerParts = iManufacturer.split(' ');
+ iManufacturerParts.shift();
+ const manufacturer = iManufacturerParts.join(' ');
+
+ result.id = (idVendor.startsWith('0x') ? idVendor.split(' ')[0].substr(2, 10) : '') + ':' + (idProduct.startsWith('0x') ? idProduct.split(' ')[0].substr(2, 10) : '');
+ result.name = product;
+ result.type = getLinuxUsbType(usbType, product);
+ result.removable = null;
+ result.vendor = vendor;
+ result.manufacturer = manufacturer;
+ result.maxPower = util.getValue(lines, 'MaxPower', ' ', true);
+ result.serialNumber = null;
+
+ return result;
+}
+
+function getDarwinUsbType(name) {
+ let result = '';
+ if (name.indexOf('camera') >= 0) { result = 'Camera'; }
+ else if (name.indexOf('touch bar') >= 0) { result = 'Touch Bar'; }
+ else if (name.indexOf('controller') >= 0) { result = 'Controller'; }
+ else if (name.indexOf('headset') >= 0) { result = 'Audio'; }
+ else if (name.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
+ else if (name.indexOf('trackpad') >= 0) { result = 'Trackpad'; }
+ else if (name.indexOf('sensor') >= 0) { result = 'Sensor'; }
+ else if (name.indexOf('bthusb') >= 0) { result = 'Bluetooth'; }
+ else if (name.indexOf('bth') >= 0) { result = 'Bluetooth'; }
+ else if (name.indexOf('rfcomm') >= 0) { result = 'Bluetooth'; }
+ else if (name.indexOf('usbhub') >= 0) { result = 'Hub'; }
+ else if (name.indexOf(' hub') >= 0) { result = 'Hub'; }
+ else if (name.indexOf('mouse') >= 0) { result = 'Mouse'; }
+ else if (name.indexOf('mic') >= 0) { result = 'Microphone'; }
+ else if (name.indexOf('removable') >= 0) { result = 'Storage'; }
+ return result;
+}
+
+
+function parseDarwinUsb(usb, id) {
+ const result = {};
+ result.id = id;
+
+ usb = usb.replace(/ \|/g, '');
+ usb = usb.trim();
+ let lines = usb.split('\n');
+ lines.shift();
+ try {
+ for (let i = 0; i < lines.length; i++) {
+ lines[i] = lines[i].trim();
+ lines[i] = lines[i].replace(/=/g, ':');
+ if (lines[i] !== '{' && lines[i] !== '}' && lines[i + 1] && lines[i + 1].trim() !== '}') {
+ lines[i] = lines[i] + ',';
+ }
+ lines[i] = lines[i].replace(': Yes,', ': "Yes",');
+ lines[i] = lines[i].replace(': No,', ': "No",');
+ }
+ const usbObj = JSON.parse(lines.join('\n'));
+ const removableDrive = usbObj['Built-In'].toLowerCase() !== 'yes' && usbObj['non-removable'].toLowerCase() === 'no';
+
+ result.bus = null;
+ result.deviceId = null;
+ result.id = usbObj['USB Address'] || null;
+ result.name = usbObj['kUSBProductString'] || usbObj['USB Product Name'] || null;
+ result.type = getDarwinUsbType((usbObj['kUSBProductString'] || usbObj['USB Product Name'] || '').toLowerCase() + (removableDrive ? ' removable' : ''));
+ result.removable = usbObj['non-removable'].toLowerCase() === 'no';
+ result.vendor = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null;
+ result.manufacturer = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null;
+ result.maxPower = null;
+ result.serialNumber = usbObj['kUSBSerialNumberString'] || null;
+
+ if (result.name) {
+ return result;
+ } else {
+ return null;
+ }
+ } catch (e) {
+ return null;
+ }
+}
+
+function getWindowsUsbTypeCreation(creationclass, name) {
+ let result = '';
+ if (name.indexOf('storage') >= 0) { result = 'Storage'; }
+ else if (name.indexOf('speicher') >= 0) { result = 'Storage'; }
+ else if (creationclass.indexOf('usbhub') >= 0) { result = 'Hub'; }
+ else if (creationclass.indexOf('storage') >= 0) { result = 'Storage'; }
+ else if (creationclass.indexOf('usbcontroller') >= 0) { result = 'Controller'; }
+ else if (creationclass.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
+ else if (creationclass.indexOf('pointing') >= 0) { result = 'Mouse'; }
+ else if (creationclass.indexOf('disk') >= 0) { result = 'Storage'; }
+ return result;
+}
+
+function parseWindowsUsb(lines, id) {
+ const usbType = getWindowsUsbTypeCreation(util.getValue(lines, 'CreationClassName', ':').toLowerCase(), util.getValue(lines, 'name', ':').toLowerCase());
+
+ if (usbType) {
+ const result = {};
+ result.bus = null;
+ result.deviceId = util.getValue(lines, 'deviceid', ':');
+ result.id = id;
+ result.name = util.getValue(lines, 'name', ':');
+ result.type = usbType;
+ result.removable = null;
+ result.vendor = null;
+ result.manufacturer = util.getValue(lines, 'Manufacturer', ':');
+ result.maxPower = null;
+ result.serialNumber = null;
+
+ return result;
+ } else {
+ return null;
+ }
+}
+
+function usb(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = [];
+ if (_linux) {
+ const cmd = 'export LC_ALL=C; lsusb -v 2>/dev/null; unset LC_ALL';
+ exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) {
+ if (!error) {
+ const parts = ('\n\n' + stdout.toString()).split('\n\nBus ');
+ for (let i = 1; i < parts.length; i++) {
+ const usb = parseLinuxUsb(parts[i]);
+ result.push(usb);
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ let cmd = 'ioreg -p IOUSB -c AppleUSBRootHubDevice -w0 -l';
+ exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) {
+ if (!error) {
+ const parts = (stdout.toString()).split(' +-o ');
+ for (let i = 1; i < parts.length; i++) {
+ const usb = parseDarwinUsb(parts[i]);
+ if (usb) {
+ result.push(usb);
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_windows) {
+ util.powerShell('Get-WmiObject CIM_LogicalDevice | where { $_.Description -match "USB"} | select Name,CreationClassName,DeviceId,Manufacturer | fl').then((stdout, error) => {
+ if (!error) {
+ const parts = stdout.toString().split(/\n\s*\n/);
+ for (let i = 0; i < parts.length; i++) {
+ const usb = parseWindowsUsb(parts[i].split('\n'), i);
+ if (usb) {
+ result.push(usb);
+ }
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ if (_sunos || _freebsd || _openbsd || _netbsd) {
+ resolve(null);
+ }
+ });
+ });
+}
+
+exports.usb = usb;
+
diff --git a/MistyCore/node_modules/systeminformation/lib/users.js b/MistyCore/node_modules/systeminformation/lib/users.js
new file mode 100644
index 0000000..38ecfe1
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/users.js
@@ -0,0 +1,393 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// users.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 11. Users/Sessions
+// ----------------------------------------------------------------------------------
+
+const exec = require('child_process').exec;
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+const _sunos = (_platform === 'sunos');
+
+function parseUsersLinux(lines, phase) {
+ let result = [];
+ let result_who = [];
+ let result_w = {};
+ let w_first = true;
+ let w_header = [];
+ let w_pos = [];
+ let who_line = {};
+
+ let is_whopart = true;
+ lines.forEach(function (line) {
+ if (line === '---') {
+ is_whopart = false;
+ } else {
+ let l = line.replace(/ +/g, ' ').split(' ');
+
+ // who part
+ if (is_whopart) {
+ result_who.push({
+ user: l[0],
+ tty: l[1],
+ date: l[2],
+ time: l[3],
+ ip: (l && l.length > 4) ? l[4].replace(/\(/g, '').replace(/\)/g, '') : ''
+ });
+ } else {
+ // w part
+ if (w_first) { // header
+ w_header = l;
+ w_header.forEach(function (item) {
+ w_pos.push(line.indexOf(item));
+ });
+ w_first = false;
+ } else {
+ // split by w_pos
+ result_w.user = line.substring(w_pos[0], w_pos[1] - 1).trim();
+ result_w.tty = line.substring(w_pos[1], w_pos[2] - 1).trim();
+ result_w.ip = line.substring(w_pos[2], w_pos[3] - 1).replace(/\(/g, '').replace(/\)/g, '').trim();
+ result_w.command = line.substring(w_pos[7], 1000).trim();
+ // find corresponding 'who' line
+ who_line = result_who.filter(function (obj) {
+ return (obj.user.substring(0, 8).trim() === result_w.user && obj.tty === result_w.tty);
+ });
+ if (who_line.length === 1) {
+ result.push({
+ user: who_line[0].user,
+ tty: who_line[0].tty,
+ date: who_line[0].date,
+ time: who_line[0].time,
+ ip: who_line[0].ip,
+ command: result_w.command
+ });
+ }
+ }
+ }
+ }
+ });
+ if (result.length === 0 && phase === 2) {
+ return result_who;
+ } else {
+ return result;
+ }
+}
+
+function parseUsersDarwin(lines) {
+ let result = [];
+ let result_who = [];
+ let result_w = {};
+ let who_line = {};
+
+ let is_whopart = true;
+ lines.forEach(function (line) {
+ if (line === '---') {
+ is_whopart = false;
+ } else {
+ let l = line.replace(/ +/g, ' ').split(' ');
+
+ // who part
+ if (is_whopart) {
+ result_who.push({
+ user: l[0],
+ tty: l[1],
+ date: ('' + new Date().getFullYear()) + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(l[2].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + l[3]).slice(-2),
+ time: l[4],
+ });
+ } else {
+ // w part
+ // split by w_pos
+ result_w.user = l[0];
+ result_w.tty = l[1];
+ result_w.ip = (l[2] !== '-') ? l[2] : '';
+ result_w.command = l.slice(5, 1000).join(' ');
+ // find corresponding 'who' line
+ who_line = result_who.filter(function (obj) {
+ return (obj.user === result_w.user && (obj.tty.substring(3, 1000) === result_w.tty || obj.tty === result_w.tty));
+ });
+ if (who_line.length === 1) {
+ result.push({
+ user: who_line[0].user,
+ tty: who_line[0].tty,
+ date: who_line[0].date,
+ time: who_line[0].time,
+ ip: result_w.ip,
+ command: result_w.command
+ });
+ }
+ }
+ }
+ });
+ return result;
+}
+
+function users(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = [];
+
+ // linux
+ if (_linux) {
+ exec('who --ips; echo "---"; w | tail -n +2', function (error, stdout) {
+ if (!error) {
+ // lines / split
+ let lines = stdout.toString().split('\n');
+ result = parseUsersLinux(lines, 1);
+ if (result.length === 0) {
+ exec('who; echo "---"; w | tail -n +2', function (error, stdout) {
+ if (!error) {
+ // lines / split
+ lines = stdout.toString().split('\n');
+ result = parseUsersLinux(lines, 2);
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ } else {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ }
+ if (_freebsd || _openbsd || _netbsd) {
+ exec('who; echo "---"; w -ih', function (error, stdout) {
+ if (!error) {
+ // lines / split
+ let lines = stdout.toString().split('\n');
+ result = parseUsersDarwin(lines);
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_sunos) {
+ exec('who; echo "---"; w -h', function (error, stdout) {
+ if (!error) {
+ // lines / split
+ let lines = stdout.toString().split('\n');
+ result = parseUsersDarwin(lines);
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+
+ if (_darwin) {
+ exec('who; echo "---"; w -ih', function (error, stdout) {
+ if (!error) {
+ // lines / split
+ let lines = stdout.toString().split('\n');
+ result = parseUsersDarwin(lines);
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ }
+ if (_windows) {
+ try {
+ let cmd = 'Get-WmiObject Win32_LogonSession | select LogonId,StartTime | fl' + '; echo \'#-#-#-#\';';
+ cmd += 'Get-WmiObject Win32_LoggedOnUser | select antecedent,dependent | fl ' + '; echo \'#-#-#-#\';';
+ cmd += 'Get-WmiObject Win32_Process -Filter "name=\'explorer.exe\'" | Select @{Name="sessionid";Expression={$_.SessionId}}, @{Name="domain";Expression={$_.GetOwner().Domain}}, @{Name="username";Expression={$_.GetOwner().User}} | fl' + '; echo \'#-#-#-#\';';
+ cmd += 'query user';
+ util.powerShell(cmd).then((data) => {
+ if (data) {
+ data = data.split('#-#-#-#');
+ let sessions = parseWinSessions((data[0] || '').split(/\n\s*\n/));
+ let loggedons = parseWinLoggedOn((data[1] || '').split(/\n\s*\n/));
+ let queryUser = parseWinUsersQuery((data[3] || '').split('\r\n'));
+ let users = parseWinUsers((data[2] || '').split(/\n\s*\n/), queryUser);
+ for (let id in loggedons) {
+ if ({}.hasOwnProperty.call(loggedons, id)) {
+ loggedons[id].dateTime = {}.hasOwnProperty.call(sessions, id) ? sessions[id] : '';
+ }
+ }
+ users.forEach(user => {
+ let dateTime = '';
+ for (let id in loggedons) {
+ if ({}.hasOwnProperty.call(loggedons, id)) {
+ if (loggedons[id].user === user.user && (!dateTime || dateTime < loggedons[id].dateTime)) {
+ dateTime = loggedons[id].dateTime;
+ }
+ }
+ }
+
+ result.push({
+ user: user.user,
+ tty: user.tty,
+ date: `${dateTime.substr(0, 4)}-${dateTime.substr(4, 2)}-${dateTime.substr(6, 2)}`,
+ time: `${dateTime.substr(8, 2)}:${dateTime.substr(10, 2)}`,
+ ip: '',
+ command: ''
+ });
+ });
+ }
+ if (callback) { callback(result); }
+ resolve(result);
+
+ });
+ // util.powerShell('query user').then(stdout => {
+ // if (stdout) {
+ // // lines / split
+ // let lines = stdout.toString().split('\r\n');
+ // getWinCulture()
+ // .then(culture => {
+ // result = parseUsersWin(lines, culture);
+ // if (callback) { callback(result); }
+ // resolve(result);
+ // });
+ // } else {
+ // if (callback) { callback(result); }
+ // resolve(result);
+ // }
+ // });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ }
+
+ });
+ });
+}
+
+// function parseWinAccounts(accountParts) {
+// const accounts = [];
+// accountParts.forEach(account => {
+// const lines = account.split('\r\n');
+// const name = util.getValue(lines, 'name', ':', true);
+// const domain = util.getValue(lines, 'domain', ':', true);
+// accounts.push(`${domain}\${name}`);
+// });
+// return accounts;
+// }
+
+function parseWinSessions(sessionParts) {
+ const sessions = {};
+ sessionParts.forEach(session => {
+ const lines = session.split('\r\n');
+ const id = util.getValue(lines, 'LogonId');
+ const starttime = util.getValue(lines, 'starttime');
+ if (id) {
+ sessions[id] = starttime;
+ }
+ });
+ return sessions;
+}
+
+function fuzzyMatch(name1, name2) {
+ name1 = name1.toLowerCase();
+ name2 = name2.toLowerCase();
+ let eq = 0;
+ let len = name1.length;
+ if (name2.length > len) { len = name2.length; }
+
+ for (let i = 0; i < len; i++) {
+ const c1 = name1[i] || '';
+ const c2 = name2[i] || '';
+ if (c1 === c2) { eq++; }
+ }
+ return (len > 10 ? eq / len > 0.9 : (len > 0 ? eq / len > 0.8 : false));
+}
+
+function parseWinUsers(userParts, userQuery) {
+ const users = [];
+ userParts.forEach(user => {
+ const lines = user.split('\r\n');
+
+ const domain = util.getValue(lines, 'domain', ':', true);
+ const username = util.getValue(lines, 'username', ':', true);
+ const sessionid = util.getValue(lines, 'sessionid', ':', true);
+
+ if (username) {
+ const quser = userQuery.filter(item => fuzzyMatch(item.user, username));
+ users.push({
+ domain,
+ user: username,
+ tty: quser && quser[0] && quser[0].tty ? quser[0].tty : sessionid
+ });
+ }
+ });
+ return users;
+}
+
+function parseWinLoggedOn(loggedonParts) {
+ const loggedons = {};
+ loggedonParts.forEach(loggedon => {
+ const lines = loggedon.split('\r\n');
+
+ const antecendent = util.getValue(lines, 'antecedent', ':', true);
+ let parts = antecendent.split(',');
+ const domainParts = parts.length > 1 ? parts[0].split('=') : [];
+ const nameParts = parts.length > 1 ? parts[1].split('=') : [];
+ const domain = domainParts.length > 1 ? domainParts[1].replace(/"/g, '') : '';
+ const name = nameParts.length > 1 ? nameParts[1].replace(/"/g, '') : '';
+ const dependent = util.getValue(lines, 'dependent', ':', true);
+ parts = dependent.split('=');
+ const id = parts.length > 1 ? parts[1].replace(/"/g, '') : '';
+ if (id) {
+ loggedons[id] = {
+ domain,
+ user: name
+ };
+ }
+ });
+ return loggedons;
+}
+
+function parseWinUsersQuery(lines) {
+ lines = lines.filter(item => item);
+ let result = [];
+ const header = lines[0];
+ const headerDelimiter = [];
+ if (header) {
+ const start = (header[0] === ' ') ? 1 : 0;
+ headerDelimiter.push(start - 1);
+ let nextSpace = 0;
+ for (let i = start + 1; i < header.length; i++) {
+ if (header[i] === ' ' && ((header[i - 1] === ' ') || (header[i - 1] === '.'))) {
+ nextSpace = i;
+ } else {
+ if (nextSpace) {
+ headerDelimiter.push(nextSpace);
+ nextSpace = 0;
+ }
+ }
+ }
+ for (let i = 1; i < lines.length; i++) {
+ if (lines[i].trim()) {
+ const user = lines[i].substring(headerDelimiter[0] + 1, headerDelimiter[1]).trim() || '';
+ const tty = lines[i].substring(headerDelimiter[1] + 1, headerDelimiter[2] - 2).trim() || '';
+ // const dateTime = util.parseDateTime(lines[i].substring(headerDelimiter[5] + 1, 2000).trim(), culture) || '';
+ result.push({
+ user: user,
+ tty: tty,
+ });
+ }
+ }
+ }
+ return result;
+}
+
+exports.users = users;
diff --git a/MistyCore/node_modules/systeminformation/lib/util.js b/MistyCore/node_modules/systeminformation/lib/util.js
new file mode 100644
index 0000000..8ee0a61
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/util.js
@@ -0,0 +1,1281 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// utils.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 0. helper functions
+// ----------------------------------------------------------------------------------
+
+const os = require('os');
+const fs = require('fs');
+const path = require('path');
+const spawn = require('child_process').spawn;
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const util = require('util');
+
+let _platform = process.platform;
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+const _freebsd = (_platform === 'freebsd');
+const _openbsd = (_platform === 'openbsd');
+const _netbsd = (_platform === 'netbsd');
+// const _sunos = (_platform === 'sunos');
+
+let _cores = 0;
+let wmicPath = '';
+let codepage = '';
+let _smartMonToolsInstalled = null;
+
+const WINDIR = process.env.WINDIR || 'C:\\Windows';
+
+// powerShell
+let _psChild;
+let _psResult = '';
+let _psCmds = [];
+let _psPersistent = false;
+const _psToUTF8 = '$OutputEncoding = [System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8 ; ';
+const _psCmdStart = '--###START###--';
+const _psError = '--ERROR--';
+const _psCmdSeperator = '--###ENDCMD###--';
+const _psIdSeperator = '--##ID##--';
+
+const execOptsWin = {
+ windowsHide: true,
+ maxBuffer: 1024 * 20000,
+ encoding: 'UTF-8',
+ env: util._extend({}, process.env, { LANG: 'en_US.UTF-8' })
+};
+
+function toInt(value) {
+ let result = parseInt(value, 10);
+ if (isNaN(result)) {
+ result = 0;
+ }
+ return result;
+}
+
+
+const stringReplace = new String().replace;
+const stringToLower = new String().toLowerCase;
+const stringToString = new String().toString;
+const stringSubstr = new String().substr;
+const stringTrim = new String().trim;
+const stringStartWith = new String().startsWith;
+const mathMin = Math.min;
+
+function isFunction(functionToCheck) {
+ let getType = {};
+ return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
+}
+
+function unique(obj) {
+ let uniques = [];
+ let stringify = {};
+ for (let i = 0; i < obj.length; i++) {
+ let keys = Object.keys(obj[i]);
+ keys.sort(function (a, b) { return a - b; });
+ let str = '';
+ for (let j = 0; j < keys.length; j++) {
+ str += JSON.stringify(keys[j]);
+ str += JSON.stringify(obj[i][keys[j]]);
+ }
+ if (!{}.hasOwnProperty.call(stringify, str)) {
+ uniques.push(obj[i]);
+ stringify[str] = true;
+ }
+ }
+ return uniques;
+}
+
+function sortByKey(array, keys) {
+ return array.sort(function (a, b) {
+ let x = '';
+ let y = '';
+ keys.forEach(function (key) {
+ x = x + a[key]; y = y + b[key];
+ });
+ return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ });
+}
+
+function cores() {
+ if (_cores === 0) {
+ _cores = os.cpus().length;
+ }
+ return _cores;
+}
+
+function getValue(lines, property, separator, trimmed, lineMatch) {
+ separator = separator || ':';
+ property = property.toLowerCase();
+ trimmed = trimmed || false;
+ lineMatch = lineMatch || false;
+ for (let i = 0; i < lines.length; i++) {
+ let line = lines[i].toLowerCase().replace(/\t/g, '');
+ if (trimmed) {
+ line = line.trim();
+ }
+ if (line.startsWith(property) && (lineMatch ? (line.match(property + separator)) : true)) {
+ const parts = trimmed ? lines[i].trim().split(separator) : lines[i].split(separator);
+ if (parts.length >= 2) {
+ parts.shift();
+ return parts.join(separator).trim();
+ } else {
+ return '';
+ }
+ }
+ }
+ return '';
+}
+
+function decodeEscapeSequence(str, base) {
+ base = base || 16;
+ return str.replace(/\\x([0-9A-Fa-f]{2})/g, function () {
+ return String.fromCharCode(parseInt(arguments[1], base));
+ });
+}
+
+function detectSplit(str) {
+ let seperator = '';
+ let part = 0;
+ str.split('').forEach(element => {
+ if (element >= '0' && element <= '9') {
+ if (part === 1) { part++; }
+ } else {
+ if (part === 0) { part++; }
+ if (part === 1) {
+ seperator += element;
+ }
+ }
+ });
+ return seperator;
+}
+
+function parseTime(t, pmDesignator) {
+ pmDesignator = pmDesignator || '';
+ t = t.toUpperCase();
+ let hour = 0;
+ let min = 0;
+ let splitter = detectSplit(t);
+ let parts = t.split(splitter);
+ if (parts.length >= 2) {
+ if (parts[2]) {
+ parts[1] += parts[2];
+ }
+ let isPM = (parts[1] && (parts[1].toLowerCase().indexOf('pm') > -1) || (parts[1].toLowerCase().indexOf('p.m.') > -1) || (parts[1].toLowerCase().indexOf('p. m.') > -1) || (parts[1].toLowerCase().indexOf('n') > -1) || (parts[1].toLowerCase().indexOf('ch') > -1) || (parts[1].toLowerCase().indexOf('ös') > -1) || (pmDesignator && parts[1].toLowerCase().indexOf(pmDesignator) > -1));
+ hour = parseInt(parts[0], 10);
+ min = parseInt(parts[1], 10);
+ hour = isPM && hour < 12 ? hour + 12 : hour;
+ return ('0' + hour).substr(-2) + ':' + ('0' + min).substr(-2);
+ }
+}
+
+function parseDateTime(dt, culture) {
+ const result = {
+ date: '',
+ time: ''
+ };
+ culture = culture || {};
+ let dateFormat = (culture.dateFormat || '').toLowerCase();
+ let pmDesignator = (culture.pmDesignator || '');
+
+ const parts = dt.split(' ');
+ if (parts[0]) {
+ if (parts[0].indexOf('/') >= 0) {
+ // Dateformat: mm/dd/yyyy or dd/mm/yyyy or dd/mm/yy or yyyy/mm/dd
+ const dtparts = parts[0].split('/');
+ if (dtparts.length === 3) {
+ if (dtparts[0].length === 4) {
+ // Dateformat: yyyy/mm/dd
+ result.date = dtparts[0] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[2]).substr(-2);
+ } else if (dtparts[2].length === 2) {
+ if ((dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1)) {
+ // Dateformat: mm/dd/yy
+ result.date = '20' + dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
+ } else {
+ // Dateformat: dd/mm/yy
+ result.date = '20' + dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
+ }
+ } else {
+ // Dateformat: mm/dd/yyyy or dd/mm/yyyy
+ const isEN = ((dt.toLowerCase().indexOf('pm') > -1) || (dt.toLowerCase().indexOf('p.m.') > -1) || (dt.toLowerCase().indexOf('p. m.') > -1) || (dt.toLowerCase().indexOf('am') > -1) || (dt.toLowerCase().indexOf('a.m.') > -1) || (dt.toLowerCase().indexOf('a. m.') > -1));
+ if ((isEN || dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1) && dateFormat.indexOf('dd/') !== 0) {
+ // Dateformat: mm/dd/yyyy
+ result.date = dtparts[2] + '-' + ('0' + dtparts[0]).substr(-2) + '-' + ('0' + dtparts[1]).substr(-2);
+ } else {
+ // Dateformat: dd/mm/yyyy
+ result.date = dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
+ }
+ }
+ }
+ }
+ if (parts[0].indexOf('.') >= 0) {
+ const dtparts = parts[0].split('.');
+ if (dtparts.length === 3) {
+ if (dateFormat.indexOf('.d.') > -1 || dateFormat.indexOf('.dd.') > -1) {
+ // Dateformat: mm.dd.yyyy
+ result.date = dtparts[2] + '-' + ('0' + dtparts[0]).substr(-2) + '-' + ('0' + dtparts[1]).substr(-2);
+ } else {
+ // Dateformat: dd.mm.yyyy
+ result.date = dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
+ }
+ }
+ }
+ if (parts[0].indexOf('-') >= 0) {
+ // Dateformat: yyyy-mm-dd
+ const dtparts = parts[0].split('-');
+ if (dtparts.length === 3) {
+ result.date = dtparts[0] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[2]).substr(-2);
+ }
+ }
+ }
+ if (parts[1]) {
+ parts.shift();
+ let time = parts.join(' ');
+ result.time = parseTime(time, pmDesignator);
+ }
+ return result;
+}
+
+function parseHead(head, rights) {
+ let space = (rights > 0);
+ let count = 1;
+ let from = 0;
+ let to = 0;
+ let result = [];
+ for (let i = 0; i < head.length; i++) {
+ if (count <= rights) {
+ // if (head[i] === ' ' && !space) {
+ if (/\s/.test(head[i]) && !space) {
+ to = i - 1;
+ result.push({
+ from: from,
+ to: to + 1,
+ cap: head.substring(from, to + 1)
+ });
+ from = to + 2;
+ count++;
+ }
+ space = head[i] === ' ';
+ } else {
+ if (!/\s/.test(head[i]) && space) {
+ to = i - 1;
+ if (from < to) {
+ result.push({
+ from: from,
+ to: to,
+ cap: head.substring(from, to)
+ });
+ }
+ from = to + 1;
+ count++;
+ }
+ space = head[i] === ' ';
+ }
+ }
+ to = 1000;
+ result.push({
+ from: from,
+ to: to,
+ cap: head.substring(from, to)
+ });
+ let len = result.length;
+ for (var i = 0; i < len; i++) {
+ if (result[i].cap.replace(/\s/g, '').length === 0) {
+ if (i + 1 < len) {
+ result[i].to = result[i + 1].to;
+ result[i].cap = result[i].cap + result[i + 1].cap;
+ result.splice(i + 1, 1);
+ len = len - 1;
+ }
+ }
+ }
+ return result;
+}
+
+function findObjectByKey(array, key, value) {
+ for (let i = 0; i < array.length; i++) {
+ if (array[i][key] === value) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+function getWmic() {
+ if (os.type() === 'Windows_NT' && !wmicPath) {
+ wmicPath = WINDIR + '\\system32\\wbem\\wmic.exe';
+ if (!fs.existsSync(wmicPath)) {
+ try {
+ const wmicPathArray = execSync('WHERE WMIC', execOptsWin).toString().split('\r\n');
+ if (wmicPathArray && wmicPathArray.length) {
+ wmicPath = wmicPathArray[0];
+ } else {
+ wmicPath = 'wmic';
+ }
+ } catch (e) {
+ wmicPath = 'wmic';
+ }
+ }
+ }
+ return wmicPath;
+}
+
+function wmic(command) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ try {
+ powerShell(getWmic() + ' ' + command).then(stdout => {
+ resolve(stdout, '');
+ });
+ } catch (e) {
+ resolve('', e);
+ }
+ });
+ });
+}
+
+// function wmic(command, options) {
+// options = options || execOptsWin;
+// return new Promise((resolve) => {
+// process.nextTick(() => {
+// try {
+// exec(WINDIR + '\\system32\\chcp.com 65001 | ' + getWmic() + ' ' + command, options, function (error, stdout) {
+// resolve(stdout, error);
+// }).stdin.end();
+// } catch (e) {
+// resolve('', e);
+// }
+// });
+// });
+// }
+
+function getVboxmanage() {
+ return _windows ? `"${process.env.VBOX_INSTALL_PATH || process.env.VBOX_MSI_INSTALL_PATH}\\VBoxManage.exe"` : 'vboxmanage';
+}
+
+function powerShellProceedResults(data) {
+ let id = '';
+ let parts;
+ let res = '';
+ // startID
+ if (data.indexOf(_psCmdStart) >= 0) {
+ parts = data.split(_psCmdStart);
+ const parts2 = parts[1].split(_psIdSeperator);
+ id = parts2[0];
+ if (parts2.length > 1) {
+ data = parts2.slice(1).join(_psIdSeperator);
+ }
+ }
+ // result;
+ if (data.indexOf(_psCmdSeperator) >= 0) {
+ parts = data.split(_psCmdSeperator);
+ res = parts[0];
+ }
+ let remove = -1;
+ for (let i = 0; i < _psCmds.length; i++) {
+ if (_psCmds[i].id === id) {
+ remove = i;
+ // console.log(`----- TIME : ${(new Date() - _psCmds[i].start) * 0.001} s`);
+
+ _psCmds[i].callback(res);
+ }
+ }
+ if (remove >= 0) {
+ _psCmds.splice(remove, 1);
+ }
+}
+
+function powerShellStart() {
+ if (!_psChild) {
+ _psChild = spawn('powershell.exe', ['-NoLogo', '-InputFormat', 'Text', '-NoExit', '-Command', '-'], {
+ stdio: 'pipe',
+ windowsHide: true,
+ maxBuffer: 1024 * 20000,
+ encoding: 'UTF-8',
+ env: util._extend({}, process.env, { LANG: 'en_US.UTF-8' })
+ });
+ if (_psChild && _psChild.pid) {
+ _psPersistent = true;
+ _psChild.stdout.on('data', function (data) {
+ _psResult = _psResult + data.toString('utf8');
+ if (data.indexOf(_psCmdSeperator) >= 0) {
+ powerShellProceedResults(_psResult);
+ _psResult = '';
+ }
+ });
+ _psChild.stderr.on('data', function () {
+ powerShellProceedResults(_psResult + _psError);
+ });
+ _psChild.on('error', function () {
+ powerShellProceedResults(_psResult + _psError);
+ });
+ _psChild.on('close', function () {
+ _psChild.kill();
+ });
+ }
+ }
+}
+
+function powerShellRelease() {
+ try {
+ if (_psChild) {
+ _psChild.stdin.write('exit' + os.EOL);
+ _psChild.stdin.end();
+ _psPersistent = false;
+ }
+ } catch (e) {
+ _psChild.kill();
+ }
+ _psChild = null;
+}
+
+function powerShell(cmd) {
+
+ if (_psPersistent) {
+ const id = Math.random().toString(36).substr(2, 10);
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ function callback(data) {
+ resolve(data);
+ }
+ _psCmds.push({
+ id,
+ cmd,
+ callback,
+ start: new Date()
+ });
+ try {
+ if (_psChild && _psChild.pid) {
+ _psChild.stdin.write(_psToUTF8 + 'echo ' + _psCmdStart + id + _psIdSeperator + '; ' + os.EOL + cmd + os.EOL + 'echo ' + _psCmdSeperator + os.EOL);
+ }
+ } catch (e) {
+ resolve('');
+ }
+ });
+ });
+
+ } else {
+ let result = '';
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ try {
+ // const start = new Date();
+ const child = spawn('powershell.exe', ['-NoLogo', '-InputFormat', 'Text', '-NoExit', '-ExecutionPolicy', 'Unrestricted', '-Command', '-'], {
+ stdio: 'pipe',
+ windowsHide: true,
+ maxBuffer: 1024 * 20000,
+ encoding: 'UTF-8',
+ env: util._extend({}, process.env, { LANG: 'en_US.UTF-8' })
+ });
+
+ if (child && !child.pid) {
+ child.on('error', function () {
+ resolve(result);
+ });
+ }
+ if (child && child.pid) {
+ child.stdout.on('data', function (data) {
+ result = result + data.toString('utf8');
+ });
+ child.stderr.on('data', function () {
+ child.kill();
+ resolve(result);
+ });
+ child.on('close', function () {
+ child.kill();
+ // console.log(`----- TIME : ${(new Date() - start) * 0.001} s`);
+
+ resolve(result);
+ });
+ child.on('error', function () {
+ child.kill();
+ resolve(result);
+ });
+ try {
+ child.stdin.write(_psToUTF8 + cmd + os.EOL);
+ child.stdin.write('exit' + os.EOL);
+ child.stdin.end();
+ } catch (e) {
+ child.kill();
+ resolve(result);
+ }
+ } else {
+ resolve(result);
+ }
+ } catch (e) {
+ resolve(result);
+ }
+ });
+ });
+ }
+}
+
+function execSafe(cmd, args, options) {
+ let result = '';
+ options = options || {};
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ try {
+ const child = spawn(cmd, args, options);
+
+ if (child && !child.pid) {
+ child.on('error', function () {
+ resolve(result);
+ });
+ }
+ if (child && child.pid) {
+ child.stdout.on('data', function (data) {
+ result += data.toString();
+ });
+ child.on('close', function () {
+ child.kill();
+ resolve(result);
+ });
+ child.on('error', function () {
+ child.kill();
+ resolve(result);
+ });
+ } else {
+ resolve(result);
+ }
+ } catch (e) {
+ resolve(result);
+ }
+ });
+ });
+}
+
+function getCodepage() {
+ if (_windows) {
+ if (!codepage) {
+ try {
+ const stdout = execSync('chcp', execOptsWin);
+ const lines = stdout.toString().split('\r\n');
+ const parts = lines[0].split(':');
+ codepage = parts.length > 1 ? parts[1].replace('.', '') : '';
+ } catch (err) {
+ codepage = '437';
+ }
+ }
+ return codepage;
+ }
+ if (_linux || _darwin || _freebsd || _openbsd || _netbsd) {
+ if (!codepage) {
+ try {
+ const stdout = execSync('echo $LANG');
+ const lines = stdout.toString().split('\r\n');
+ const parts = lines[0].split('.');
+ codepage = parts.length > 1 ? parts[1].trim() : '';
+ if (!codepage) {
+ codepage = 'UTF-8';
+ }
+ } catch (err) {
+ codepage = 'UTF-8';
+ }
+ }
+ return codepage;
+ }
+}
+
+function smartMonToolsInstalled() {
+ if (_smartMonToolsInstalled !== null) {
+ return _smartMonToolsInstalled;
+ }
+ _smartMonToolsInstalled = false;
+ if (_windows) {
+ try {
+ const pathArray = execSync('WHERE smartctl 2>nul', execOptsWin).toString().split('\r\n');
+ if (pathArray && pathArray.length) {
+ _smartMonToolsInstalled = pathArray[0].indexOf(':\\') >= 0;
+ } else {
+ _smartMonToolsInstalled = false;
+ }
+ } catch (e) {
+ _smartMonToolsInstalled = false;
+ }
+ }
+ if (_linux || _darwin || _freebsd || _openbsd || _netbsd) {
+ const pathArray = execSync('which smartctl 2>/dev/null', execOptsWin).toString().split('\r\n');
+ _smartMonToolsInstalled = pathArray.length > 0;
+ }
+ return _smartMonToolsInstalled;
+}
+
+function isRaspberry() {
+ const PI_MODEL_NO = [
+ 'BCM2708',
+ 'BCM2709',
+ 'BCM2710',
+ 'BCM2711',
+ 'BCM2835',
+ 'BCM2836',
+ 'BCM2837',
+ 'BCM2837B0'
+ ];
+ let cpuinfo = [];
+ try {
+ cpuinfo = fs.readFileSync('/proc/cpuinfo', { encoding: 'utf8' }).toString().split('\n');
+ } catch (e) {
+ return false;
+ }
+ const hardware = getValue(cpuinfo, 'hardware');
+ return (hardware && PI_MODEL_NO.indexOf(hardware) > -1);
+}
+
+function isRaspbian() {
+ let osrelease = [];
+ try {
+ osrelease = fs.readFileSync('/etc/os-release', { encoding: 'utf8' }).toString().split('\n');
+ } catch (e) {
+ return false;
+ }
+ const id = getValue(osrelease, 'id', '=');
+ return (id && id.indexOf('raspbian') > -1);
+}
+
+function execWin(cmd, opts, callback) {
+ if (!callback) {
+ callback = opts;
+ opts = execOptsWin;
+ }
+ let newCmd = 'chcp 65001 > nul && cmd /C ' + cmd + ' && chcp ' + codepage + ' > nul';
+ exec(newCmd, opts, function (error, stdout) {
+ callback(error, stdout);
+ });
+}
+
+function darwinXcodeExists() {
+ const cmdLineToolsExists = fs.existsSync('/Library/Developer/CommandLineTools/usr/bin/');
+ const xcodeAppExists = fs.existsSync('/Applications/Xcode.app/Contents/Developer/Tools');
+ const xcodeExists = fs.existsSync('/Library/Developer/Xcode/');
+ return (cmdLineToolsExists || xcodeExists || xcodeAppExists);
+}
+
+function nanoSeconds() {
+ const time = process.hrtime();
+ if (!Array.isArray(time) || time.length !== 2) {
+ return 0;
+ }
+ return +time[0] * 1e9 + +time[1];
+}
+
+function countUniqueLines(lines, startingWith) {
+ startingWith = startingWith || '';
+ const uniqueLines = [];
+ lines.forEach(line => {
+ if (line.startsWith(startingWith)) {
+ if (uniqueLines.indexOf(line) === -1) {
+ uniqueLines.push(line);
+ }
+ }
+ });
+ return uniqueLines.length;
+}
+
+function countLines(lines, startingWith) {
+ startingWith = startingWith || '';
+ const uniqueLines = [];
+ lines.forEach(line => {
+ if (line.startsWith(startingWith)) {
+ uniqueLines.push(line);
+ }
+ });
+ return uniqueLines.length;
+}
+
+function sanitizeShellString(str, strict) {
+ if (typeof strict === 'undefined') { strict = false; }
+ const s = str || '';
+ let result = '';
+ for (let i = 0; i <= mathMin(s.length, 2000); i++) {
+ if (!(s[i] === undefined ||
+ s[i] === '>' ||
+ s[i] === '<' ||
+ s[i] === '*' ||
+ s[i] === '?' ||
+ s[i] === '[' ||
+ s[i] === ']' ||
+ s[i] === '|' ||
+ s[i] === '˚' ||
+ s[i] === '$' ||
+ s[i] === ';' ||
+ s[i] === '&' ||
+ s[i] === '(' ||
+ s[i] === ')' ||
+ s[i] === ']' ||
+ s[i] === '#' ||
+ s[i] === '\\' ||
+ s[i] === '\t' ||
+ s[i] === '\n' ||
+ s[i] === '\'' ||
+ s[i] === '`' ||
+ s[i] === '"' ||
+ s[i].length > 1 ||
+ (strict && s[i] === '@') ||
+ (strict && s[i] === ' ') ||
+ (strict && s[i] == '{') ||
+ (strict && s[i] == ')'))) {
+ result = result + s[i];
+ }
+ }
+ return result;
+}
+
+function isPrototypePolluted() {
+ const s = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ let notPolluted = true;
+ let st = '';
+
+ st.__proto__.replace = stringReplace;
+ st.__proto__.toLowerCase = stringToLower;
+ st.__proto__.toString = stringToString;
+ st.__proto__.substr = stringSubstr;
+
+ notPolluted = notPolluted || !(s.length === 62);
+ const ms = Date.now();
+ if (typeof ms === 'number' && ms > 1600000000000) {
+ const l = ms % 100 + 15;
+ for (let i = 0; i < l; i++) {
+ const r = Math.random() * 61.99999999 + 1;
+ const rs = parseInt(Math.floor(r).toString(), 10);
+ const rs2 = parseInt(r.toString().split('.')[0], 10);
+ const q = Math.random() * 61.99999999 + 1;
+ const qs = parseInt(Math.floor(q).toString(), 10);
+ const qs2 = parseInt(q.toString().split('.')[0], 10);
+ notPolluted = notPolluted && !(r === q);
+ notPolluted = notPolluted && rs === rs2 && qs === qs2;
+ st += s[rs - 1];
+ }
+ notPolluted = notPolluted && st.length === l;
+ // string manipulation
+ let p = Math.random() * l * 0.9999999999;
+ let stm = st.substr(0, p) + ' ' + st.substr(p, 2000);
+ stm.__proto__.replace = stringReplace;
+ let sto = stm.replace(/ /g, '');
+ notPolluted = notPolluted && st === sto;
+ p = Math.random() * l * 0.9999999999;
+ stm = st.substr(0, p) + '{' + st.substr(p, 2000);
+ sto = stm.replace(/{/g, '');
+ notPolluted = notPolluted && st === sto;
+ p = Math.random() * l * 0.9999999999;
+ stm = st.substr(0, p) + '*' + st.substr(p, 2000);
+ sto = stm.replace(/\*/g, '');
+ notPolluted = notPolluted && st === sto;
+ p = Math.random() * l * 0.9999999999;
+ stm = st.substr(0, p) + '$' + st.substr(p, 2000);
+ sto = stm.replace(/\$/g, '');
+ notPolluted = notPolluted && st === sto;
+
+ // lower
+ const stl = st.toLowerCase();
+ notPolluted = notPolluted && (stl.length === l) && stl[l - 1] && !(stl[l]);
+ for (let i = 0; i < l; i++) {
+ const s1 = st[i];
+ s1.__proto__.toLowerCase = stringToLower;
+ const s2 = stl ? stl[i] : '';
+ const s1l = s1.toLowerCase();
+ notPolluted = notPolluted && s1l[0] === s2 && s1l[0] && !(s1l[1]);
+ }
+ }
+ return !notPolluted;
+}
+
+function hex2bin(hex) {
+ return ('00000000' + (parseInt(hex, 16)).toString(2)).substr(-8);
+}
+
+function getFilesInPath(source) {
+ const lstatSync = fs.lstatSync;
+ const readdirSync = fs.readdirSync;
+ const join = path.join;
+
+ function isDirectory(source) {
+ return lstatSync(source).isDirectory();
+ }
+ function isFile(source) { return lstatSync(source).isFile(); }
+
+ function getDirectories(source) {
+ return readdirSync(source).map(function (name) { return join(source, name); }).filter(isDirectory);
+ }
+ function getFiles(source) {
+ return readdirSync(source).map(function (name) { return join(source, name); }).filter(isFile);
+ }
+
+ function getFilesRecursively(source) {
+ try {
+ let dirs = getDirectories(source);
+ let files = dirs
+ .map(function (dir) { return getFilesRecursively(dir); })
+ .reduce(function (a, b) { return a.concat(b); }, []);
+ return files.concat(getFiles(source));
+ } catch (e) {
+ return [];
+ }
+ }
+
+ if (fs.existsSync(source)) {
+ return getFilesRecursively(source);
+ } else {
+ return [];
+ }
+}
+
+function decodePiCpuinfo(lines) {
+
+ // https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
+
+ const oldRevisionCodes = {
+ '0002': {
+ type: 'B',
+ revision: '1.0',
+ memory: 256,
+ manufacturer: 'Egoman',
+ processor: 'BCM2835'
+ },
+ '0003': {
+ type: 'B',
+ revision: '1.0',
+ memory: 256,
+ manufacturer: 'Egoman',
+ processor: 'BCM2835'
+ },
+ '0004': {
+ type: 'B',
+ revision: '2.0',
+ memory: 256,
+ manufacturer: 'Sony UK',
+ processor: 'BCM2835'
+ },
+ '0005': {
+ type: 'B',
+ revision: '2.0',
+ memory: 256,
+ manufacturer: 'Qisda',
+ processor: 'BCM2835'
+ },
+ '0006': {
+ type: 'B',
+ revision: '2.0',
+ memory: 256,
+ manufacturer: 'Egoman',
+ processor: 'BCM2835'
+ },
+ '0007': {
+ type: 'A',
+ revision: '2.0',
+ memory: 256,
+ manufacturer: 'Egoman',
+ processor: 'BCM2835'
+ },
+ '0008': {
+ type: 'A',
+ revision: '2.0',
+ memory: 256,
+ manufacturer: 'Sony UK',
+ processor: 'BCM2835'
+ },
+ '0009': {
+ type: 'A',
+ revision: '2.0',
+ memory: 256,
+ manufacturer: 'Qisda',
+ processor: 'BCM2835'
+ },
+ '000d': {
+ type: 'B',
+ revision: '2.0',
+ memory: 512,
+ manufacturer: 'Egoman',
+ processor: 'BCM2835'
+ },
+ '000e': {
+ type: 'B',
+ revision: '2.0',
+ memory: 512,
+ manufacturer: 'Sony UK',
+ processor: 'BCM2835'
+ },
+ '000f': {
+ type: 'B',
+ revision: '2.0',
+ memory: 512,
+ manufacturer: 'Egoman',
+ processor: 'BCM2835'
+ },
+ '0010': {
+ type: 'B+',
+ revision: '1.2',
+ memory: 512,
+ manufacturer: 'Sony UK',
+ processor: 'BCM2835'
+ },
+ '0011': {
+ type: 'CM1',
+ revision: '1.0',
+ memory: 512,
+ manufacturer: 'Sony UK',
+ processor: 'BCM2835'
+ },
+ '0012': {
+ type: 'A+',
+ revision: '1.1',
+ memory: 256,
+ manufacturer: 'Sony UK',
+ processor: 'BCM2835'
+ },
+ '0013': {
+ type: 'B+',
+ revision: '1.2',
+ memory: 512,
+ manufacturer: 'Embest',
+ processor: 'BCM2835'
+ },
+ '0014': {
+ type: 'CM1',
+ revision: '1.0',
+ memory: 512,
+ manufacturer: 'Embest',
+ processor: 'BCM2835'
+ },
+ '0015': {
+ type: 'A+',
+ revision: '1.1',
+ memory: 256,
+ manufacturer: '512MB Embest',
+ processor: 'BCM2835'
+ }
+ };
+
+ const processorList = [
+ 'BCM2835',
+ 'BCM2836',
+ 'BCM2837',
+ 'BCM2711',
+ ];
+ const manufacturerList = [
+ 'Sony UK',
+ 'Egoman',
+ 'Embest',
+ 'Sony Japan',
+ 'Embest',
+ 'Stadium'
+ ];
+ const typeList = {
+ '00': 'A',
+ '01': 'B',
+ '02': 'A+',
+ '03': 'B+',
+ '04': '2B',
+ '05': 'Alpha (early prototype)',
+ '06': 'CM1',
+ '08': '3B',
+ '09': 'Zero',
+ '0a': 'CM3',
+ '0c': 'Zero W',
+ '0d': '3B+',
+ '0e': '3A+',
+ '0f': 'Internal use only',
+ '10': 'CM3+',
+ '11': '4B',
+ '12': 'Zero 2 W',
+ '13': '400',
+ '14': 'CM4'
+ };
+
+ const revisionCode = getValue(lines, 'revision', ':', true);
+ const model = getValue(lines, 'model:', ':', true);
+ const serial = getValue(lines, 'serial', ':', true);
+
+ let result = {};
+ if ({}.hasOwnProperty.call(oldRevisionCodes, revisionCode)) {
+ // old revision codes
+ result = {
+ model,
+ serial,
+ revisionCode,
+ memory: oldRevisionCodes[revisionCode].memory,
+ manufacturer: oldRevisionCodes[revisionCode].manufacturer,
+ processor: oldRevisionCodes[revisionCode].processor,
+ type: oldRevisionCodes[revisionCode].type,
+ revision: oldRevisionCodes[revisionCode].revision,
+ };
+
+ } else {
+ // new revision code
+ const revision = ('00000000' + getValue(lines, 'revision', ':', true).toLowerCase()).substr(-8);
+ // const revisionStyleNew = hex2bin(revision.substr(2, 1)).substr(4, 1) === '1';
+ const memSizeCode = parseInt(hex2bin(revision.substr(2, 1)).substr(5, 3), 2) || 0;
+ const manufacturer = manufacturerList[parseInt(revision.substr(3, 1), 10)];
+ const processor = processorList[parseInt(revision.substr(4, 1), 10)];
+ const typeCode = revision.substr(5, 2);
+
+
+ result = {
+ model,
+ serial,
+ revisionCode,
+ memory: 256 * Math.pow(2, memSizeCode),
+ manufacturer,
+ processor,
+ type: {}.hasOwnProperty.call(typeList, typeCode) ? typeList[typeCode] : '',
+ revision: '1.' + revision.substr(7, 1),
+ };
+ }
+ return result;
+}
+
+function promiseAll(promises) {
+ const resolvingPromises = promises.map(function (promise) {
+ return new Promise(function (resolve) {
+ var payload = new Array(2);
+ promise.then(function (result) {
+ payload[0] = result;
+ })
+ .catch(function (error) {
+ payload[1] = error;
+ })
+ .then(function () {
+ // The wrapped Promise returns an array: 0 = result, 1 = error ... we resolve all
+ resolve(payload);
+ });
+ });
+ });
+ var errors = [];
+ var results = [];
+
+ // Execute all wrapped Promises
+ return Promise.all(resolvingPromises)
+ .then(function (items) {
+ items.forEach(function (payload) {
+ if (payload[1]) {
+ errors.push(payload[1]);
+ results.push(null);
+ } else {
+ errors.push(null);
+ results.push(payload[0]);
+ }
+ });
+
+ return {
+ errors: errors,
+ results: results
+ };
+ });
+}
+
+function promisify(nodeStyleFunction) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments);
+ return new Promise(function (resolve, reject) {
+ args.push(function (err, data) {
+ if (err) {
+ reject(err);
+ } else {
+ resolve(data);
+ }
+ });
+ nodeStyleFunction.apply(null, args);
+ });
+ };
+}
+
+function promisifySave(nodeStyleFunction) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments);
+ return new Promise(function (resolve) {
+ args.push(function (err, data) {
+ resolve(data);
+ });
+ nodeStyleFunction.apply(null, args);
+ });
+ };
+}
+
+function linuxVersion() {
+ let result = '';
+ if (_linux) {
+ try {
+ result = execSync('uname -v').toString();
+ } catch (e) {
+ result = '';
+ }
+ }
+ return result;
+}
+
+function plistParser(xmlStr) {
+ const tags = ['array', 'dict', 'key', 'string', 'integer', 'date', 'real', 'data', 'boolean', 'arrayEmpty'];
+ const startStr = '<plist version';
+
+ let pos = xmlStr.indexOf(startStr);
+ let len = xmlStr.length;
+ while (xmlStr[pos] !== '>' && pos < len) {
+ pos++;
+ }
+
+ let depth = 0;
+ let inTagStart = false;
+ let inTagContent = false;
+ let inTagEnd = false;
+ let metaData = [{ tagStart: '', tagEnd: '', tagContent: '', key: '', data: null }];
+ let c = '';
+ let cn = xmlStr[pos];
+
+ while (pos < len) {
+ c = cn;
+ if (pos + 1 < len) { cn = xmlStr[pos + 1]; }
+ if (c === '<') {
+ inTagContent = false;
+ if (cn === '/') { inTagEnd = true; }
+ else if (metaData[depth].tagStart) {
+ metaData[depth].tagContent = '';
+ if (!metaData[depth].data) { metaData[depth].data = metaData[depth].tagStart === 'array' ? [] : {}; }
+ depth++;
+ metaData.push({ tagStart: '', tagEnd: '', tagContent: '', key: null, data: null });
+ inTagStart = true;
+ inTagContent = false;
+ }
+ else if (!inTagStart) { inTagStart = true; }
+ } else if (c === '>') {
+ if (metaData[depth].tagStart === 'true/') { inTagStart = false; inTagEnd = true; metaData[depth].tagStart = ''; metaData[depth].tagEnd = '/boolean'; metaData[depth].data = true; }
+ if (metaData[depth].tagStart === 'false/') { inTagStart = false; inTagEnd = true; metaData[depth].tagStart = ''; metaData[depth].tagEnd = '/boolean'; metaData[depth].data = false; }
+ if (metaData[depth].tagStart === 'array/') { inTagStart = false; inTagEnd = true; metaData[depth].tagStart = ''; metaData[depth].tagEnd = '/arrayEmpty'; metaData[depth].data = []; }
+ if (inTagContent) { inTagContent = false; }
+ if (inTagStart) {
+ inTagStart = false;
+ inTagContent = true;
+ if (metaData[depth].tagStart === 'array') {
+ metaData[depth].data = [];
+ }
+ if (metaData[depth].tagStart === 'dict') {
+ metaData[depth].data = {};
+ }
+ }
+ if (inTagEnd) {
+ inTagEnd = false;
+ if (metaData[depth].tagEnd && tags.indexOf(metaData[depth].tagEnd.substr(1)) >= 0) {
+ if (metaData[depth].tagEnd === '/dict' || metaData[depth].tagEnd === '/array') {
+ if (depth > 1 && metaData[depth - 2].tagStart === 'array') {
+ metaData[depth - 2].data.push(metaData[depth - 1].data);
+ }
+ if (depth > 1 && metaData[depth - 2].tagStart === 'dict') {
+ metaData[depth - 2].data[metaData[depth - 1].key] = metaData[depth - 1].data;
+ }
+ depth--;
+ metaData.pop();
+ metaData[depth].tagContent = '';
+ metaData[depth].tagStart = '';
+ metaData[depth].tagEnd = '';
+ }
+ else {
+ if (metaData[depth].tagEnd === '/key' && metaData[depth].tagContent) {
+ metaData[depth].key = metaData[depth].tagContent;
+ } else {
+ if (metaData[depth].tagEnd === '/real' && metaData[depth].tagContent) { metaData[depth].data = parseFloat(metaData[depth].tagContent) || 0; }
+ if (metaData[depth].tagEnd === '/integer' && metaData[depth].tagContent) { metaData[depth].data = parseInt(metaData[depth].tagContent) || 0; }
+ if (metaData[depth].tagEnd === '/string' && metaData[depth].tagContent) { metaData[depth].data = metaData[depth].tagContent || ''; }
+ if (metaData[depth].tagEnd === '/boolean') { metaData[depth].data = metaData[depth].tagContent || false; }
+ if (metaData[depth].tagEnd === '/arrayEmpty') { metaData[depth].data = metaData[depth].tagContent || []; }
+ if (depth > 0 && metaData[depth - 1].tagStart === 'array') { metaData[depth - 1].data.push(metaData[depth].data); }
+ if (depth > 0 && metaData[depth - 1].tagStart === 'dict') { metaData[depth - 1].data[metaData[depth].key] = metaData[depth].data; }
+ }
+ metaData[depth].tagContent = '';
+ metaData[depth].tagStart = '';
+ metaData[depth].tagEnd = '';
+ }
+ }
+ metaData[depth].tagEnd = '';
+ inTagStart = false;
+ inTagContent = false;
+ }
+ } else {
+ if (inTagStart) { metaData[depth].tagStart += c; }
+ if (inTagEnd) { metaData[depth].tagEnd += c; }
+ if (inTagContent) { metaData[depth].tagContent += c; }
+ }
+ pos++;
+ }
+ return metaData[0].data;
+}
+
+function semverCompare(v1, v2) {
+ let res = 0;
+ const parts1 = v1.split('.');
+ const parts2 = v2.split('.');
+ if (parts1[0] < parts2[0]) { res = 1; }
+ else if (parts1[0] > parts2[0]) { res = -1; }
+ else if (parts1[0] === parts2[0] && parts1.length >= 2 && parts2.length >= 2) {
+ if (parts1[1] < parts2[1]) { res = 1; }
+ else if (parts1[1] > parts2[1]) { res = -1; }
+ else if (parts1[1] === parts2[1]) {
+ if (parts1.length >= 3 && parts2.length >= 3) {
+ if (parts1[2] < parts2[2]) { res = 1; }
+ else if (parts1[2] > parts2[2]) { res = -1; }
+ } else if (parts2.length >= 3) {
+ res = 1;
+ }
+ }
+ }
+ return res;
+}
+
+function noop() { }
+
+exports.toInt = toInt;
+exports.execOptsWin = execOptsWin;
+exports.getCodepage = getCodepage;
+exports.execWin = execWin;
+exports.isFunction = isFunction;
+exports.unique = unique;
+exports.sortByKey = sortByKey;
+exports.cores = cores;
+exports.getValue = getValue;
+exports.decodeEscapeSequence = decodeEscapeSequence;
+exports.parseDateTime = parseDateTime;
+exports.parseHead = parseHead;
+exports.findObjectByKey = findObjectByKey;
+exports.getWmic = getWmic;
+exports.wmic = wmic;
+exports.darwinXcodeExists = darwinXcodeExists;
+exports.getVboxmanage = getVboxmanage;
+exports.powerShell = powerShell;
+exports.powerShellStart = powerShellStart;
+exports.powerShellRelease = powerShellRelease;
+exports.execSafe = execSafe;
+exports.nanoSeconds = nanoSeconds;
+exports.countUniqueLines = countUniqueLines;
+exports.countLines = countLines;
+exports.noop = noop;
+exports.isRaspberry = isRaspberry;
+exports.isRaspbian = isRaspbian;
+exports.sanitizeShellString = sanitizeShellString;
+exports.isPrototypePolluted = isPrototypePolluted;
+exports.decodePiCpuinfo = decodePiCpuinfo;
+exports.promiseAll = promiseAll;
+exports.promisify = promisify;
+exports.promisifySave = promisifySave;
+exports.smartMonToolsInstalled = smartMonToolsInstalled;
+exports.linuxVersion = linuxVersion;
+exports.plistParser = plistParser;
+exports.stringReplace = stringReplace;
+exports.stringToLower = stringToLower;
+exports.stringToString = stringToString;
+exports.stringSubstr = stringSubstr;
+exports.stringTrim = stringTrim;
+exports.stringStartWith = stringStartWith;
+exports.mathMin = mathMin;
+exports.WINDIR = WINDIR;
+exports.getFilesInPath = getFilesInPath;
+exports.semverCompare = semverCompare;
diff --git a/MistyCore/node_modules/systeminformation/lib/virtualbox.js b/MistyCore/node_modules/systeminformation/lib/virtualbox.js
new file mode 100644
index 0000000..61268b6
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/virtualbox.js
@@ -0,0 +1,107 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// virtualbox.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 14. Docker
+// ----------------------------------------------------------------------------------
+
+const os = require('os');
+const exec = require('child_process').exec;
+const util = require('./util');
+
+function vboxInfo(callback) {
+
+ // fallback - if only callback is given
+ let result = [];
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ try {
+ exec(util.getVboxmanage() + ' list vms --long', function (error, stdout) {
+ let parts = (os.EOL + stdout.toString()).split(os.EOL + 'Name:');
+ parts.shift();
+ parts.forEach(part => {
+ const lines = ('Name:' + part).split(os.EOL);
+ const state = util.getValue(lines, 'State');
+ const running = state.startsWith('running');
+ const runningSinceString = running ? state.replace('running (since ', '').replace(')', '').trim() : '';
+ let runningSince = 0;
+ try {
+ if (running) {
+ const sinceDateObj = new Date(runningSinceString);
+ const offset = sinceDateObj.getTimezoneOffset();
+ runningSince = Math.round((Date.now() - Date.parse(sinceDateObj)) / 1000) + offset * 60;
+ }
+ } catch (e) {
+ util.noop();
+ }
+ const stoppedSinceString = !running ? state.replace('powered off (since', '').replace(')', '').trim() : '';
+ let stoppedSince = 0;
+ try {
+ if (!running) {
+ const sinceDateObj = new Date(stoppedSinceString);
+ const offset = sinceDateObj.getTimezoneOffset();
+ stoppedSince = Math.round((Date.now() - Date.parse(sinceDateObj)) / 1000) + offset * 60;
+ }
+ } catch (e) {
+ util.noop();
+ }
+ result.push({
+ id: util.getValue(lines, 'UUID'),
+ name: util.getValue(lines, 'Name'),
+ running,
+ started: runningSinceString,
+ runningSince,
+ stopped: stoppedSinceString,
+ stoppedSince,
+ guestOS: util.getValue(lines, 'Guest OS'),
+ hardwareUUID: util.getValue(lines, 'Hardware UUID'),
+ memory: parseInt(util.getValue(lines, 'Memory size', ' '), 10),
+ vram: parseInt(util.getValue(lines, 'VRAM size'), 10),
+ cpus: parseInt(util.getValue(lines, 'Number of CPUs'), 10),
+ cpuExepCap: util.getValue(lines, 'CPU exec cap'),
+ cpuProfile: util.getValue(lines, 'CPUProfile'),
+ chipset: util.getValue(lines, 'Chipset'),
+ firmware: util.getValue(lines, 'Firmware'),
+ pageFusion: util.getValue(lines, 'Page Fusion') === 'enabled',
+ configFile: util.getValue(lines, 'Config file'),
+ snapshotFolder: util.getValue(lines, 'Snapshot folder'),
+ logFolder: util.getValue(lines, 'Log folder'),
+ hpet: util.getValue(lines, 'HPET') === 'enabled',
+ pae: util.getValue(lines, 'PAE') === 'enabled',
+ longMode: util.getValue(lines, 'Long Mode') === 'enabled',
+ tripleFaultReset: util.getValue(lines, 'Triple Fault Reset') === 'enabled',
+ apic: util.getValue(lines, 'APIC') === 'enabled',
+ x2Apic: util.getValue(lines, 'X2APIC') === 'enabled',
+ acpi: util.getValue(lines, 'ACPI') === 'enabled',
+ ioApic: util.getValue(lines, 'IOAPIC') === 'enabled',
+ biosApicMode: util.getValue(lines, 'BIOS APIC mode'),
+ bootMenuMode: util.getValue(lines, 'Boot menu mode'),
+ bootDevice1: util.getValue(lines, 'Boot Device 1'),
+ bootDevice2: util.getValue(lines, 'Boot Device 2'),
+ bootDevice3: util.getValue(lines, 'Boot Device 3'),
+ bootDevice4: util.getValue(lines, 'Boot Device 4'),
+ timeOffset: util.getValue(lines, 'Time offset'),
+ rtc: util.getValue(lines, 'RTC'),
+ });
+ });
+
+ if (callback) { callback(result); }
+ resolve(result);
+ });
+ } catch (e) {
+ if (callback) { callback(result); }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.vboxInfo = vboxInfo;
diff --git a/MistyCore/node_modules/systeminformation/lib/wifi.js b/MistyCore/node_modules/systeminformation/lib/wifi.js
new file mode 100644
index 0000000..d5e56cb
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/lib/wifi.js
@@ -0,0 +1,744 @@
+'use strict';
+// @ts-check
+// ==================================================================================
+// wifi.js
+// ----------------------------------------------------------------------------------
+// Description: System Information - library
+// for Node.js
+// Copyright: (c) 2014 - 2022
+// Author: Sebastian Hildebrandt
+// ----------------------------------------------------------------------------------
+// License: MIT
+// ==================================================================================
+// 9. wifi
+// ----------------------------------------------------------------------------------
+
+const os = require('os');
+const exec = require('child_process').exec;
+const execSync = require('child_process').execSync;
+const util = require('./util');
+
+let _platform = process.platform;
+
+const _linux = (_platform === 'linux' || _platform === 'android');
+const _darwin = (_platform === 'darwin');
+const _windows = (_platform === 'win32');
+
+function wifiDBFromQuality(quality) {
+ return (parseFloat(quality) / 2 - 100);
+}
+
+function wifiQualityFromDB(db) {
+ const result = 2 * (parseFloat(db) + 100);
+ return result <= 100 ? result : 100;
+}
+
+const _wifi_frequencies = {
+ 1: 2412,
+ 2: 2417,
+ 3: 2422,
+ 4: 2427,
+ 5: 2432,
+ 6: 2437,
+ 7: 2442,
+ 8: 2447,
+ 9: 2452,
+ 10: 2457,
+ 11: 2462,
+ 12: 2467,
+ 13: 2472,
+ 14: 2484,
+ 32: 5160,
+ 34: 5170,
+ 36: 5180,
+ 38: 5190,
+ 40: 5200,
+ 42: 5210,
+ 44: 5220,
+ 46: 5230,
+ 48: 5240,
+ 50: 5250,
+ 52: 5260,
+ 54: 5270,
+ 56: 5280,
+ 58: 5290,
+ 60: 5300,
+ 62: 5310,
+ 64: 5320,
+ 68: 5340,
+ 96: 5480,
+ 100: 5500,
+ 102: 5510,
+ 104: 5520,
+ 106: 5530,
+ 108: 5540,
+ 110: 5550,
+ 112: 5560,
+ 114: 5570,
+ 116: 5580,
+ 118: 5590,
+ 120: 5600,
+ 122: 5610,
+ 124: 5620,
+ 126: 5630,
+ 128: 5640,
+ 132: 5660,
+ 134: 5670,
+ 136: 5680,
+ 138: 5690,
+ 140: 5700,
+ 142: 5710,
+ 144: 5720,
+ 149: 5745,
+ 151: 5755,
+ 153: 5765,
+ 155: 5775,
+ 157: 5785,
+ 159: 5795,
+ 161: 5805,
+ 165: 5825,
+ 169: 5845,
+ 173: 5865,
+ 183: 4915,
+ 184: 4920,
+ 185: 4925,
+ 187: 4935,
+ 188: 4940,
+ 189: 4945,
+ 192: 4960,
+ 196: 4980
+};
+
+function wifiFrequencyFromChannel(channel) {
+ return {}.hasOwnProperty.call(_wifi_frequencies, channel) ? _wifi_frequencies[channel] : null;
+}
+
+function wifiChannelFromFrequencs(frequency) {
+ let channel = 0;
+ for (let key in _wifi_frequencies) {
+ if ({}.hasOwnProperty.call(_wifi_frequencies, key)) {
+ if (_wifi_frequencies[key] === frequency) { channel = util.toInt(key); }
+ }
+ }
+ return channel;
+}
+
+function ifaceListLinux() {
+ const result = [];
+ const cmd = 'iw dev 2>/dev/null';
+ try {
+ const all = execSync(cmd).toString().split('\n').map(line => line.trim()).join('\n');
+ const parts = all.split('\nInterface ');
+ parts.shift();
+ parts.forEach(ifaceDetails => {
+ const lines = ifaceDetails.split('\n');
+ const iface = lines[0];
+ const id = util.toInt(util.getValue(lines, 'ifindex', ' '));
+ const mac = util.getValue(lines, 'addr', ' ');
+ const channel = util.toInt(util.getValue(lines, 'channel', ' '));
+ result.push({
+ id,
+ iface,
+ mac,
+ channel
+ });
+ });
+ return result;
+ } catch (e) {
+ try {
+ const all = execSync('nmcli -t -f general,wifi-properties,wired-properties,interface-flags,capabilities,nsp device show 2>/dev/null').toString();
+ const parts = all.split('\nGENERAL.DEVICE:');
+ let i = 1;
+ parts.forEach(ifaceDetails => {
+ const lines = ifaceDetails.split('\n');
+ const iface = util.getValue(lines, 'GENERAL.DEVICE');
+ const type = util.getValue(lines, 'GENERAL.TYPE');
+ const id = i++; // // util.getValue(lines, 'GENERAL.PATH');
+ const mac = util.getValue(lines, 'GENERAL.HWADDR');
+ const channel = '';
+ if (type.toLowerCase() === 'wifi') {
+ result.push({
+ id,
+ iface,
+ mac,
+ channel
+ });
+ }
+ });
+ return result;
+ } catch (e) {
+ return [];
+ }
+ }
+}
+
+function nmiDeviceLinux(iface) {
+ const cmd = `nmcli -t -f general,wifi-properties,capabilities,ip4,ip6 device show ${iface} 2>/dev/null`;
+ try {
+ const lines = execSync(cmd).toString().split('\n');
+ const ssid = util.getValue(lines, 'GENERAL.CONNECTION');
+ return {
+ iface,
+ type: util.getValue(lines, 'GENERAL.TYPE'),
+ vendor: util.getValue(lines, 'GENERAL.VENDOR'),
+ product: util.getValue(lines, 'GENERAL.PRODUCT'),
+ mac: util.getValue(lines, 'GENERAL.HWADDR').toLowerCase(),
+ ssid: ssid !== '--' ? ssid : null
+ };
+ } catch (e) {
+ return {};
+ }
+}
+
+function nmiConnectionLinux(ssid) {
+ const cmd = `nmcli -t --show-secrets connection show ${ssid} 2>/dev/null`;
+ try {
+ const lines = execSync(cmd).toString().split('\n');
+ const bssid = util.getValue(lines, '802-11-wireless.seen-bssids').toLowerCase();
+ return {
+ ssid: ssid !== '--' ? ssid : null,
+ uuid: util.getValue(lines, 'connection.uuid'),
+ type: util.getValue(lines, 'connection.type'),
+ autoconnect: util.getValue(lines, 'connection.autoconnect') === 'yes',
+ security: util.getValue(lines, '802-11-wireless-security.key-mgmt'),
+ bssid: bssid !== '--' ? bssid : null
+ };
+ } catch (e) {
+ return {};
+ }
+}
+
+function wpaConnectionLinux(iface) {
+ const cmd = `wpa_cli -i ${iface} status 2>&1`;
+ try {
+ const lines = execSync(cmd).toString().split('\n');
+ const freq = util.toInt(util.getValue(lines, 'freq', '='));
+ return {
+ ssid: util.getValue(lines, 'ssid', '='),
+ uuid: util.getValue(lines, 'uuid', '='),
+ security: util.getValue(lines, 'key_mgmt', '='),
+ freq,
+ channel: wifiChannelFromFrequencs(freq),
+ bssid: util.getValue(lines, 'bssid', '=').toLowerCase()
+ };
+ } catch (e) {
+ return {};
+ }
+}
+
+function getWifiNetworkListNmi() {
+ const result = [];
+ const cmd = 'nmcli -t -m multiline --fields active,ssid,bssid,mode,chan,freq,signal,security,wpa-flags,rsn-flags device wifi list 2>/dev/null';
+ try {
+ const stdout = execSync(cmd, { maxBuffer: 1024 * 20000 });
+ const parts = stdout.toString().split('ACTIVE:');
+ parts.shift();
+ parts.forEach(part => {
+ part = 'ACTIVE:' + part;
+ const lines = part.split(os.EOL);
+ const channel = util.getValue(lines, 'CHAN');
+ const frequency = util.getValue(lines, 'FREQ').toLowerCase().replace('mhz', '').trim();
+ const security = util.getValue(lines, 'SECURITY').replace('(', '').replace(')', '');
+ const wpaFlags = util.getValue(lines, 'WPA-FLAGS').replace('(', '').replace(')', '');
+ const rsnFlags = util.getValue(lines, 'RSN-FLAGS').replace('(', '').replace(')', '');
+ result.push({
+ ssid: util.getValue(lines, 'SSID'),
+ bssid: util.getValue(lines, 'BSSID').toLowerCase(),
+ mode: util.getValue(lines, 'MODE'),
+ channel: channel ? parseInt(channel, 10) : null,
+ frequency: frequency ? parseInt(frequency, 10) : null,
+ signalLevel: wifiDBFromQuality(util.getValue(lines, 'SIGNAL')),
+ quality: parseFloat(util.getValue(lines, 'SIGNAL')),
+ security: security && security !== 'none' ? security.split(' ') : [],
+ wpaFlags: wpaFlags && wpaFlags !== 'none' ? wpaFlags.split(' ') : [],
+ rsnFlags: rsnFlags && rsnFlags !== 'none' ? rsnFlags.split(' ') : []
+ });
+ });
+ return result;
+ } catch (e) {
+ return [];
+ }
+}
+
+function getWifiNetworkListIw(iface) {
+ const result = [];
+ try {
+ let iwlistParts = execSync(`export LC_ALL=C; iwlist ${iface} scan 2>&1; unset LC_ALL`).toString().split(' Cell ');
+ if (iwlistParts[0].indexOf('resource busy') >= 0) { return -1; }
+ if (iwlistParts.length > 1) {
+ iwlistParts.shift();
+ iwlistParts.forEach(element => {
+ const lines = element.split('\n');
+ const channel = util.getValue(lines, 'channel', ':', true);
+ const address = (lines && lines.length && lines[0].indexOf('Address:') >= 0 ? lines[0].split('Address:')[1].trim().toLowerCase() : '');
+ const mode = util.getValue(lines, 'mode', ':', true);
+ const frequency = util.getValue(lines, 'frequency', ':', true);
+ const qualityString = util.getValue(lines, 'Quality', '=', true);
+ const dbParts = qualityString.toLowerCase().split('signal level=');
+ const db = dbParts.length > 1 ? util.toInt(dbParts[1]) : 0;
+ const quality = db ? wifiQualityFromDB(db) : 0;
+ const ssid = util.getValue(lines, 'essid', ':', true);
+
+ // security and wpa-flags
+ const isWpa = element.indexOf(' WPA ') >= 0;
+ const isWpa2 = element.indexOf('WPA2 ') >= 0;
+ const security = [];
+ if (isWpa) { security.push('WPA'); }
+ if (isWpa2) { security.push('WPA2'); }
+ const wpaFlags = [];
+ let wpaFlag = '';
+ lines.forEach(function (line) {
+ const l = line.trim().toLowerCase();
+ if (l.indexOf('group cipher') >= 0) {
+ if (wpaFlag) {
+ wpaFlags.push(wpaFlag);
+ }
+ const parts = l.split(':');
+ if (parts.length > 1) {
+ wpaFlag = parts[1].trim().toUpperCase();
+ }
+ }
+ if (l.indexOf('pairwise cipher') >= 0) {
+ const parts = l.split(':');
+ if (parts.length > 1) {
+ if (parts[1].indexOf('tkip')) { wpaFlag = (wpaFlag ? 'TKIP/' + wpaFlag : 'TKIP'); }
+ else if (parts[1].indexOf('ccmp')) { wpaFlag = (wpaFlag ? 'CCMP/' + wpaFlag : 'CCMP'); }
+ else if (parts[1].indexOf('proprietary')) { wpaFlag = (wpaFlag ? 'PROP/' + wpaFlag : 'PROP'); }
+ }
+ }
+ if (l.indexOf('authentication suites') >= 0) {
+ const parts = l.split(':');
+ if (parts.length > 1) {
+ if (parts[1].indexOf('802.1x')) { wpaFlag = (wpaFlag ? '802.1x/' + wpaFlag : '802.1x'); }
+ else if (parts[1].indexOf('psk')) { wpaFlag = (wpaFlag ? 'PSK/' + wpaFlag : 'PSK'); }
+ }
+ }
+ });
+ if (wpaFlag) {
+ wpaFlags.push(wpaFlag);
+ }
+
+ result.push({
+ ssid,
+ bssid: address,
+ mode,
+ channel: channel ? util.toInt(channel) : null,
+ frequency: frequency ? util.toInt(frequency.replace('.', '')) : null,
+ signalLevel: db,
+ quality,
+ security,
+ wpaFlags,
+ rsnFlags: []
+ });
+ });
+ }
+ return result;
+ } catch (e) {
+ return -1;
+ }
+}
+
+function parseWifiDarwin(wifiObj) {
+ const result = [];
+ if (wifiObj) {
+ wifiObj.forEach(function (wifiItem) {
+ const signalLevel = wifiItem.RSSI;
+ let security = [];
+ let wpaFlags = [];
+ if (wifiItem.WPA_IE) {
+ security.push('WPA');
+ if (wifiItem.WPA_IE.IE_KEY_WPA_UCIPHERS) {
+ wifiItem.WPA_IE.IE_KEY_WPA_UCIPHERS.forEach(function (ciphers) {
+ if (ciphers === 0 && wpaFlags.indexOf('unknown/TKIP') === -1) { wpaFlags.push('unknown/TKIP'); }
+ if (ciphers === 2 && wpaFlags.indexOf('PSK/TKIP') === -1) { wpaFlags.push('PSK/TKIP'); }
+ if (ciphers === 4 && wpaFlags.indexOf('PSK/AES') === -1) { wpaFlags.push('PSK/AES'); }
+ });
+ }
+ }
+ if (wifiItem.RSN_IE) {
+ security.push('WPA2');
+ if (wifiItem.RSN_IE.IE_KEY_RSN_UCIPHERS) {
+ wifiItem.RSN_IE.IE_KEY_RSN_UCIPHERS.forEach(function (ciphers) {
+ if (ciphers === 0 && wpaFlags.indexOf('unknown/TKIP') === -1) { wpaFlags.push('unknown/TKIP'); }
+ if (ciphers === 2 && wpaFlags.indexOf('TKIP/TKIP') === -1) { wpaFlags.push('TKIP/TKIP'); }
+ if (ciphers === 4 && wpaFlags.indexOf('PSK/AES') === -1) { wpaFlags.push('PSK/AES'); }
+ });
+ }
+ }
+ result.push({
+ ssid: wifiItem.SSID_STR,
+ bssid: wifiItem.BSSID,
+ mode: '',
+ channel: wifiItem.CHANNEL,
+ frequency: wifiFrequencyFromChannel(wifiItem.CHANNEL),
+ signalLevel: signalLevel ? parseInt(signalLevel, 10) : null,
+ quality: wifiQualityFromDB(signalLevel),
+ security,
+ wpaFlags,
+ rsnFlags: []
+ });
+ });
+ }
+ return result;
+}
+function wifiNetworks(callback) {
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = [];
+ if (_linux) {
+ result = getWifiNetworkListNmi();
+ if (result.length === 0) {
+ try {
+ const iwconfigParts = execSync('export LC_ALL=C; iwconfig 2>/dev/null; unset LC_ALL').toString().split('\n\n');
+ let iface = '';
+ iwconfigParts.forEach(element => {
+ if (element.indexOf('no wireless') === -1 && element.trim() !== '') {
+ iface = element.split(' ')[0];
+ }
+ });
+ if (iface) {
+ const res = getWifiNetworkListIw(iface);
+ if (res === -1) {
+ // try again after 4 secs
+ setTimeout(function (iface) {
+ const res = getWifiNetworkListIw(iface);
+ if (res != -1) { result = res; }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }, 4000);
+ } else {
+ result = res;
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ } catch (e) {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ } else if (_darwin) {
+ let cmd = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s -x';
+ exec(cmd, { maxBuffer: 1024 * 40000 }, function (error, stdout) {
+ const output = stdout.toString();
+ result = parseWifiDarwin(util.plistParser(output));
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else if (_windows) {
+ let cmd = 'netsh wlan show networks mode=Bssid';
+ util.powerShell(cmd).then((stdout) => {
+ const ssidParts = stdout.toString('utf8').split(os.EOL + os.EOL + 'SSID ');
+ ssidParts.shift();
+
+ ssidParts.forEach(ssidPart => {
+ const ssidLines = ssidPart.split(os.EOL);
+ if (ssidLines && ssidLines.length >= 8 && ssidLines[0].indexOf(':') >= 0) {
+ const bssidsParts = ssidPart.split(' BSSID');
+ bssidsParts.shift();
+
+ bssidsParts.forEach((bssidPart) => {
+ const bssidLines = bssidPart.split(os.EOL);
+ const bssidLine = bssidLines[0].split(':');
+ bssidLine.shift();
+ const bssid = bssidLine.join(':').trim().toLowerCase();
+ const channel = bssidLines[3].split(':').pop().trim();
+ const quality = bssidLines[1].split(':').pop().trim();
+
+ result.push({
+ ssid: ssidLines[0].split(':').pop().trim(),
+ bssid,
+ mode: '',
+ channel: channel ? parseInt(channel, 10) : null,
+ frequency: wifiFrequencyFromChannel(channel),
+ signalLevel: wifiDBFromQuality(quality),
+ quality: quality ? parseInt(quality, 10) : null,
+ security: [ssidLines[2].split(':').pop().trim()],
+ wpaFlags: [ssidLines[3].split(':').pop().trim()],
+ rsnFlags: []
+ });
+ });
+ }
+ });
+
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.wifiNetworks = wifiNetworks;
+
+function getVendor(model) {
+ model = model.toLowerCase();
+ let result = '';
+ if (model.indexOf('intel') >= 0) { result = 'Intel'; }
+ else if (model.indexOf('realtek') >= 0) { result = 'Realtek'; }
+ else if (model.indexOf('qualcom') >= 0) { result = 'Qualcom'; }
+ else if (model.indexOf('broadcom') >= 0) { result = 'Broadcom'; }
+ else if (model.indexOf('cavium') >= 0) { result = 'Cavium'; }
+ else if (model.indexOf('cisco') >= 0) { result = 'Cisco'; }
+ else if (model.indexOf('marvel') >= 0) { result = 'Marvel'; }
+ else if (model.indexOf('zyxel') >= 0) { result = 'Zyxel'; }
+ else if (model.indexOf('melanox') >= 0) { result = 'Melanox'; }
+ else if (model.indexOf('d-link') >= 0) { result = 'D-Link'; }
+ else if (model.indexOf('tp-link') >= 0) { result = 'TP-Link'; }
+ else if (model.indexOf('asus') >= 0) { result = 'Asus'; }
+ else if (model.indexOf('linksys') >= 0) { result = 'Linksys'; }
+ return result;
+}
+
+function wifiConnections(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ const result = [];
+
+ if (_linux) {
+ const ifaces = ifaceListLinux();
+ const networkList = getWifiNetworkListNmi();
+ ifaces.forEach(ifaceDetail => {
+ const nmiDetails = nmiDeviceLinux(ifaceDetail.iface);
+ const wpaDetails = wpaConnectionLinux(ifaceDetail.iface);
+ const ssid = nmiDetails.ssid || wpaDetails.ssid;
+ const network = networkList.filter(nw => nw.ssid === ssid);
+ const nmiConnection = nmiConnectionLinux(ssid);
+ const channel = network && network.length && network[0].channel ? network[0].channel : (wpaDetails.channel ? wpaDetails.channel : null);
+ const bssid = network && network.length && network[0].bssid ? network[0].bssid : (wpaDetails.bssid ? wpaDetails.bssid : null);
+ if (ssid && bssid) {
+ result.push({
+ id: ifaceDetail.id,
+ iface: ifaceDetail.iface,
+ model: nmiDetails.product,
+ ssid,
+ bssid: network && network.length && network[0].bssid ? network[0].bssid : (wpaDetails.bssid ? wpaDetails.bssid : null),
+ channel,
+ frequency: channel ? wifiFrequencyFromChannel(channel) : null,
+ type: nmiConnection.type ? nmiConnection.type : '802.11',
+ security: nmiConnection.security ? nmiConnection.security : (wpaDetails.security ? wpaDetails.security : null),
+ signalLevel: network && network.length && network[0].signalLevel ? network[0].signalLevel : null,
+ txRate: null
+ });
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else if (_darwin) {
+ let cmd = 'system_profiler SPNetworkDataType';
+ exec(cmd, function (error, stdout) {
+ const parts1 = stdout.toString().split('\n\n Wi-Fi:\n\n');
+ if (parts1.length > 1) {
+ const lines = parts1[1].split('\n\n')[0].split('\n');
+ const iface = util.getValue(lines, 'BSD Device Name', ':', true);
+ const model = util.getValue(lines, 'hardware', ':', true);
+ cmd = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I';
+ exec(cmd, function (error, stdout) {
+ const lines2 = stdout.toString().split('\n');
+ if (lines.length > 10) {
+ const ssid = util.getValue(lines2, 'ssid', ':', true);
+ const bssid = util.getValue(lines2, 'bssid', ':', true);
+ const security = util.getValue(lines2, 'link auth', ':', true);
+ const txRate = util.getValue(lines2, 'lastTxRate', ':', true);
+ const channel = util.getValue(lines2, 'channel', ':', true).split(',')[0];
+ const type = '802.11';
+ const rssi = util.toInt(util.getValue(lines2, 'agrCtlRSSI', ':', true));
+ const noise = util.toInt(util.getValue(lines2, 'agrCtlNoise', ':', true));
+ const signalLevel = rssi - noise;
+ if (ssid || bssid) {
+ result.push({
+ id: 'Wi-Fi',
+ iface,
+ model,
+ ssid,
+ bssid,
+ channel: util.toInt(channel),
+ frequency: channel ? wifiFrequencyFromChannel(channel) : null,
+ type,
+ security,
+ signalLevel,
+ txRate
+ });
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ });
+ } else if (_windows) {
+ let cmd = 'netsh wlan show interfaces';
+ util.powerShell(cmd).then(function (stdout) {
+ const allLines = stdout.toString().split('\r\n');
+ for (let i = 0; i < allLines.length; i++) {
+ allLines[i] = allLines[i].trim();
+ }
+ const parts = allLines.join('\r\n').split(':\r\n\r\n');
+ parts.shift();
+ parts.forEach(part => {
+ const lines = part.split('\r\n');
+ if (lines.length >= 5) {
+ const iface = lines[0].indexOf(':') >= 0 ? lines[0].split(':')[1].trim() : '';
+ const model = lines[1].indexOf(':') >= 0 ? lines[1].split(':')[1].trim() : '';
+ const id = lines[2].indexOf(':') >= 0 ? lines[2].split(':')[1].trim() : '';
+ const ssid = util.getValue(lines, 'SSID', ':', true);
+ const bssid = util.getValue(lines, 'BSSID', ':', true);
+ const signalLevel = util.getValue(lines, 'Signal', ':', true);
+ const type = util.getValue(lines, 'Radio type', ':', true) || util.getValue(lines, 'Type de radio', ':', true) || util.getValue(lines, 'Funktyp', ':', true) || null;
+ const security = util.getValue(lines, 'authentication', ':', true) || util.getValue(lines, 'Authentification', ':', true) || util.getValue(lines, 'Authentifizierung', ':', true) || null;
+ const channel = util.getValue(lines, 'Channel', ':', true) || util.getValue(lines, 'Canal', ':', true) || util.getValue(lines, 'Kanal', ':', true) || null;
+ const txRate = util.getValue(lines, 'Transmit rate (mbps)', ':', true) || util.getValue(lines, 'Transmission (mbit/s)', ':', true) || util.getValue(lines, 'Empfangsrate (MBit/s)', ':', true) || null;
+ if (model && id && ssid && bssid) {
+ result.push({
+ id,
+ iface,
+ model,
+ ssid,
+ bssid,
+ channel: util.toInt(channel),
+ frequency: channel ? wifiFrequencyFromChannel(channel) : null,
+ type,
+ security,
+ signalLevel,
+ txRate: util.toInt(txRate) || null
+ });
+ }
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.wifiConnections = wifiConnections;
+
+function wifiInterfaces(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ const result = [];
+
+ if (_linux) {
+ const ifaces = ifaceListLinux();
+ ifaces.forEach(ifaceDetail => {
+ const nmiDetails = nmiDeviceLinux(ifaceDetail.iface);
+ result.push({
+ id: ifaceDetail.id,
+ iface: ifaceDetail.iface,
+ model: nmiDetails.product ? nmiDetails.product : null,
+ vendor: nmiDetails.vendor ? nmiDetails.vendor : null,
+ mac: ifaceDetail.mac,
+ });
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else if (_darwin) {
+ let cmd = 'system_profiler SPNetworkDataType';
+ exec(cmd, function (error, stdout) {
+ const parts1 = stdout.toString().split('\n\n Wi-Fi:\n\n');
+ if (parts1.length > 1) {
+ const lines = parts1[1].split('\n\n')[0].split('\n');
+ const iface = util.getValue(lines, 'BSD Device Name', ':', true);
+ const mac = util.getValue(lines, 'MAC Address', ':', true);
+ const model = util.getValue(lines, 'hardware', ':', true);
+ result.push({
+ id: 'Wi-Fi',
+ iface,
+ model,
+ vendor: '',
+ mac
+ });
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else if (_windows) {
+ let cmd = 'netsh wlan show interfaces';
+ util.powerShell(cmd).then(function (stdout) {
+ const allLines = stdout.toString().split('\r\n');
+ for (let i = 0; i < allLines.length; i++) {
+ allLines[i] = allLines[i].trim();
+ }
+ const parts = allLines.join('\r\n').split(':\r\n\r\n');
+ parts.shift();
+ parts.forEach(part => {
+ const lines = part.split('\r\n');
+ if (lines.length >= 5) {
+ const iface = lines[0].indexOf(':') >= 0 ? lines[0].split(':')[1].trim() : '';
+ const model = lines[1].indexOf(':') >= 0 ? lines[1].split(':')[1].trim() : '';
+ const id = lines[2].indexOf(':') >= 0 ? lines[2].split(':')[1].trim() : '';
+ const macParts = lines[3].indexOf(':') >= 0 ? lines[3].split(':') : [];
+ macParts.shift();
+ const mac = macParts.join(':').trim();
+ const vendor = getVendor(model);
+ if (iface && model && id && mac) {
+ result.push({
+ id,
+ iface,
+ model,
+ vendor,
+ mac,
+ });
+ }
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.wifiInterfaces = wifiInterfaces;
diff --git a/MistyCore/node_modules/systeminformation/package.json b/MistyCore/node_modules/systeminformation/package.json
new file mode 100644
index 0000000..8017da4
--- /dev/null
+++ b/MistyCore/node_modules/systeminformation/package.json
@@ -0,0 +1,99 @@
+{
+ "name": "systeminformation",
+ "version": "5.12.11",
+ "description": "Advanced, lightweight system and OS information library",
+ "license": "MIT",
+ "author": "Sebastian Hildebrandt <hildebrandt@plus-innovations.com> (https://plus-innovations.com)",
+ "homepage": "https://systeminformation.io",
+ "main": "./lib/index.js",
+ "bin": {
+ "systeminformation": "lib/cli.js"
+ },
+ "types": "./lib/index.d.ts",
+ "scripts": {
+ "test": "node ./test/test.js"
+ },
+ "files": [
+ "lib/"
+ ],
+ "keywords": [
+ "system information",
+ "sysinfo",
+ "monitor",
+ "monitoring",
+ "os",
+ "linux",
+ "osx",
+ "windows",
+ "freebsd",
+ "openbsd",
+ "netbsd",
+ "cpu",
+ "cpuload",
+ "physical cores",
+ "logical cores",
+ "processor",
+ "cores",
+ "threads",
+ "socket type",
+ "memory",
+ "file system",
+ "fsstats",
+ "diskio",
+ "block devices",
+ "netstats",
+ "network",
+ "network interfaces",
+ "network connections",
+ "network stats",
+ "iface",
+ "printer",
+ "processes",
+ "users",
+ "internet",
+ "battery",
+ "docker",
+ "docker stats",
+ "docker processes",
+ "graphics",
+ "graphic card",
+ "graphic controller",
+ "gpu",
+ "display",
+ "smart",
+ "disk layout",
+ "usb",
+ "audio",
+ "bluetooth",
+ "wifi",
+ "wifinetworks",
+ "virtual box",
+ "virtualbox",
+ "vm",
+ "backend",
+ "hardware",
+ "BIOS",
+ "chassis"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/sebhildebrandt/systeminformation.git"
+ },
+ "funding": {
+ "type": "Buy me a coffee",
+ "url": "https://www.buymeacoffee.com/systeminfo"
+ },
+ "os": [
+ "darwin",
+ "linux",
+ "win32",
+ "freebsd",
+ "openbsd",
+ "netbsd",
+ "sunos",
+ "android"
+ ],
+ "engines": {
+ "node": ">=8.0.0"
+ }
+}
diff --git a/MistyCore/node_modules/yallist/LICENSE b/MistyCore/node_modules/yallist/LICENSE
new file mode 100644
index 0000000..19129e3
--- /dev/null
+++ b/MistyCore/node_modules/yallist/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/MistyCore/node_modules/yallist/README.md b/MistyCore/node_modules/yallist/README.md
new file mode 100644
index 0000000..f586101
--- /dev/null
+++ b/MistyCore/node_modules/yallist/README.md
@@ -0,0 +1,204 @@
+# yallist
+
+Yet Another Linked List
+
+There are many doubly-linked list implementations like it, but this
+one is mine.
+
+For when an array would be too big, and a Map can't be iterated in
+reverse order.
+
+
+[![Build Status](https://travis-ci.org/isaacs/yallist.svg?branch=master)](https://travis-ci.org/isaacs/yallist) [![Coverage Status](https://coveralls.io/repos/isaacs/yallist/badge.svg?service=github)](https://coveralls.io/github/isaacs/yallist)
+
+## basic usage
+
+```javascript
+var yallist = require('yallist')
+var myList = yallist.create([1, 2, 3])
+myList.push('foo')
+myList.unshift('bar')
+// of course pop() and shift() are there, too
+console.log(myList.toArray()) // ['bar', 1, 2, 3, 'foo']
+myList.forEach(function (k) {
+ // walk the list head to tail
+})
+myList.forEachReverse(function (k, index, list) {
+ // walk the list tail to head
+})
+var myDoubledList = myList.map(function (k) {
+ return k + k
+})
+// now myDoubledList contains ['barbar', 2, 4, 6, 'foofoo']
+// mapReverse is also a thing
+var myDoubledListReverse = myList.mapReverse(function (k) {
+ return k + k
+}) // ['foofoo', 6, 4, 2, 'barbar']
+
+var reduced = myList.reduce(function (set, entry) {
+ set += entry
+ return set
+}, 'start')
+console.log(reduced) // 'startfoo123bar'
+```
+
+## api
+
+The whole API is considered "public".
+
+Functions with the same name as an Array method work more or less the
+same way.
+
+There's reverse versions of most things because that's the point.
+
+### Yallist
+
+Default export, the class that holds and manages a list.
+
+Call it with either a forEach-able (like an array) or a set of
+arguments, to initialize the list.
+
+The Array-ish methods all act like you'd expect. No magic length,
+though, so if you change that it won't automatically prune or add
+empty spots.
+
+### Yallist.create(..)
+
+Alias for Yallist function. Some people like factories.
+
+#### yallist.head
+
+The first node in the list
+
+#### yallist.tail
+
+The last node in the list
+
+#### yallist.length
+
+The number of nodes in the list. (Change this at your peril. It is
+not magic like Array length.)
+
+#### yallist.toArray()
+
+Convert the list to an array.
+
+#### yallist.forEach(fn, [thisp])
+
+Call a function on each item in the list.
+
+#### yallist.forEachReverse(fn, [thisp])
+
+Call a function on each item in the list, in reverse order.
+
+#### yallist.get(n)
+
+Get the data at position `n` in the list. If you use this a lot,
+probably better off just using an Array.
+
+#### yallist.getReverse(n)
+
+Get the data at position `n`, counting from the tail.
+
+#### yallist.map(fn, thisp)
+
+Create a new Yallist with the result of calling the function on each
+item.
+
+#### yallist.mapReverse(fn, thisp)
+
+Same as `map`, but in reverse.
+
+#### yallist.pop()
+
+Get the data from the list tail, and remove the tail from the list.
+
+#### yallist.push(item, ...)
+
+Insert one or more items to the tail of the list.
+
+#### yallist.reduce(fn, initialValue)
+
+Like Array.reduce.
+
+#### yallist.reduceReverse
+
+Like Array.reduce, but in reverse.
+
+#### yallist.reverse
+
+Reverse the list in place.
+
+#### yallist.shift()
+
+Get the data from the list head, and remove the head from the list.
+
+#### yallist.slice([from], [to])
+
+Just like Array.slice, but returns a new Yallist.
+
+#### yallist.sliceReverse([from], [to])
+
+Just like yallist.slice, but the result is returned in reverse.
+
+#### yallist.toArray()
+
+Create an array representation of the list.
+
+#### yallist.toArrayReverse()
+
+Create a reversed array representation of the list.
+
+#### yallist.unshift(item, ...)
+
+Insert one or more items to the head of the list.
+
+#### yallist.unshiftNode(node)
+
+Move a Node object to the front of the list. (That is, pull it out of
+wherever it lives, and make it the new head.)
+
+If the node belongs to a different list, then that list will remove it
+first.
+
+#### yallist.pushNode(node)
+
+Move a Node object to the end of the list. (That is, pull it out of
+wherever it lives, and make it the new tail.)
+
+If the node belongs to a list already, then that list will remove it
+first.
+
+#### yallist.removeNode(node)
+
+Remove a node from the list, preserving referential integrity of head
+and tail and other nodes.
+
+Will throw an error if you try to have a list remove a node that
+doesn't belong to it.
+
+### Yallist.Node
+
+The class that holds the data and is actually the list.
+
+Call with `var n = new Node(value, previousNode, nextNode)`
+
+Note that if you do direct operations on Nodes themselves, it's very
+easy to get into weird states where the list is broken. Be careful :)
+
+#### node.next
+
+The next node in the list.
+
+#### node.prev
+
+The previous node in the list.
+
+#### node.value
+
+The data the node contains.
+
+#### node.list
+
+The list to which this node belongs. (Null if it does not belong to
+any list.)
diff --git a/MistyCore/node_modules/yallist/iterator.js b/MistyCore/node_modules/yallist/iterator.js
new file mode 100644
index 0000000..d41c97a
--- /dev/null
+++ b/MistyCore/node_modules/yallist/iterator.js
@@ -0,0 +1,8 @@
+'use strict'
+module.exports = function (Yallist) {
+ Yallist.prototype[Symbol.iterator] = function* () {
+ for (let walker = this.head; walker; walker = walker.next) {
+ yield walker.value
+ }
+ }
+}
diff --git a/MistyCore/node_modules/yallist/package.json b/MistyCore/node_modules/yallist/package.json
new file mode 100644
index 0000000..8a08386
--- /dev/null
+++ b/MistyCore/node_modules/yallist/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "yallist",
+ "version": "4.0.0",
+ "description": "Yet Another Linked List",
+ "main": "yallist.js",
+ "directories": {
+ "test": "test"
+ },
+ "files": [
+ "yallist.js",
+ "iterator.js"
+ ],
+ "dependencies": {},
+ "devDependencies": {
+ "tap": "^12.1.0"
+ },
+ "scripts": {
+ "test": "tap test/*.js --100",
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "postpublish": "git push origin --all; git push origin --tags"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/isaacs/yallist.git"
+ },
+ "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
+ "license": "ISC"
+}
diff --git a/MistyCore/node_modules/yallist/yallist.js b/MistyCore/node_modules/yallist/yallist.js
new file mode 100644
index 0000000..4e83ab1
--- /dev/null
+++ b/MistyCore/node_modules/yallist/yallist.js
@@ -0,0 +1,426 @@
+'use strict'
+module.exports = Yallist
+
+Yallist.Node = Node
+Yallist.create = Yallist
+
+function Yallist (list) {
+ var self = this
+ if (!(self instanceof Yallist)) {
+ self = new Yallist()
+ }
+
+ self.tail = null
+ self.head = null
+ self.length = 0
+
+ if (list && typeof list.forEach === 'function') {
+ list.forEach(function (item) {
+ self.push(item)
+ })
+ } else if (arguments.length > 0) {
+ for (var i = 0, l = arguments.length; i < l; i++) {
+ self.push(arguments[i])
+ }
+ }
+
+ return self
+}
+
+Yallist.prototype.removeNode = function (node) {
+ if (node.list !== this) {
+ throw new Error('removing node which does not belong to this list')
+ }
+
+ var next = node.next
+ var prev = node.prev
+
+ if (next) {
+ next.prev = prev
+ }
+
+ if (prev) {
+ prev.next = next
+ }
+
+ if (node === this.head) {
+ this.head = next
+ }
+ if (node === this.tail) {
+ this.tail = prev
+ }
+
+ node.list.length--
+ node.next = null
+ node.prev = null
+ node.list = null
+
+ return next
+}
+
+Yallist.prototype.unshiftNode = function (node) {
+ if (node === this.head) {
+ return
+ }
+
+ if (node.list) {
+ node.list.removeNode(node)
+ }
+
+ var head = this.head
+ node.list = this
+ node.next = head
+ if (head) {
+ head.prev = node
+ }
+
+ this.head = node
+ if (!this.tail) {
+ this.tail = node
+ }
+ this.length++
+}
+
+Yallist.prototype.pushNode = function (node) {
+ if (node === this.tail) {
+ return
+ }
+
+ if (node.list) {
+ node.list.removeNode(node)
+ }
+
+ var tail = this.tail
+ node.list = this
+ node.prev = tail
+ if (tail) {
+ tail.next = node
+ }
+
+ this.tail = node
+ if (!this.head) {
+ this.head = node
+ }
+ this.length++
+}
+
+Yallist.prototype.push = function () {
+ for (var i = 0, l = arguments.length; i < l; i++) {
+ push(this, arguments[i])
+ }
+ return this.length
+}
+
+Yallist.prototype.unshift = function () {
+ for (var i = 0, l = arguments.length; i < l; i++) {
+ unshift(this, arguments[i])
+ }
+ return this.length
+}
+
+Yallist.prototype.pop = function () {
+ if (!this.tail) {
+ return undefined
+ }
+
+ var res = this.tail.value
+ this.tail = this.tail.prev
+ if (this.tail) {
+ this.tail.next = null
+ } else {
+ this.head = null
+ }
+ this.length--
+ return res
+}
+
+Yallist.prototype.shift = function () {
+ if (!this.head) {
+ return undefined
+ }
+
+ var res = this.head.value
+ this.head = this.head.next
+ if (this.head) {
+ this.head.prev = null
+ } else {
+ this.tail = null
+ }
+ this.length--
+ return res
+}
+
+Yallist.prototype.forEach = function (fn, thisp) {
+ thisp = thisp || this
+ for (var walker = this.head, i = 0; walker !== null; i++) {
+ fn.call(thisp, walker.value, i, this)
+ walker = walker.next
+ }
+}
+
+Yallist.prototype.forEachReverse = function (fn, thisp) {
+ thisp = thisp || this
+ for (var walker = this.tail, i = this.length - 1; walker !== null; i--) {
+ fn.call(thisp, walker.value, i, this)
+ walker = walker.prev
+ }
+}
+
+Yallist.prototype.get = function (n) {
+ for (var i = 0, walker = this.head; walker !== null && i < n; i++) {
+ // abort out of the list early if we hit a cycle
+ walker = walker.next
+ }
+ if (i === n && walker !== null) {
+ return walker.value
+ }
+}
+
+Yallist.prototype.getReverse = function (n) {
+ for (var i = 0, walker = this.tail; walker !== null && i < n; i++) {
+ // abort out of the list early if we hit a cycle
+ walker = walker.prev
+ }
+ if (i === n && walker !== null) {
+ return walker.value
+ }
+}
+
+Yallist.prototype.map = function (fn, thisp) {
+ thisp = thisp || this
+ var res = new Yallist()
+ for (var walker = this.head; walker !== null;) {
+ res.push(fn.call(thisp, walker.value, this))
+ walker = walker.next
+ }
+ return res
+}
+
+Yallist.prototype.mapReverse = function (fn, thisp) {
+ thisp = thisp || this
+ var res = new Yallist()
+ for (var walker = this.tail; walker !== null;) {
+ res.push(fn.call(thisp, walker.value, this))
+ walker = walker.prev
+ }
+ return res
+}
+
+Yallist.prototype.reduce = function (fn, initial) {
+ var acc
+ var walker = this.head
+ if (arguments.length > 1) {
+ acc = initial
+ } else if (this.head) {
+ walker = this.head.next
+ acc = this.head.value
+ } else {
+ throw new TypeError('Reduce of empty list with no initial value')
+ }
+
+ for (var i = 0; walker !== null; i++) {
+ acc = fn(acc, walker.value, i)
+ walker = walker.next
+ }
+
+ return acc
+}
+
+Yallist.prototype.reduceReverse = function (fn, initial) {
+ var acc
+ var walker = this.tail
+ if (arguments.length > 1) {
+ acc = initial
+ } else if (this.tail) {
+ walker = this.tail.prev
+ acc = this.tail.value
+ } else {
+ throw new TypeError('Reduce of empty list with no initial value')
+ }
+
+ for (var i = this.length - 1; walker !== null; i--) {
+ acc = fn(acc, walker.value, i)
+ walker = walker.prev
+ }
+
+ return acc
+}
+
+Yallist.prototype.toArray = function () {
+ var arr = new Array(this.length)
+ for (var i = 0, walker = this.head; walker !== null; i++) {
+ arr[i] = walker.value
+ walker = walker.next
+ }
+ return arr
+}
+
+Yallist.prototype.toArrayReverse = function () {
+ var arr = new Array(this.length)
+ for (var i = 0, walker = this.tail; walker !== null; i++) {
+ arr[i] = walker.value
+ walker = walker.prev
+ }
+ return arr
+}
+
+Yallist.prototype.slice = function (from, to) {
+ to = to || this.length
+ if (to < 0) {
+ to += this.length
+ }
+ from = from || 0
+ if (from < 0) {
+ from += this.length
+ }
+ var ret = new Yallist()
+ if (to < from || to < 0) {
+ return ret
+ }
+ if (from < 0) {
+ from = 0
+ }
+ if (to > this.length) {
+ to = this.length
+ }
+ for (var i = 0, walker = this.head; walker !== null && i < from; i++) {
+ walker = walker.next
+ }
+ for (; walker !== null && i < to; i++, walker = walker.next) {
+ ret.push(walker.value)
+ }
+ return ret
+}
+
+Yallist.prototype.sliceReverse = function (from, to) {
+ to = to || this.length
+ if (to < 0) {
+ to += this.length
+ }
+ from = from || 0
+ if (from < 0) {
+ from += this.length
+ }
+ var ret = new Yallist()
+ if (to < from || to < 0) {
+ return ret
+ }
+ if (from < 0) {
+ from = 0
+ }
+ if (to > this.length) {
+ to = this.length
+ }
+ for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) {
+ walker = walker.prev
+ }
+ for (; walker !== null && i > from; i--, walker = walker.prev) {
+ ret.push(walker.value)
+ }
+ return ret
+}
+
+Yallist.prototype.splice = function (start, deleteCount, ...nodes) {
+ if (start > this.length) {
+ start = this.length - 1
+ }
+ if (start < 0) {
+ start = this.length + start;
+ }
+
+ for (var i = 0, walker = this.head; walker !== null && i < start; i++) {
+ walker = walker.next
+ }
+
+ var ret = []
+ for (var i = 0; walker && i < deleteCount; i++) {
+ ret.push(walker.value)
+ walker = this.removeNode(walker)
+ }
+ if (walker === null) {
+ walker = this.tail
+ }
+
+ if (walker !== this.head && walker !== this.tail) {
+ walker = walker.prev
+ }
+
+ for (var i = 0; i < nodes.length; i++) {
+ walker = insert(this, walker, nodes[i])
+ }
+ return ret;
+}
+
+Yallist.prototype.reverse = function () {
+ var head = this.head
+ var tail = this.tail
+ for (var walker = head; walker !== null; walker = walker.prev) {
+ var p = walker.prev
+ walker.prev = walker.next
+ walker.next = p
+ }
+ this.head = tail
+ this.tail = head
+ return this
+}
+
+function insert (self, node, value) {
+ var inserted = node === self.head ?
+ new Node(value, null, node, self) :
+ new Node(value, node, node.next, self)
+
+ if (inserted.next === null) {
+ self.tail = inserted
+ }
+ if (inserted.prev === null) {
+ self.head = inserted
+ }
+
+ self.length++
+
+ return inserted
+}
+
+function push (self, item) {
+ self.tail = new Node(item, self.tail, null, self)
+ if (!self.head) {
+ self.head = self.tail
+ }
+ self.length++
+}
+
+function unshift (self, item) {
+ self.head = new Node(item, null, self.head, self)
+ if (!self.tail) {
+ self.tail = self.head
+ }
+ self.length++
+}
+
+function Node (value, prev, next, list) {
+ if (!(this instanceof Node)) {
+ return new Node(value, prev, next, list)
+ }
+
+ this.list = list
+ this.value = value
+
+ if (prev) {
+ prev.next = this
+ this.prev = prev
+ } else {
+ this.prev = null
+ }
+
+ if (next) {
+ next.prev = this
+ this.next = next
+ } else {
+ this.next = null
+ }
+}
+
+try {
+ // add if support for Symbol.iterator is present
+ require('./iterator.js')(Yallist)
+} catch (er) {}
diff --git a/MistyCore/node_modules/yaml/LICENSE b/MistyCore/node_modules/yaml/LICENSE
new file mode 100644
index 0000000..e060aaa
--- /dev/null
+++ b/MistyCore/node_modules/yaml/LICENSE
@@ -0,0 +1,13 @@
+Copyright Eemeli Aro <eemeli@gmail.com>
+
+Permission to use, copy, modify, and/or distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright notice
+and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
diff --git a/MistyCore/node_modules/yaml/README.md b/MistyCore/node_modules/yaml/README.md
new file mode 100644
index 0000000..3af1473
--- /dev/null
+++ b/MistyCore/node_modules/yaml/README.md
@@ -0,0 +1,143 @@
+# YAML <a href="https://www.npmjs.com/package/yaml"><img align="right" src="https://badge.fury.io/js/yaml.svg" title="npm package" /></a>
+
+`yaml` is a definitive library for [YAML](https://yaml.org/), the human friendly data serialization standard.
+This library:
+
+- Supports both YAML 1.1 and YAML 1.2 and all common data schemas,
+- Passes all of the [yaml-test-suite](https://github.com/yaml/yaml-test-suite) tests,
+- Can accept any string as input without throwing, parsing as much YAML out of it as it can, and
+- Supports parsing, modifying, and writing YAML comments and blank lines.
+
+The library is released under the ISC open source license, and the code is [available on GitHub](https://github.com/eemeli/yaml/).
+It has no external dependencies and runs on Node.js as well as modern browsers.
+
+For the purposes of versioning, any changes that break any of the documented endpoints or APIs will be considered semver-major breaking changes.
+Undocumented library internals may change between minor versions, and previous APIs may be deprecated (but not removed).
+
+For more information, see the project's documentation site: [**eemeli.org/yaml**](https://eemeli.org/yaml/)
+
+To install:
+
+```sh
+npm install yaml
+```
+
+**Note:** These docs are for `yaml@2`. For v1, see the [v1.10.0 tag](https://github.com/eemeli/yaml/tree/v1.10.0) for the source and [eemeli.org/yaml/v1](https://eemeli.org/yaml/v1/) for the documentation.
+
+## API Overview
+
+The API provided by `yaml` has three layers, depending on how deep you need to go: [Parse & Stringify](https://eemeli.org/yaml/#parse-amp-stringify), [Documents](https://eemeli.org/yaml/#documents), and the underlying [Lexer/Parser/Composer](https://eemeli.org/yaml/#parsing-yaml).
+The first has the simplest API and "just works", the second gets you all the bells and whistles supported by the library along with a decent [AST](https://eemeli.org/yaml/#content-nodes), and the third lets you get progressively closer to YAML source, if that's your thing.
+
+```js
+import { parse, stringify } from 'yaml'
+// or
+import YAML from 'yaml'
+// or
+const YAML = require('yaml')
+```
+
+### Parse & Stringify
+
+- [`parse(str, reviver?, options?): value`](https://eemeli.org/yaml/#yaml-parse)
+- [`stringify(value, replacer?, options?): string`](https://eemeli.org/yaml/#yaml-stringify)
+
+### Documents
+
+- [`Document`](https://eemeli.org/yaml/#documents)
+ - [`constructor(value, replacer?, options?)`](https://eemeli.org/yaml/#creating-documents)
+ - [`#anchors`](https://eemeli.org/yaml/#working-with-anchors)
+ - [`#contents`](https://eemeli.org/yaml/#content-nodes)
+ - [`#directives`](https://eemeli.org/yaml/#stream-directives)
+ - [`#errors`](https://eemeli.org/yaml/#errors)
+ - [`#warnings`](https://eemeli.org/yaml/#errors)
+- [`isDocument(foo): boolean`](https://eemeli.org/yaml/#identifying-nodes)
+- [`parseAllDocuments(str, options?): Document[]`](https://eemeli.org/yaml/#parsing-documents)
+- [`parseDocument(str, options?): Document`](https://eemeli.org/yaml/#parsing-documents)
+
+### Content Nodes
+
+- [`isAlias(foo): boolean`](https://eemeli.org/yaml/#identifying-nodes)
+- [`isCollection(foo): boolean`](https://eemeli.org/yaml/#identifying-nodes)
+- [`isMap(foo): boolean`](https://eemeli.org/yaml/#identifying-nodes)
+- [`isNode(foo): boolean`](https://eemeli.org/yaml/#identifying-nodes)
+- [`isPair(foo): boolean`](https://eemeli.org/yaml/#identifying-nodes)
+- [`isScalar(foo): boolean`](https://eemeli.org/yaml/#identifying-nodes)
+- [`isSeq(foo): boolean`](https://eemeli.org/yaml/#identifying-nodes)
+- [`new Scalar(value)`](https://eemeli.org/yaml/#scalar-values)
+- [`new YAMLMap()`](https://eemeli.org/yaml/#collections)
+- [`new YAMLSeq()`](https://eemeli.org/yaml/#collections)
+- [`doc.createAlias(node, name?): Alias`](https://eemeli.org/yaml/#working-with-anchors)
+- [`doc.createNode(value, options?): Node`](https://eemeli.org/yaml/#creating-nodes)
+- [`doc.createPair(key, value): Pair`](https://eemeli.org/yaml/#creating-nodes)
+- [`visit(node, visitor)`](https://eemeli.org/yaml/#modifying-nodes)
+
+### Parsing YAML
+
+- [`new Lexer().lex(src)`](https://eemeli.org/yaml/#lexer)
+- [`new Parser(onNewLine?).parse(src)`](https://eemeli.org/yaml/#parser)
+- [`new Composer(options?).compose(tokens)`](https://eemeli.org/yaml/#composer)
+
+## YAML.parse
+
+```yaml
+# file.yml
+YAML:
+ - A human-readable data serialization language
+ - https://en.wikipedia.org/wiki/YAML
+yaml:
+ - A complete JavaScript implementation
+ - https://www.npmjs.com/package/yaml
+```
+
+```js
+import fs from 'fs'
+import YAML from 'yaml'
+
+YAML.parse('3.14159')
+// 3.14159
+
+YAML.parse('[ true, false, maybe, null ]\n')
+// [ true, false, 'maybe', null ]
+
+const file = fs.readFileSync('./file.yml', 'utf8')
+YAML.parse(file)
+// { YAML:
+// [ 'A human-readable data serialization language',
+// 'https://en.wikipedia.org/wiki/YAML' ],
+// yaml:
+// [ 'A complete JavaScript implementation',
+// 'https://www.npmjs.com/package/yaml' ] }
+```
+
+## YAML.stringify
+
+```js
+import YAML from 'yaml'
+
+YAML.stringify(3.14159)
+// '3.14159\n'
+
+YAML.stringify([true, false, 'maybe', null])
+// `- true
+// - false
+// - maybe
+// - null
+// `
+
+YAML.stringify({ number: 3, plain: 'string', block: 'two\nlines\n' })
+// `number: 3
+// plain: string
+// block: |
+// two
+// lines
+// `
+```
+
+---
+
+Browser testing provided by:
+
+<a href="https://www.browserstack.com/open-source">
+<img width=200 src="https://eemeli.org/yaml/images/browserstack.svg" />
+</a>
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/compose-collection.js b/MistyCore/node_modules/yaml/browser/dist/compose/compose-collection.js
new file mode 100644
index 0000000..44910e5
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/compose-collection.js
@@ -0,0 +1,59 @@
+import { isNode, isMap } from '../nodes/Node.js';
+import { Scalar } from '../nodes/Scalar.js';
+import { resolveBlockMap } from './resolve-block-map.js';
+import { resolveBlockSeq } from './resolve-block-seq.js';
+import { resolveFlowCollection } from './resolve-flow-collection.js';
+
+function composeCollection(CN, ctx, token, tagToken, onError) {
+ let coll;
+ switch (token.type) {
+ case 'block-map': {
+ coll = resolveBlockMap(CN, ctx, token, onError);
+ break;
+ }
+ case 'block-seq': {
+ coll = resolveBlockSeq(CN, ctx, token, onError);
+ break;
+ }
+ case 'flow-collection': {
+ coll = resolveFlowCollection(CN, ctx, token, onError);
+ break;
+ }
+ }
+ if (!tagToken)
+ return coll;
+ const tagName = ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg));
+ if (!tagName)
+ return coll;
+ // Cast needed due to: https://github.com/Microsoft/TypeScript/issues/3841
+ const Coll = coll.constructor;
+ if (tagName === '!' || tagName === Coll.tagName) {
+ coll.tag = Coll.tagName;
+ return coll;
+ }
+ const expType = isMap(coll) ? 'map' : 'seq';
+ let tag = ctx.schema.tags.find(t => t.collection === expType && t.tag === tagName);
+ if (!tag) {
+ const kt = ctx.schema.knownTags[tagName];
+ if (kt && kt.collection === expType) {
+ ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
+ tag = kt;
+ }
+ else {
+ onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, true);
+ coll.tag = tagName;
+ return coll;
+ }
+ }
+ const res = tag.resolve(coll, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg), ctx.options);
+ const node = isNode(res)
+ ? res
+ : new Scalar(res);
+ node.range = coll.range;
+ node.tag = tagName;
+ if (tag?.format)
+ node.format = tag.format;
+ return node;
+}
+
+export { composeCollection };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/compose-doc.js b/MistyCore/node_modules/yaml/browser/dist/compose/compose-doc.js
new file mode 100644
index 0000000..e973c8a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/compose-doc.js
@@ -0,0 +1,40 @@
+import { Document } from '../doc/Document.js';
+import { composeNode, composeEmptyNode } from './compose-node.js';
+import { resolveEnd } from './resolve-end.js';
+import { resolveProps } from './resolve-props.js';
+
+function composeDoc(options, directives, { offset, start, value, end }, onError) {
+ const opts = Object.assign({ _directives: directives }, options);
+ const doc = new Document(undefined, opts);
+ const ctx = {
+ atRoot: true,
+ directives: doc.directives,
+ options: doc.options,
+ schema: doc.schema
+ };
+ const props = resolveProps(start, {
+ indicator: 'doc-start',
+ next: value ?? end?.[0],
+ offset,
+ onError,
+ startOnNewline: true
+ });
+ if (props.found) {
+ doc.directives.docStart = true;
+ if (value &&
+ (value.type === 'block-map' || value.type === 'block-seq') &&
+ !props.hasNewline)
+ onError(props.end, 'MISSING_CHAR', 'Block collection cannot start on same line with directives-end marker');
+ }
+ doc.contents = value
+ ? composeNode(ctx, value, props, onError)
+ : composeEmptyNode(ctx, props.end, start, null, props, onError);
+ const contentEnd = doc.contents.range[2];
+ const re = resolveEnd(end, contentEnd, false, onError);
+ if (re.comment)
+ doc.comment = re.comment;
+ doc.range = [offset, contentEnd, re.offset];
+ return doc;
+}
+
+export { composeDoc };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/compose-node.js b/MistyCore/node_modules/yaml/browser/dist/compose/compose-node.js
new file mode 100644
index 0000000..39d98e3
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/compose-node.js
@@ -0,0 +1,92 @@
+import { Alias } from '../nodes/Alias.js';
+import { composeCollection } from './compose-collection.js';
+import { composeScalar } from './compose-scalar.js';
+import { resolveEnd } from './resolve-end.js';
+import { emptyScalarPosition } from './util-empty-scalar-position.js';
+
+const CN = { composeNode, composeEmptyNode };
+function composeNode(ctx, token, props, onError) {
+ const { spaceBefore, comment, anchor, tag } = props;
+ let node;
+ let isSrcToken = true;
+ switch (token.type) {
+ case 'alias':
+ node = composeAlias(ctx, token, onError);
+ if (anchor || tag)
+ onError(token, 'ALIAS_PROPS', 'An alias node must not specify any properties');
+ break;
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ case 'block-scalar':
+ node = composeScalar(ctx, token, tag, onError);
+ if (anchor)
+ node.anchor = anchor.source.substring(1);
+ break;
+ case 'block-map':
+ case 'block-seq':
+ case 'flow-collection':
+ node = composeCollection(CN, ctx, token, tag, onError);
+ if (anchor)
+ node.anchor = anchor.source.substring(1);
+ break;
+ default: {
+ const message = token.type === 'error'
+ ? token.message
+ : `Unsupported token (type: ${token.type})`;
+ onError(token, 'UNEXPECTED_TOKEN', message);
+ node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
+ isSrcToken = false;
+ }
+ }
+ if (anchor && node.anchor === '')
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
+ if (spaceBefore)
+ node.spaceBefore = true;
+ if (comment) {
+ if (token.type === 'scalar' && token.source === '')
+ node.comment = comment;
+ else
+ node.commentBefore = comment;
+ }
+ // @ts-expect-error Type checking misses meaning of isSrcToken
+ if (ctx.options.keepSourceTokens && isSrcToken)
+ node.srcToken = token;
+ return node;
+}
+function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor, tag, end }, onError) {
+ const token = {
+ type: 'scalar',
+ offset: emptyScalarPosition(offset, before, pos),
+ indent: -1,
+ source: ''
+ };
+ const node = composeScalar(ctx, token, tag, onError);
+ if (anchor) {
+ node.anchor = anchor.source.substring(1);
+ if (node.anchor === '')
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
+ }
+ if (spaceBefore)
+ node.spaceBefore = true;
+ if (comment) {
+ node.comment = comment;
+ node.range[2] = end;
+ }
+ return node;
+}
+function composeAlias({ options }, { offset, source, end }, onError) {
+ const alias = new Alias(source.substring(1));
+ if (alias.source === '')
+ onError(offset, 'BAD_ALIAS', 'Alias cannot be an empty string');
+ if (alias.source.endsWith(':'))
+ onError(offset + source.length - 1, 'BAD_ALIAS', 'Alias ending in : is ambiguous', true);
+ const valueEnd = offset + source.length;
+ const re = resolveEnd(end, valueEnd, options.strict, onError);
+ alias.range = [offset, valueEnd, re.offset];
+ if (re.comment)
+ alias.comment = re.comment;
+ return alias;
+}
+
+export { composeEmptyNode, composeNode };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/compose-scalar.js b/MistyCore/node_modules/yaml/browser/dist/compose/compose-scalar.js
new file mode 100644
index 0000000..f2bd343
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/compose-scalar.js
@@ -0,0 +1,80 @@
+import { SCALAR, isScalar } from '../nodes/Node.js';
+import { Scalar } from '../nodes/Scalar.js';
+import { resolveBlockScalar } from './resolve-block-scalar.js';
+import { resolveFlowScalar } from './resolve-flow-scalar.js';
+
+function composeScalar(ctx, token, tagToken, onError) {
+ const { value, type, comment, range } = token.type === 'block-scalar'
+ ? resolveBlockScalar(token, ctx.options.strict, onError)
+ : resolveFlowScalar(token, ctx.options.strict, onError);
+ const tagName = tagToken
+ ? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg))
+ : null;
+ const tag = tagToken && tagName
+ ? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError)
+ : token.type === 'scalar'
+ ? findScalarTagByTest(ctx, value, token, onError)
+ : ctx.schema[SCALAR];
+ let scalar;
+ try {
+ const res = tag.resolve(value, msg => onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg), ctx.options);
+ scalar = isScalar(res) ? res : new Scalar(res);
+ }
+ catch (error) {
+ const msg = error instanceof Error ? error.message : String(error);
+ onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg);
+ scalar = new Scalar(value);
+ }
+ scalar.range = range;
+ scalar.source = value;
+ if (type)
+ scalar.type = type;
+ if (tagName)
+ scalar.tag = tagName;
+ if (tag.format)
+ scalar.format = tag.format;
+ if (comment)
+ scalar.comment = comment;
+ return scalar;
+}
+function findScalarTagByName(schema, value, tagName, tagToken, onError) {
+ if (tagName === '!')
+ return schema[SCALAR]; // non-specific tag
+ const matchWithTest = [];
+ for (const tag of schema.tags) {
+ if (!tag.collection && tag.tag === tagName) {
+ if (tag.default && tag.test)
+ matchWithTest.push(tag);
+ else
+ return tag;
+ }
+ }
+ for (const tag of matchWithTest)
+ if (tag.test?.test(value))
+ return tag;
+ const kt = schema.knownTags[tagName];
+ if (kt && !kt.collection) {
+ // Ensure that the known tag is available for stringifying,
+ // but does not get used by default.
+ schema.tags.push(Object.assign({}, kt, { default: false, test: undefined }));
+ return kt;
+ }
+ onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str');
+ return schema[SCALAR];
+}
+function findScalarTagByTest({ directives, schema }, value, token, onError) {
+ const tag = schema.tags.find(tag => tag.default && tag.test?.test(value)) || schema[SCALAR];
+ if (schema.compat) {
+ const compat = schema.compat.find(tag => tag.default && tag.test?.test(value)) ??
+ schema[SCALAR];
+ if (tag.tag !== compat.tag) {
+ const ts = directives.tagString(tag.tag);
+ const cs = directives.tagString(compat.tag);
+ const msg = `Value may be parsed as either ${ts} or ${cs}`;
+ onError(token, 'TAG_RESOLVE_FAILED', msg, true);
+ }
+ }
+ return tag;
+}
+
+export { composeScalar };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/composer.js b/MistyCore/node_modules/yaml/browser/dist/compose/composer.js
new file mode 100644
index 0000000..8f76855
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/composer.js
@@ -0,0 +1,217 @@
+import { Directives } from '../doc/directives.js';
+import { Document } from '../doc/Document.js';
+import { YAMLWarning, YAMLParseError } from '../errors.js';
+import { isCollection, isPair } from '../nodes/Node.js';
+import { composeDoc } from './compose-doc.js';
+import { resolveEnd } from './resolve-end.js';
+
+function getErrorPos(src) {
+ if (typeof src === 'number')
+ return [src, src + 1];
+ if (Array.isArray(src))
+ return src.length === 2 ? src : [src[0], src[1]];
+ const { offset, source } = src;
+ return [offset, offset + (typeof source === 'string' ? source.length : 1)];
+}
+function parsePrelude(prelude) {
+ let comment = '';
+ let atComment = false;
+ let afterEmptyLine = false;
+ for (let i = 0; i < prelude.length; ++i) {
+ const source = prelude[i];
+ switch (source[0]) {
+ case '#':
+ comment +=
+ (comment === '' ? '' : afterEmptyLine ? '\n\n' : '\n') +
+ (source.substring(1) || ' ');
+ atComment = true;
+ afterEmptyLine = false;
+ break;
+ case '%':
+ if (prelude[i + 1]?.[0] !== '#')
+ i += 1;
+ atComment = false;
+ break;
+ default:
+ // This may be wrong after doc-end, but in that case it doesn't matter
+ if (!atComment)
+ afterEmptyLine = true;
+ atComment = false;
+ }
+ }
+ return { comment, afterEmptyLine };
+}
+/**
+ * Compose a stream of CST nodes into a stream of YAML Documents.
+ *
+ * ```ts
+ * import { Composer, Parser } from 'yaml'
+ *
+ * const src: string = ...
+ * const tokens = new Parser().parse(src)
+ * const docs = new Composer().compose(tokens)
+ * ```
+ */
+class Composer {
+ constructor(options = {}) {
+ this.doc = null;
+ this.atDirectives = false;
+ this.prelude = [];
+ this.errors = [];
+ this.warnings = [];
+ this.onError = (source, code, message, warning) => {
+ const pos = getErrorPos(source);
+ if (warning)
+ this.warnings.push(new YAMLWarning(pos, code, message));
+ else
+ this.errors.push(new YAMLParseError(pos, code, message));
+ };
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ this.directives = new Directives({ version: options.version || '1.2' });
+ this.options = options;
+ }
+ decorate(doc, afterDoc) {
+ const { comment, afterEmptyLine } = parsePrelude(this.prelude);
+ //console.log({ dc: doc.comment, prelude, comment })
+ if (comment) {
+ const dc = doc.contents;
+ if (afterDoc) {
+ doc.comment = doc.comment ? `${doc.comment}\n${comment}` : comment;
+ }
+ else if (afterEmptyLine || doc.directives.docStart || !dc) {
+ doc.commentBefore = comment;
+ }
+ else if (isCollection(dc) && !dc.flow && dc.items.length > 0) {
+ let it = dc.items[0];
+ if (isPair(it))
+ it = it.key;
+ const cb = it.commentBefore;
+ it.commentBefore = cb ? `${comment}\n${cb}` : comment;
+ }
+ else {
+ const cb = dc.commentBefore;
+ dc.commentBefore = cb ? `${comment}\n${cb}` : comment;
+ }
+ }
+ if (afterDoc) {
+ Array.prototype.push.apply(doc.errors, this.errors);
+ Array.prototype.push.apply(doc.warnings, this.warnings);
+ }
+ else {
+ doc.errors = this.errors;
+ doc.warnings = this.warnings;
+ }
+ this.prelude = [];
+ this.errors = [];
+ this.warnings = [];
+ }
+ /**
+ * Current stream status information.
+ *
+ * Mostly useful at the end of input for an empty stream.
+ */
+ streamInfo() {
+ return {
+ comment: parsePrelude(this.prelude).comment,
+ directives: this.directives,
+ errors: this.errors,
+ warnings: this.warnings
+ };
+ }
+ /**
+ * Compose tokens into documents.
+ *
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
+ */
+ *compose(tokens, forceDoc = false, endOffset = -1) {
+ for (const token of tokens)
+ yield* this.next(token);
+ yield* this.end(forceDoc, endOffset);
+ }
+ /** Advance the composer by one CST token. */
+ *next(token) {
+ switch (token.type) {
+ case 'directive':
+ this.directives.add(token.source, (offset, message, warning) => {
+ const pos = getErrorPos(token);
+ pos[0] += offset;
+ this.onError(pos, 'BAD_DIRECTIVE', message, warning);
+ });
+ this.prelude.push(token.source);
+ this.atDirectives = true;
+ break;
+ case 'document': {
+ const doc = composeDoc(this.options, this.directives, token, this.onError);
+ if (this.atDirectives && !doc.directives.docStart)
+ this.onError(token, 'MISSING_CHAR', 'Missing directives-end/doc-start indicator line');
+ this.decorate(doc, false);
+ if (this.doc)
+ yield this.doc;
+ this.doc = doc;
+ this.atDirectives = false;
+ break;
+ }
+ case 'byte-order-mark':
+ case 'space':
+ break;
+ case 'comment':
+ case 'newline':
+ this.prelude.push(token.source);
+ break;
+ case 'error': {
+ const msg = token.source
+ ? `${token.message}: ${JSON.stringify(token.source)}`
+ : token.message;
+ const error = new YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', msg);
+ if (this.atDirectives || !this.doc)
+ this.errors.push(error);
+ else
+ this.doc.errors.push(error);
+ break;
+ }
+ case 'doc-end': {
+ if (!this.doc) {
+ const msg = 'Unexpected doc-end without preceding document';
+ this.errors.push(new YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', msg));
+ break;
+ }
+ this.doc.directives.docEnd = true;
+ const end = resolveEnd(token.end, token.offset + token.source.length, this.doc.options.strict, this.onError);
+ this.decorate(this.doc, true);
+ if (end.comment) {
+ const dc = this.doc.comment;
+ this.doc.comment = dc ? `${dc}\n${end.comment}` : end.comment;
+ }
+ this.doc.range[2] = end.offset;
+ break;
+ }
+ default:
+ this.errors.push(new YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', `Unsupported token ${token.type}`));
+ }
+ }
+ /**
+ * Call at end of input to yield any remaining document.
+ *
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
+ */
+ *end(forceDoc = false, endOffset = -1) {
+ if (this.doc) {
+ this.decorate(this.doc, true);
+ yield this.doc;
+ this.doc = null;
+ }
+ else if (forceDoc) {
+ const opts = Object.assign({ _directives: this.directives }, this.options);
+ const doc = new Document(undefined, opts);
+ if (this.atDirectives)
+ this.onError(endOffset, 'MISSING_CHAR', 'Missing directives-end indicator line');
+ doc.range = [0, endOffset, endOffset];
+ this.decorate(doc, false);
+ yield doc;
+ }
+ }
+}
+
+export { Composer };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-map.js b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-map.js
new file mode 100644
index 0000000..5ab1671
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-map.js
@@ -0,0 +1,110 @@
+import { Pair } from '../nodes/Pair.js';
+import { YAMLMap } from '../nodes/YAMLMap.js';
+import { resolveProps } from './resolve-props.js';
+import { containsNewline } from './util-contains-newline.js';
+import { flowIndentCheck } from './util-flow-indent-check.js';
+import { mapIncludes } from './util-map-includes.js';
+
+const startColMsg = 'All mapping items must start at the same column';
+function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError) {
+ const map = new YAMLMap(ctx.schema);
+ if (ctx.atRoot)
+ ctx.atRoot = false;
+ let offset = bm.offset;
+ let commentEnd = null;
+ for (const collItem of bm.items) {
+ const { start, key, sep, value } = collItem;
+ // key properties
+ const keyProps = resolveProps(start, {
+ indicator: 'explicit-key-ind',
+ next: key ?? sep?.[0],
+ offset,
+ onError,
+ startOnNewline: true
+ });
+ const implicitKey = !keyProps.found;
+ if (implicitKey) {
+ if (key) {
+ if (key.type === 'block-seq')
+ onError(offset, 'BLOCK_AS_IMPLICIT_KEY', 'A block sequence may not be used as an implicit map key');
+ else if ('indent' in key && key.indent !== bm.indent)
+ onError(offset, 'BAD_INDENT', startColMsg);
+ }
+ if (!keyProps.anchor && !keyProps.tag && !sep) {
+ commentEnd = keyProps.end;
+ if (keyProps.comment) {
+ if (map.comment)
+ map.comment += '\n' + keyProps.comment;
+ else
+ map.comment = keyProps.comment;
+ }
+ continue;
+ }
+ if (keyProps.hasNewlineAfterProp || containsNewline(key)) {
+ onError(key ?? start[start.length - 1], 'MULTILINE_IMPLICIT_KEY', 'Implicit keys need to be on a single line');
+ }
+ }
+ else if (keyProps.found?.indent !== bm.indent) {
+ onError(offset, 'BAD_INDENT', startColMsg);
+ }
+ // key value
+ const keyStart = keyProps.end;
+ const keyNode = key
+ ? composeNode(ctx, key, keyProps, onError)
+ : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
+ if (ctx.schema.compat)
+ flowIndentCheck(bm.indent, key, onError);
+ if (mapIncludes(ctx, map.items, keyNode))
+ onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');
+ // value properties
+ const valueProps = resolveProps(sep ?? [], {
+ indicator: 'map-value-ind',
+ next: value,
+ offset: keyNode.range[2],
+ onError,
+ startOnNewline: !key || key.type === 'block-scalar'
+ });
+ offset = valueProps.end;
+ if (valueProps.found) {
+ if (implicitKey) {
+ if (value?.type === 'block-map' && !valueProps.hasNewline)
+ onError(offset, 'BLOCK_AS_IMPLICIT_KEY', 'Nested mappings are not allowed in compact mappings');
+ if (ctx.options.strict &&
+ keyProps.start < valueProps.found.offset - 1024)
+ onError(keyNode.range, 'KEY_OVER_1024_CHARS', 'The : indicator must be at most 1024 chars after the start of an implicit block mapping key');
+ }
+ // value value
+ const valueNode = value
+ ? composeNode(ctx, value, valueProps, onError)
+ : composeEmptyNode(ctx, offset, sep, null, valueProps, onError);
+ if (ctx.schema.compat)
+ flowIndentCheck(bm.indent, value, onError);
+ offset = valueNode.range[2];
+ const pair = new Pair(keyNode, valueNode);
+ if (ctx.options.keepSourceTokens)
+ pair.srcToken = collItem;
+ map.items.push(pair);
+ }
+ else {
+ // key with no value
+ if (implicitKey)
+ onError(keyNode.range, 'MISSING_CHAR', 'Implicit map keys need to be followed by map values');
+ if (valueProps.comment) {
+ if (keyNode.comment)
+ keyNode.comment += '\n' + valueProps.comment;
+ else
+ keyNode.comment = valueProps.comment;
+ }
+ const pair = new Pair(keyNode);
+ if (ctx.options.keepSourceTokens)
+ pair.srcToken = collItem;
+ map.items.push(pair);
+ }
+ }
+ if (commentEnd && commentEnd < offset)
+ onError(commentEnd, 'IMPOSSIBLE', 'Map comment with trailing content');
+ map.range = [bm.offset, offset, commentEnd ?? offset];
+ return map;
+}
+
+export { resolveBlockMap };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js
new file mode 100644
index 0000000..592d807
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js
@@ -0,0 +1,194 @@
+import { Scalar } from '../nodes/Scalar.js';
+
+function resolveBlockScalar(scalar, strict, onError) {
+ const start = scalar.offset;
+ const header = parseBlockScalarHeader(scalar, strict, onError);
+ if (!header)
+ return { value: '', type: null, comment: '', range: [start, start, start] };
+ const type = header.mode === '>' ? Scalar.BLOCK_FOLDED : Scalar.BLOCK_LITERAL;
+ const lines = scalar.source ? splitLines(scalar.source) : [];
+ // determine the end of content & start of chomping
+ let chompStart = lines.length;
+ for (let i = lines.length - 1; i >= 0; --i) {
+ const content = lines[i][1];
+ if (content === '' || content === '\r')
+ chompStart = i;
+ else
+ break;
+ }
+ // shortcut for empty contents
+ if (chompStart === 0) {
+ const value = header.chomp === '+' && lines.length > 0
+ ? '\n'.repeat(Math.max(1, lines.length - 1))
+ : '';
+ let end = start + header.length;
+ if (scalar.source)
+ end += scalar.source.length;
+ return { value, type, comment: header.comment, range: [start, end, end] };
+ }
+ // find the indentation level to trim from start
+ let trimIndent = scalar.indent + header.indent;
+ let offset = scalar.offset + header.length;
+ let contentStart = 0;
+ for (let i = 0; i < chompStart; ++i) {
+ const [indent, content] = lines[i];
+ if (content === '' || content === '\r') {
+ if (header.indent === 0 && indent.length > trimIndent)
+ trimIndent = indent.length;
+ }
+ else {
+ if (indent.length < trimIndent) {
+ const message = 'Block scalars with more-indented leading empty lines must use an explicit indentation indicator';
+ onError(offset + indent.length, 'MISSING_CHAR', message);
+ }
+ if (header.indent === 0)
+ trimIndent = indent.length;
+ contentStart = i;
+ break;
+ }
+ offset += indent.length + content.length + 1;
+ }
+ // include trailing more-indented empty lines in content
+ for (let i = lines.length - 1; i >= chompStart; --i) {
+ if (lines[i][0].length > trimIndent)
+ chompStart = i + 1;
+ }
+ let value = '';
+ let sep = '';
+ let prevMoreIndented = false;
+ // leading whitespace is kept intact
+ for (let i = 0; i < contentStart; ++i)
+ value += lines[i][0].slice(trimIndent) + '\n';
+ for (let i = contentStart; i < chompStart; ++i) {
+ let [indent, content] = lines[i];
+ offset += indent.length + content.length + 1;
+ const crlf = content[content.length - 1] === '\r';
+ if (crlf)
+ content = content.slice(0, -1);
+ /* istanbul ignore if already caught in lexer */
+ if (content && indent.length < trimIndent) {
+ const src = header.indent
+ ? 'explicit indentation indicator'
+ : 'first line';
+ const message = `Block scalar lines must not be less indented than their ${src}`;
+ onError(offset - content.length - (crlf ? 2 : 1), 'BAD_INDENT', message);
+ indent = '';
+ }
+ if (type === Scalar.BLOCK_LITERAL) {
+ value += sep + indent.slice(trimIndent) + content;
+ sep = '\n';
+ }
+ else if (indent.length > trimIndent || content[0] === '\t') {
+ // more-indented content within a folded block
+ if (sep === ' ')
+ sep = '\n';
+ else if (!prevMoreIndented && sep === '\n')
+ sep = '\n\n';
+ value += sep + indent.slice(trimIndent) + content;
+ sep = '\n';
+ prevMoreIndented = true;
+ }
+ else if (content === '') {
+ // empty line
+ if (sep === '\n')
+ value += '\n';
+ else
+ sep = '\n';
+ }
+ else {
+ value += sep + content;
+ sep = ' ';
+ prevMoreIndented = false;
+ }
+ }
+ switch (header.chomp) {
+ case '-':
+ break;
+ case '+':
+ for (let i = chompStart; i < lines.length; ++i)
+ value += '\n' + lines[i][0].slice(trimIndent);
+ if (value[value.length - 1] !== '\n')
+ value += '\n';
+ break;
+ default:
+ value += '\n';
+ }
+ const end = start + header.length + scalar.source.length;
+ return { value, type, comment: header.comment, range: [start, end, end] };
+}
+function parseBlockScalarHeader({ offset, props }, strict, onError) {
+ /* istanbul ignore if should not happen */
+ if (props[0].type !== 'block-scalar-header') {
+ onError(props[0], 'IMPOSSIBLE', 'Block scalar header not found');
+ return null;
+ }
+ const { source } = props[0];
+ const mode = source[0];
+ let indent = 0;
+ let chomp = '';
+ let error = -1;
+ for (let i = 1; i < source.length; ++i) {
+ const ch = source[i];
+ if (!chomp && (ch === '-' || ch === '+'))
+ chomp = ch;
+ else {
+ const n = Number(ch);
+ if (!indent && n)
+ indent = n;
+ else if (error === -1)
+ error = offset + i;
+ }
+ }
+ if (error !== -1)
+ onError(error, 'UNEXPECTED_TOKEN', `Block scalar header includes extra characters: ${source}`);
+ let hasSpace = false;
+ let comment = '';
+ let length = source.length;
+ for (let i = 1; i < props.length; ++i) {
+ const token = props[i];
+ switch (token.type) {
+ case 'space':
+ hasSpace = true;
+ // fallthrough
+ case 'newline':
+ length += token.source.length;
+ break;
+ case 'comment':
+ if (strict && !hasSpace) {
+ const message = 'Comments must be separated from other tokens by white space characters';
+ onError(token, 'MISSING_CHAR', message);
+ }
+ length += token.source.length;
+ comment = token.source.substring(1);
+ break;
+ case 'error':
+ onError(token, 'UNEXPECTED_TOKEN', token.message);
+ length += token.source.length;
+ break;
+ /* istanbul ignore next should not happen */
+ default: {
+ const message = `Unexpected token in block scalar header: ${token.type}`;
+ onError(token, 'UNEXPECTED_TOKEN', message);
+ const ts = token.source;
+ if (ts && typeof ts === 'string')
+ length += ts.length;
+ }
+ }
+ }
+ return { mode, indent, chomp, comment, length };
+}
+/** @returns Array of lines split up as `[indent, content]` */
+function splitLines(source) {
+ const split = source.split(/\n( *)/);
+ const first = split[0];
+ const m = first.match(/^( *)/);
+ const line0 = m?.[1]
+ ? [m[1], first.slice(m[1].length)]
+ : ['', first];
+ const lines = [line0];
+ for (let i = 1; i < split.length; i += 2)
+ lines.push([split[i], split[i + 1]]);
+ return lines;
+}
+
+export { resolveBlockScalar };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-seq.js b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-seq.js
new file mode 100644
index 0000000..4bf08ba
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-block-seq.js
@@ -0,0 +1,45 @@
+import { YAMLSeq } from '../nodes/YAMLSeq.js';
+import { resolveProps } from './resolve-props.js';
+import { flowIndentCheck } from './util-flow-indent-check.js';
+
+function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError) {
+ const seq = new YAMLSeq(ctx.schema);
+ if (ctx.atRoot)
+ ctx.atRoot = false;
+ let offset = bs.offset;
+ let commentEnd = null;
+ for (const { start, value } of bs.items) {
+ const props = resolveProps(start, {
+ indicator: 'seq-item-ind',
+ next: value,
+ offset,
+ onError,
+ startOnNewline: true
+ });
+ if (!props.found) {
+ if (props.anchor || props.tag || value) {
+ if (value && value.type === 'block-seq')
+ onError(props.end, 'BAD_INDENT', 'All sequence items must start at the same column');
+ else
+ onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator');
+ }
+ else {
+ commentEnd = props.end;
+ if (props.comment)
+ seq.comment = props.comment;
+ continue;
+ }
+ }
+ const node = value
+ ? composeNode(ctx, value, props, onError)
+ : composeEmptyNode(ctx, props.end, start, null, props, onError);
+ if (ctx.schema.compat)
+ flowIndentCheck(bs.indent, value, onError);
+ offset = node.range[2];
+ seq.items.push(node);
+ }
+ seq.range = [bs.offset, offset, commentEnd ?? offset];
+ return seq;
+}
+
+export { resolveBlockSeq };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/resolve-end.js b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-end.js
new file mode 100644
index 0000000..d5c65d7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-end.js
@@ -0,0 +1,37 @@
+function resolveEnd(end, offset, reqSpace, onError) {
+ let comment = '';
+ if (end) {
+ let hasSpace = false;
+ let sep = '';
+ for (const token of end) {
+ const { source, type } = token;
+ switch (type) {
+ case 'space':
+ hasSpace = true;
+ break;
+ case 'comment': {
+ if (reqSpace && !hasSpace)
+ onError(token, 'MISSING_CHAR', 'Comments must be separated from other tokens by white space characters');
+ const cb = source.substring(1) || ' ';
+ if (!comment)
+ comment = cb;
+ else
+ comment += sep + cb;
+ sep = '';
+ break;
+ }
+ case 'newline':
+ if (comment)
+ sep += source;
+ hasSpace = true;
+ break;
+ default:
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${type} at node end`);
+ }
+ offset += source.length;
+ }
+ }
+ return { comment, offset };
+}
+
+export { resolveEnd };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js
new file mode 100644
index 0000000..c36e268
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js
@@ -0,0 +1,200 @@
+import { isPair } from '../nodes/Node.js';
+import { Pair } from '../nodes/Pair.js';
+import { YAMLMap } from '../nodes/YAMLMap.js';
+import { YAMLSeq } from '../nodes/YAMLSeq.js';
+import { resolveEnd } from './resolve-end.js';
+import { resolveProps } from './resolve-props.js';
+import { containsNewline } from './util-contains-newline.js';
+import { mapIncludes } from './util-map-includes.js';
+
+const blockMsg = 'Block collections are not allowed within flow collections';
+const isBlock = (token) => token && (token.type === 'block-map' || token.type === 'block-seq');
+function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError) {
+ const isMap = fc.start.source === '{';
+ const fcName = isMap ? 'flow map' : 'flow sequence';
+ const coll = isMap
+ ? new YAMLMap(ctx.schema)
+ : new YAMLSeq(ctx.schema);
+ coll.flow = true;
+ const atRoot = ctx.atRoot;
+ if (atRoot)
+ ctx.atRoot = false;
+ let offset = fc.offset + fc.start.source.length;
+ for (let i = 0; i < fc.items.length; ++i) {
+ const collItem = fc.items[i];
+ const { start, key, sep, value } = collItem;
+ const props = resolveProps(start, {
+ flow: fcName,
+ indicator: 'explicit-key-ind',
+ next: key ?? sep?.[0],
+ offset,
+ onError,
+ startOnNewline: false
+ });
+ if (!props.found) {
+ if (!props.anchor && !props.tag && !sep && !value) {
+ if (i === 0 && props.comma)
+ onError(props.comma, 'UNEXPECTED_TOKEN', `Unexpected , in ${fcName}`);
+ else if (i < fc.items.length - 1)
+ onError(props.start, 'UNEXPECTED_TOKEN', `Unexpected empty item in ${fcName}`);
+ if (props.comment) {
+ if (coll.comment)
+ coll.comment += '\n' + props.comment;
+ else
+ coll.comment = props.comment;
+ }
+ offset = props.end;
+ continue;
+ }
+ if (!isMap && ctx.options.strict && containsNewline(key))
+ onError(key, // checked by containsNewline()
+ 'MULTILINE_IMPLICIT_KEY', 'Implicit keys of flow sequence pairs need to be on a single line');
+ }
+ if (i === 0) {
+ if (props.comma)
+ onError(props.comma, 'UNEXPECTED_TOKEN', `Unexpected , in ${fcName}`);
+ }
+ else {
+ if (!props.comma)
+ onError(props.start, 'MISSING_CHAR', `Missing , between ${fcName} items`);
+ if (props.comment) {
+ let prevItemComment = '';
+ loop: for (const st of start) {
+ switch (st.type) {
+ case 'comma':
+ case 'space':
+ break;
+ case 'comment':
+ prevItemComment = st.source.substring(1);
+ break loop;
+ default:
+ break loop;
+ }
+ }
+ if (prevItemComment) {
+ let prev = coll.items[coll.items.length - 1];
+ if (isPair(prev))
+ prev = prev.value ?? prev.key;
+ if (prev.comment)
+ prev.comment += '\n' + prevItemComment;
+ else
+ prev.comment = prevItemComment;
+ props.comment = props.comment.substring(prevItemComment.length + 1);
+ }
+ }
+ }
+ if (!isMap && !sep && !props.found) {
+ // item is a value in a seq
+ // → key & sep are empty, start does not include ? or :
+ const valueNode = value
+ ? composeNode(ctx, value, props, onError)
+ : composeEmptyNode(ctx, props.end, sep, null, props, onError);
+ coll.items.push(valueNode);
+ offset = valueNode.range[2];
+ if (isBlock(value))
+ onError(valueNode.range, 'BLOCK_IN_FLOW', blockMsg);
+ }
+ else {
+ // item is a key+value pair
+ // key value
+ const keyStart = props.end;
+ const keyNode = key
+ ? composeNode(ctx, key, props, onError)
+ : composeEmptyNode(ctx, keyStart, start, null, props, onError);
+ if (isBlock(key))
+ onError(keyNode.range, 'BLOCK_IN_FLOW', blockMsg);
+ // value properties
+ const valueProps = resolveProps(sep ?? [], {
+ flow: fcName,
+ indicator: 'map-value-ind',
+ next: value,
+ offset: keyNode.range[2],
+ onError,
+ startOnNewline: false
+ });
+ if (valueProps.found) {
+ if (!isMap && !props.found && ctx.options.strict) {
+ if (sep)
+ for (const st of sep) {
+ if (st === valueProps.found)
+ break;
+ if (st.type === 'newline') {
+ onError(st, 'MULTILINE_IMPLICIT_KEY', 'Implicit keys of flow sequence pairs need to be on a single line');
+ break;
+ }
+ }
+ if (props.start < valueProps.found.offset - 1024)
+ onError(valueProps.found, 'KEY_OVER_1024_CHARS', 'The : indicator must be at most 1024 chars after the start of an implicit flow sequence key');
+ }
+ }
+ else if (value) {
+ if ('source' in value && value.source && value.source[0] === ':')
+ onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
+ else
+ onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
+ }
+ // value value
+ const valueNode = value
+ ? composeNode(ctx, value, valueProps, onError)
+ : valueProps.found
+ ? composeEmptyNode(ctx, valueProps.end, sep, null, valueProps, onError)
+ : null;
+ if (valueNode) {
+ if (isBlock(value))
+ onError(valueNode.range, 'BLOCK_IN_FLOW', blockMsg);
+ }
+ else if (valueProps.comment) {
+ if (keyNode.comment)
+ keyNode.comment += '\n' + valueProps.comment;
+ else
+ keyNode.comment = valueProps.comment;
+ }
+ const pair = new Pair(keyNode, valueNode);
+ if (ctx.options.keepSourceTokens)
+ pair.srcToken = collItem;
+ if (isMap) {
+ const map = coll;
+ if (mapIncludes(ctx, map.items, keyNode))
+ onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');
+ map.items.push(pair);
+ }
+ else {
+ const map = new YAMLMap(ctx.schema);
+ map.flow = true;
+ map.items.push(pair);
+ coll.items.push(map);
+ }
+ offset = valueNode ? valueNode.range[2] : valueProps.end;
+ }
+ }
+ const expectedEnd = isMap ? '}' : ']';
+ const [ce, ...ee] = fc.end;
+ let cePos = offset;
+ if (ce && ce.source === expectedEnd)
+ cePos = ce.offset + ce.source.length;
+ else {
+ const name = fcName[0].toUpperCase() + fcName.substring(1);
+ const msg = atRoot
+ ? `${name} must end with a ${expectedEnd}`
+ : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
+ onError(offset, atRoot ? 'MISSING_CHAR' : 'BAD_INDENT', msg);
+ if (ce && ce.source.length !== 1)
+ ee.unshift(ce);
+ }
+ if (ee.length > 0) {
+ const end = resolveEnd(ee, cePos, ctx.options.strict, onError);
+ if (end.comment) {
+ if (coll.comment)
+ coll.comment += '\n' + end.comment;
+ else
+ coll.comment = end.comment;
+ }
+ coll.range = [fc.offset, cePos, end.offset];
+ }
+ else {
+ coll.range = [fc.offset, cePos, cePos];
+ }
+ return coll;
+}
+
+export { resolveFlowCollection };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js
new file mode 100644
index 0000000..501cf39
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js
@@ -0,0 +1,223 @@
+import { Scalar } from '../nodes/Scalar.js';
+import { resolveEnd } from './resolve-end.js';
+
+function resolveFlowScalar(scalar, strict, onError) {
+ const { offset, type, source, end } = scalar;
+ let _type;
+ let value;
+ const _onError = (rel, code, msg) => onError(offset + rel, code, msg);
+ switch (type) {
+ case 'scalar':
+ _type = Scalar.PLAIN;
+ value = plainValue(source, _onError);
+ break;
+ case 'single-quoted-scalar':
+ _type = Scalar.QUOTE_SINGLE;
+ value = singleQuotedValue(source, _onError);
+ break;
+ case 'double-quoted-scalar':
+ _type = Scalar.QUOTE_DOUBLE;
+ value = doubleQuotedValue(source, _onError);
+ break;
+ /* istanbul ignore next should not happen */
+ default:
+ onError(scalar, 'UNEXPECTED_TOKEN', `Expected a flow scalar value, but found: ${type}`);
+ return {
+ value: '',
+ type: null,
+ comment: '',
+ range: [offset, offset + source.length, offset + source.length]
+ };
+ }
+ const valueEnd = offset + source.length;
+ const re = resolveEnd(end, valueEnd, strict, onError);
+ return {
+ value,
+ type: _type,
+ comment: re.comment,
+ range: [offset, valueEnd, re.offset]
+ };
+}
+function plainValue(source, onError) {
+ let badChar = '';
+ switch (source[0]) {
+ /* istanbul ignore next should not happen */
+ case '\t':
+ badChar = 'a tab character';
+ break;
+ case ',':
+ badChar = 'flow indicator character ,';
+ break;
+ case '%':
+ badChar = 'directive indicator character %';
+ break;
+ case '|':
+ case '>': {
+ badChar = `block scalar indicator ${source[0]}`;
+ break;
+ }
+ case '@':
+ case '`': {
+ badChar = `reserved character ${source[0]}`;
+ break;
+ }
+ }
+ if (badChar)
+ onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
+ return foldLines(source);
+}
+function singleQuotedValue(source, onError) {
+ if (source[source.length - 1] !== "'" || source.length === 1)
+ onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
+ return foldLines(source.slice(1, -1)).replace(/''/g, "'");
+}
+function foldLines(source) {
+ /**
+ * The negative lookbehind here and in the `re` RegExp is to
+ * prevent causing a polynomial search time in certain cases.
+ *
+ * The try-catch is for Safari, which doesn't support this yet:
+ * https://caniuse.com/js-regexp-lookbehind
+ */
+ let first, line;
+ try {
+ first = new RegExp('(.*?)(?<![ \t])[ \t]*\r?\n', 'sy');
+ line = new RegExp('[ \t]*(.*?)(?:(?<![ \t])[ \t]*)?\r?\n', 'sy');
+ }
+ catch (_) {
+ first = /(.*?)[ \t]*\r?\n/sy;
+ line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
+ }
+ let match = first.exec(source);
+ if (!match)
+ return source;
+ let res = match[1];
+ let sep = ' ';
+ let pos = first.lastIndex;
+ line.lastIndex = pos;
+ while ((match = line.exec(source))) {
+ if (match[1] === '') {
+ if (sep === '\n')
+ res += sep;
+ else
+ sep = '\n';
+ }
+ else {
+ res += sep + match[1];
+ sep = ' ';
+ }
+ pos = line.lastIndex;
+ }
+ const last = /[ \t]*(.*)/sy;
+ last.lastIndex = pos;
+ match = last.exec(source);
+ return res + sep + (match?.[1] ?? '');
+}
+function doubleQuotedValue(source, onError) {
+ let res = '';
+ for (let i = 1; i < source.length - 1; ++i) {
+ const ch = source[i];
+ if (ch === '\r' && source[i + 1] === '\n')
+ continue;
+ if (ch === '\n') {
+ const { fold, offset } = foldNewline(source, i);
+ res += fold;
+ i = offset;
+ }
+ else if (ch === '\\') {
+ let next = source[++i];
+ const cc = escapeCodes[next];
+ if (cc)
+ res += cc;
+ else if (next === '\n') {
+ // skip escaped newlines, but still trim the following line
+ next = source[i + 1];
+ while (next === ' ' || next === '\t')
+ next = source[++i + 1];
+ }
+ else if (next === '\r' && source[i + 1] === '\n') {
+ // skip escaped CRLF newlines, but still trim the following line
+ next = source[++i + 1];
+ while (next === ' ' || next === '\t')
+ next = source[++i + 1];
+ }
+ else if (next === 'x' || next === 'u' || next === 'U') {
+ const length = { x: 2, u: 4, U: 8 }[next];
+ res += parseCharCode(source, i + 1, length, onError);
+ i += length;
+ }
+ else {
+ const raw = source.substr(i - 1, 2);
+ onError(i - 1, 'BAD_DQ_ESCAPE', `Invalid escape sequence ${raw}`);
+ res += raw;
+ }
+ }
+ else if (ch === ' ' || ch === '\t') {
+ // trim trailing whitespace
+ const wsStart = i;
+ let next = source[i + 1];
+ while (next === ' ' || next === '\t')
+ next = source[++i + 1];
+ if (next !== '\n' && !(next === '\r' && source[i + 2] === '\n'))
+ res += i > wsStart ? source.slice(wsStart, i + 1) : ch;
+ }
+ else {
+ res += ch;
+ }
+ }
+ if (source[source.length - 1] !== '"' || source.length === 1)
+ onError(source.length, 'MISSING_CHAR', 'Missing closing "quote');
+ return res;
+}
+/**
+ * Fold a single newline into a space, multiple newlines to N - 1 newlines.
+ * Presumes `source[offset] === '\n'`
+ */
+function foldNewline(source, offset) {
+ let fold = '';
+ let ch = source[offset + 1];
+ while (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r') {
+ if (ch === '\r' && source[offset + 2] !== '\n')
+ break;
+ if (ch === '\n')
+ fold += '\n';
+ offset += 1;
+ ch = source[offset + 1];
+ }
+ if (!fold)
+ fold = ' ';
+ return { fold, offset };
+}
+const escapeCodes = {
+ '0': '\0',
+ a: '\x07',
+ b: '\b',
+ e: '\x1b',
+ f: '\f',
+ n: '\n',
+ r: '\r',
+ t: '\t',
+ v: '\v',
+ N: '\u0085',
+ _: '\u00a0',
+ L: '\u2028',
+ P: '\u2029',
+ ' ': ' ',
+ '"': '"',
+ '/': '/',
+ '\\': '\\',
+ '\t': '\t'
+};
+function parseCharCode(source, offset, length, onError) {
+ const cc = source.substr(offset, length);
+ const ok = cc.length === length && /^[0-9a-fA-F]+$/.test(cc);
+ const code = ok ? parseInt(cc, 16) : NaN;
+ if (isNaN(code)) {
+ const raw = source.substr(offset - 2, length + 2);
+ onError(offset - 2, 'BAD_DQ_ESCAPE', `Invalid escape sequence ${raw}`);
+ return raw;
+ }
+ return String.fromCodePoint(code);
+}
+
+export { resolveFlowScalar };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/resolve-props.js b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-props.js
new file mode 100644
index 0000000..ab30f56
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/resolve-props.js
@@ -0,0 +1,134 @@
+function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnNewline }) {
+ let spaceBefore = false;
+ let atNewline = startOnNewline;
+ let hasSpace = startOnNewline;
+ let comment = '';
+ let commentSep = '';
+ let hasNewline = false;
+ let hasNewlineAfterProp = false;
+ let reqSpace = false;
+ let anchor = null;
+ let tag = null;
+ let comma = null;
+ let found = null;
+ let start = null;
+ for (const token of tokens) {
+ if (reqSpace) {
+ if (token.type !== 'space' &&
+ token.type !== 'newline' &&
+ token.type !== 'comma')
+ onError(token.offset, 'MISSING_CHAR', 'Tags and anchors must be separated from the next token by white space');
+ reqSpace = false;
+ }
+ switch (token.type) {
+ case 'space':
+ // At the doc level, tabs at line start may be parsed
+ // as leading white space rather than indentation.
+ // In a flow collection, only the parser handles indent.
+ if (!flow &&
+ atNewline &&
+ indicator !== 'doc-start' &&
+ token.source[0] === '\t')
+ onError(token, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation');
+ hasSpace = true;
+ break;
+ case 'comment': {
+ if (!hasSpace)
+ onError(token, 'MISSING_CHAR', 'Comments must be separated from other tokens by white space characters');
+ const cb = token.source.substring(1) || ' ';
+ if (!comment)
+ comment = cb;
+ else
+ comment += commentSep + cb;
+ commentSep = '';
+ atNewline = false;
+ break;
+ }
+ case 'newline':
+ if (atNewline) {
+ if (comment)
+ comment += token.source;
+ else
+ spaceBefore = true;
+ }
+ else
+ commentSep += token.source;
+ atNewline = true;
+ hasNewline = true;
+ if (anchor || tag)
+ hasNewlineAfterProp = true;
+ hasSpace = true;
+ break;
+ case 'anchor':
+ if (anchor)
+ onError(token, 'MULTIPLE_ANCHORS', 'A node can have at most one anchor');
+ if (token.source.endsWith(':'))
+ onError(token.offset + token.source.length - 1, 'BAD_ALIAS', 'Anchor ending in : is ambiguous', true);
+ anchor = token;
+ if (start === null)
+ start = token.offset;
+ atNewline = false;
+ hasSpace = false;
+ reqSpace = true;
+ break;
+ case 'tag': {
+ if (tag)
+ onError(token, 'MULTIPLE_TAGS', 'A node can have at most one tag');
+ tag = token;
+ if (start === null)
+ start = token.offset;
+ atNewline = false;
+ hasSpace = false;
+ reqSpace = true;
+ break;
+ }
+ case indicator:
+ // Could here handle preceding comments differently
+ if (anchor || tag)
+ onError(token, 'BAD_PROP_ORDER', `Anchors and tags must be after the ${token.source} indicator`);
+ if (found)
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.source} in ${flow ?? 'collection'}`);
+ found = token;
+ atNewline = false;
+ hasSpace = false;
+ break;
+ case 'comma':
+ if (flow) {
+ if (comma)
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected , in ${flow}`);
+ comma = token;
+ atNewline = false;
+ hasSpace = false;
+ break;
+ }
+ // else fallthrough
+ default:
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.type} token`);
+ atNewline = false;
+ hasSpace = false;
+ }
+ }
+ const last = tokens[tokens.length - 1];
+ const end = last ? last.offset + last.source.length : offset;
+ if (reqSpace &&
+ next &&
+ next.type !== 'space' &&
+ next.type !== 'newline' &&
+ next.type !== 'comma' &&
+ (next.type !== 'scalar' || next.source !== ''))
+ onError(next.offset, 'MISSING_CHAR', 'Tags and anchors must be separated from the next token by white space');
+ return {
+ comma,
+ found,
+ spaceBefore,
+ comment,
+ hasNewline,
+ hasNewlineAfterProp,
+ anchor,
+ tag,
+ end,
+ start: start ?? end
+ };
+}
+
+export { resolveProps };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/util-contains-newline.js b/MistyCore/node_modules/yaml/browser/dist/compose/util-contains-newline.js
new file mode 100644
index 0000000..2d65390
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/util-contains-newline.js
@@ -0,0 +1,34 @@
+function containsNewline(key) {
+ if (!key)
+ return null;
+ switch (key.type) {
+ case 'alias':
+ case 'scalar':
+ case 'double-quoted-scalar':
+ case 'single-quoted-scalar':
+ if (key.source.includes('\n'))
+ return true;
+ if (key.end)
+ for (const st of key.end)
+ if (st.type === 'newline')
+ return true;
+ return false;
+ case 'flow-collection':
+ for (const it of key.items) {
+ for (const st of it.start)
+ if (st.type === 'newline')
+ return true;
+ if (it.sep)
+ for (const st of it.sep)
+ if (st.type === 'newline')
+ return true;
+ if (containsNewline(it.key) || containsNewline(it.value))
+ return true;
+ }
+ return false;
+ default:
+ return true;
+ }
+}
+
+export { containsNewline };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js b/MistyCore/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js
new file mode 100644
index 0000000..ab6e0c9
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js
@@ -0,0 +1,27 @@
+function emptyScalarPosition(offset, before, pos) {
+ if (before) {
+ if (pos === null)
+ pos = before.length;
+ for (let i = pos - 1; i >= 0; --i) {
+ let st = before[i];
+ switch (st.type) {
+ case 'space':
+ case 'comment':
+ case 'newline':
+ offset -= st.source.length;
+ continue;
+ }
+ // Technically, an empty scalar is immediately after the last non-empty
+ // node, but it's more useful to place it after any whitespace.
+ st = before[++i];
+ while (st?.type === 'space') {
+ offset += st.source.length;
+ st = before[++i];
+ }
+ break;
+ }
+ }
+ return offset;
+}
+
+export { emptyScalarPosition };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js b/MistyCore/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js
new file mode 100644
index 0000000..c20e670
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js
@@ -0,0 +1,15 @@
+import { containsNewline } from './util-contains-newline.js';
+
+function flowIndentCheck(indent, fc, onError) {
+ if (fc?.type === 'flow-collection') {
+ const end = fc.end[0];
+ if (end.indent === indent &&
+ (end.source === ']' || end.source === '}') &&
+ containsNewline(fc)) {
+ const msg = 'Flow end indicator should be more indented than parent';
+ onError(end, 'BAD_INDENT', msg, true);
+ }
+ }
+}
+
+export { flowIndentCheck };
diff --git a/MistyCore/node_modules/yaml/browser/dist/compose/util-map-includes.js b/MistyCore/node_modules/yaml/browser/dist/compose/util-map-includes.js
new file mode 100644
index 0000000..de74ddf
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/compose/util-map-includes.js
@@ -0,0 +1,17 @@
+import { isScalar } from '../nodes/Node.js';
+
+function mapIncludes(ctx, items, search) {
+ const { uniqueKeys } = ctx.options;
+ if (uniqueKeys === false)
+ return false;
+ const isEqual = typeof uniqueKeys === 'function'
+ ? uniqueKeys
+ : (a, b) => a === b ||
+ (isScalar(a) &&
+ isScalar(b) &&
+ a.value === b.value &&
+ !(a.value === '<<' && ctx.schema.merge));
+ return items.some(pair => isEqual(pair.key, search));
+}
+
+export { mapIncludes };
diff --git a/MistyCore/node_modules/yaml/browser/dist/doc/Document.js b/MistyCore/node_modules/yaml/browser/dist/doc/Document.js
new file mode 100644
index 0000000..82e3693
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/doc/Document.js
@@ -0,0 +1,332 @@
+import { Alias } from '../nodes/Alias.js';
+import { isEmptyPath, collectionFromPath } from '../nodes/Collection.js';
+import { NODE_TYPE, DOC, isNode, isCollection, isScalar } from '../nodes/Node.js';
+import { Pair } from '../nodes/Pair.js';
+import { toJS } from '../nodes/toJS.js';
+import { Schema } from '../schema/Schema.js';
+import { stringify } from '../stringify/stringify.js';
+import { stringifyDocument } from '../stringify/stringifyDocument.js';
+import { anchorNames, findNewAnchor, createNodeAnchors } from './anchors.js';
+import { applyReviver } from './applyReviver.js';
+import { createNode } from './createNode.js';
+import { Directives } from './directives.js';
+
+class Document {
+ constructor(value, replacer, options) {
+ /** A comment before this Document */
+ this.commentBefore = null;
+ /** A comment immediately after this Document */
+ this.comment = null;
+ /** Errors encountered during parsing. */
+ this.errors = [];
+ /** Warnings encountered during parsing. */
+ this.warnings = [];
+ Object.defineProperty(this, NODE_TYPE, { value: DOC });
+ let _replacer = null;
+ if (typeof replacer === 'function' || Array.isArray(replacer)) {
+ _replacer = replacer;
+ }
+ else if (options === undefined && replacer) {
+ options = replacer;
+ replacer = undefined;
+ }
+ const opt = Object.assign({
+ intAsBigInt: false,
+ keepSourceTokens: false,
+ logLevel: 'warn',
+ prettyErrors: true,
+ strict: true,
+ uniqueKeys: true,
+ version: '1.2'
+ }, options);
+ this.options = opt;
+ let { version } = opt;
+ if (options?._directives) {
+ this.directives = options._directives.atDocument();
+ if (this.directives.yaml.explicit)
+ version = this.directives.yaml.version;
+ }
+ else
+ this.directives = new Directives({ version });
+ this.setSchema(version, options);
+ if (value === undefined)
+ this.contents = null;
+ else {
+ this.contents = this.createNode(value, _replacer, options);
+ }
+ }
+ /**
+ * Create a deep copy of this Document and its contents.
+ *
+ * Custom Node values that inherit from `Object` still refer to their original instances.
+ */
+ clone() {
+ const copy = Object.create(Document.prototype, {
+ [NODE_TYPE]: { value: DOC }
+ });
+ copy.commentBefore = this.commentBefore;
+ copy.comment = this.comment;
+ copy.errors = this.errors.slice();
+ copy.warnings = this.warnings.slice();
+ copy.options = Object.assign({}, this.options);
+ if (this.directives)
+ copy.directives = this.directives.clone();
+ copy.schema = this.schema.clone();
+ copy.contents = isNode(this.contents)
+ ? this.contents.clone(copy.schema)
+ : this.contents;
+ if (this.range)
+ copy.range = this.range.slice();
+ return copy;
+ }
+ /** Adds a value to the document. */
+ add(value) {
+ if (assertCollection(this.contents))
+ this.contents.add(value);
+ }
+ /** Adds a value to the document. */
+ addIn(path, value) {
+ if (assertCollection(this.contents))
+ this.contents.addIn(path, value);
+ }
+ /**
+ * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
+ *
+ * If `node` already has an anchor, `name` is ignored.
+ * Otherwise, the `node.anchor` value will be set to `name`,
+ * or if an anchor with that name is already present in the document,
+ * `name` will be used as a prefix for a new unique anchor.
+ * If `name` is undefined, the generated anchor will use 'a' as a prefix.
+ */
+ createAlias(node, name) {
+ if (!node.anchor) {
+ const prev = anchorNames(this);
+ node.anchor =
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ !name || prev.has(name) ? findNewAnchor(name || 'a', prev) : name;
+ }
+ return new Alias(node.anchor);
+ }
+ createNode(value, replacer, options) {
+ let _replacer = undefined;
+ if (typeof replacer === 'function') {
+ value = replacer.call({ '': value }, '', value);
+ _replacer = replacer;
+ }
+ else if (Array.isArray(replacer)) {
+ const keyToStr = (v) => typeof v === 'number' || v instanceof String || v instanceof Number;
+ const asStr = replacer.filter(keyToStr).map(String);
+ if (asStr.length > 0)
+ replacer = replacer.concat(asStr);
+ _replacer = replacer;
+ }
+ else if (options === undefined && replacer) {
+ options = replacer;
+ replacer = undefined;
+ }
+ const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options ?? {};
+ const { onAnchor, setAnchors, sourceObjects } = createNodeAnchors(this,
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ anchorPrefix || 'a');
+ const ctx = {
+ aliasDuplicateObjects: aliasDuplicateObjects ?? true,
+ keepUndefined: keepUndefined ?? false,
+ onAnchor,
+ onTagObj,
+ replacer: _replacer,
+ schema: this.schema,
+ sourceObjects
+ };
+ const node = createNode(value, tag, ctx);
+ if (flow && isCollection(node))
+ node.flow = true;
+ setAnchors();
+ return node;
+ }
+ /**
+ * Convert a key and a value into a `Pair` using the current schema,
+ * recursively wrapping all values as `Scalar` or `Collection` nodes.
+ */
+ createPair(key, value, options = {}) {
+ const k = this.createNode(key, null, options);
+ const v = this.createNode(value, null, options);
+ return new Pair(k, v);
+ }
+ /**
+ * Removes a value from the document.
+ * @returns `true` if the item was found and removed.
+ */
+ delete(key) {
+ return assertCollection(this.contents) ? this.contents.delete(key) : false;
+ }
+ /**
+ * Removes a value from the document.
+ * @returns `true` if the item was found and removed.
+ */
+ deleteIn(path) {
+ if (isEmptyPath(path)) {
+ if (this.contents == null)
+ return false;
+ this.contents = null;
+ return true;
+ }
+ return assertCollection(this.contents)
+ ? this.contents.deleteIn(path)
+ : false;
+ }
+ /**
+ * Returns item at `key`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ get(key, keepScalar) {
+ return isCollection(this.contents)
+ ? this.contents.get(key, keepScalar)
+ : undefined;
+ }
+ /**
+ * Returns item at `path`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ getIn(path, keepScalar) {
+ if (isEmptyPath(path))
+ return !keepScalar && isScalar(this.contents)
+ ? this.contents.value
+ : this.contents;
+ return isCollection(this.contents)
+ ? this.contents.getIn(path, keepScalar)
+ : undefined;
+ }
+ /**
+ * Checks if the document includes a value with the key `key`.
+ */
+ has(key) {
+ return isCollection(this.contents) ? this.contents.has(key) : false;
+ }
+ /**
+ * Checks if the document includes a value at `path`.
+ */
+ hasIn(path) {
+ if (isEmptyPath(path))
+ return this.contents !== undefined;
+ return isCollection(this.contents) ? this.contents.hasIn(path) : false;
+ }
+ /**
+ * Sets a value in this document. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ set(key, value) {
+ if (this.contents == null) {
+ this.contents = collectionFromPath(this.schema, [key], value);
+ }
+ else if (assertCollection(this.contents)) {
+ this.contents.set(key, value);
+ }
+ }
+ /**
+ * Sets a value in this document. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ setIn(path, value) {
+ if (isEmptyPath(path))
+ this.contents = value;
+ else if (this.contents == null) {
+ this.contents = collectionFromPath(this.schema, Array.from(path), value);
+ }
+ else if (assertCollection(this.contents)) {
+ this.contents.setIn(path, value);
+ }
+ }
+ /**
+ * Change the YAML version and schema used by the document.
+ * A `null` version disables support for directives, explicit tags, anchors, and aliases.
+ * It also requires the `schema` option to be given as a `Schema` instance value.
+ *
+ * Overrides all previously set schema options.
+ */
+ setSchema(version, options = {}) {
+ if (typeof version === 'number')
+ version = String(version);
+ let opt;
+ switch (version) {
+ case '1.1':
+ if (this.directives)
+ this.directives.yaml.version = '1.1';
+ else
+ this.directives = new Directives({ version: '1.1' });
+ opt = { merge: true, resolveKnownTags: false, schema: 'yaml-1.1' };
+ break;
+ case '1.2':
+ case 'next':
+ if (this.directives)
+ this.directives.yaml.version = version;
+ else
+ this.directives = new Directives({ version });
+ opt = { merge: false, resolveKnownTags: true, schema: 'core' };
+ break;
+ case null:
+ if (this.directives)
+ delete this.directives;
+ opt = null;
+ break;
+ default: {
+ const sv = JSON.stringify(version);
+ throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
+ }
+ }
+ // Not using `instanceof Schema` to allow for duck typing
+ if (options.schema instanceof Object)
+ this.schema = options.schema;
+ else if (opt)
+ this.schema = new Schema(Object.assign(opt, options));
+ else
+ throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
+ }
+ // json & jsonArg are only used from toJSON()
+ toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
+ const ctx = {
+ anchors: new Map(),
+ doc: this,
+ keep: !json,
+ mapAsMap: mapAsMap === true,
+ mapKeyWarned: false,
+ maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100,
+ stringify
+ };
+ const res = toJS(this.contents, jsonArg ?? '', ctx);
+ if (typeof onAnchor === 'function')
+ for (const { count, res } of ctx.anchors.values())
+ onAnchor(res, count);
+ return typeof reviver === 'function'
+ ? applyReviver(reviver, { '': res }, '', res)
+ : res;
+ }
+ /**
+ * A JSON representation of the document `contents`.
+ *
+ * @param jsonArg Used by `JSON.stringify` to indicate the array index or
+ * property name.
+ */
+ toJSON(jsonArg, onAnchor) {
+ return this.toJS({ json: true, jsonArg, mapAsMap: false, onAnchor });
+ }
+ /** A YAML representation of the document. */
+ toString(options = {}) {
+ if (this.errors.length > 0)
+ throw new Error('Document with errors cannot be stringified');
+ if ('indent' in options &&
+ (!Number.isInteger(options.indent) || Number(options.indent) <= 0)) {
+ const s = JSON.stringify(options.indent);
+ throw new Error(`"indent" option must be a positive integer, not ${s}`);
+ }
+ return stringifyDocument(this, options);
+ }
+}
+function assertCollection(contents) {
+ if (isCollection(contents))
+ return true;
+ throw new Error('Expected a YAML collection as document contents');
+}
+
+export { Document };
diff --git a/MistyCore/node_modules/yaml/browser/dist/doc/anchors.js b/MistyCore/node_modules/yaml/browser/dist/doc/anchors.js
new file mode 100644
index 0000000..797e8a7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/doc/anchors.js
@@ -0,0 +1,72 @@
+import { isScalar, isCollection } from '../nodes/Node.js';
+import { visit } from '../visit.js';
+
+/**
+ * Verify that the input string is a valid anchor.
+ *
+ * Will throw on errors.
+ */
+function anchorIsValid(anchor) {
+ if (/[\x00-\x19\s,[\]{}]/.test(anchor)) {
+ const sa = JSON.stringify(anchor);
+ const msg = `Anchor must not contain whitespace or control characters: ${sa}`;
+ throw new Error(msg);
+ }
+ return true;
+}
+function anchorNames(root) {
+ const anchors = new Set();
+ visit(root, {
+ Value(_key, node) {
+ if (node.anchor)
+ anchors.add(node.anchor);
+ }
+ });
+ return anchors;
+}
+/** Find a new anchor name with the given `prefix` and a one-indexed suffix. */
+function findNewAnchor(prefix, exclude) {
+ for (let i = 1; true; ++i) {
+ const name = `${prefix}${i}`;
+ if (!exclude.has(name))
+ return name;
+ }
+}
+function createNodeAnchors(doc, prefix) {
+ const aliasObjects = [];
+ const sourceObjects = new Map();
+ let prevAnchors = null;
+ return {
+ onAnchor: (source) => {
+ aliasObjects.push(source);
+ if (!prevAnchors)
+ prevAnchors = anchorNames(doc);
+ const anchor = findNewAnchor(prefix, prevAnchors);
+ prevAnchors.add(anchor);
+ return anchor;
+ },
+ /**
+ * With circular references, the source node is only resolved after all
+ * of its child nodes are. This is why anchors are set only after all of
+ * the nodes have been created.
+ */
+ setAnchors: () => {
+ for (const source of aliasObjects) {
+ const ref = sourceObjects.get(source);
+ if (typeof ref === 'object' &&
+ ref.anchor &&
+ (isScalar(ref.node) || isCollection(ref.node))) {
+ ref.node.anchor = ref.anchor;
+ }
+ else {
+ const error = new Error('Failed to resolve repeated object (this should not happen)');
+ error.source = source;
+ throw error;
+ }
+ }
+ },
+ sourceObjects
+ };
+}
+
+export { anchorIsValid, anchorNames, createNodeAnchors, findNewAnchor };
diff --git a/MistyCore/node_modules/yaml/browser/dist/doc/applyReviver.js b/MistyCore/node_modules/yaml/browser/dist/doc/applyReviver.js
new file mode 100644
index 0000000..0e6a93c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/doc/applyReviver.js
@@ -0,0 +1,54 @@
+/**
+ * Applies the JSON.parse reviver algorithm as defined in the ECMA-262 spec,
+ * in section 24.5.1.1 "Runtime Semantics: InternalizeJSONProperty" of the
+ * 2021 edition: https://tc39.es/ecma262/#sec-json.parse
+ *
+ * Includes extensions for handling Map and Set objects.
+ */
+function applyReviver(reviver, obj, key, val) {
+ if (val && typeof val === 'object') {
+ if (Array.isArray(val)) {
+ for (let i = 0, len = val.length; i < len; ++i) {
+ const v0 = val[i];
+ const v1 = applyReviver(reviver, val, String(i), v0);
+ if (v1 === undefined)
+ delete val[i];
+ else if (v1 !== v0)
+ val[i] = v1;
+ }
+ }
+ else if (val instanceof Map) {
+ for (const k of Array.from(val.keys())) {
+ const v0 = val.get(k);
+ const v1 = applyReviver(reviver, val, k, v0);
+ if (v1 === undefined)
+ val.delete(k);
+ else if (v1 !== v0)
+ val.set(k, v1);
+ }
+ }
+ else if (val instanceof Set) {
+ for (const v0 of Array.from(val)) {
+ const v1 = applyReviver(reviver, val, v0, v0);
+ if (v1 === undefined)
+ val.delete(v0);
+ else if (v1 !== v0) {
+ val.delete(v0);
+ val.add(v1);
+ }
+ }
+ }
+ else {
+ for (const [k, v0] of Object.entries(val)) {
+ const v1 = applyReviver(reviver, val, k, v0);
+ if (v1 === undefined)
+ delete val[k];
+ else if (v1 !== v0)
+ val[k] = v1;
+ }
+ }
+ }
+ return reviver.call(obj, key, val);
+}
+
+export { applyReviver };
diff --git a/MistyCore/node_modules/yaml/browser/dist/doc/createNode.js b/MistyCore/node_modules/yaml/browser/dist/doc/createNode.js
new file mode 100644
index 0000000..52ca122
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/doc/createNode.js
@@ -0,0 +1,85 @@
+import { Alias } from '../nodes/Alias.js';
+import { isNode, isPair, MAP, SEQ, isDocument } from '../nodes/Node.js';
+import { Scalar } from '../nodes/Scalar.js';
+
+const defaultTagPrefix = 'tag:yaml.org,2002:';
+function findTagObject(value, tagName, tags) {
+ if (tagName) {
+ const match = tags.filter(t => t.tag === tagName);
+ const tagObj = match.find(t => !t.format) ?? match[0];
+ if (!tagObj)
+ throw new Error(`Tag ${tagName} not found`);
+ return tagObj;
+ }
+ return tags.find(t => t.identify?.(value) && !t.format);
+}
+function createNode(value, tagName, ctx) {
+ if (isDocument(value))
+ value = value.contents;
+ if (isNode(value))
+ return value;
+ if (isPair(value)) {
+ const map = ctx.schema[MAP].createNode?.(ctx.schema, null, ctx);
+ map.items.push(value);
+ return map;
+ }
+ if (value instanceof String ||
+ value instanceof Number ||
+ value instanceof Boolean ||
+ (typeof BigInt !== 'undefined' && value instanceof BigInt) // not supported everywhere
+ ) {
+ // https://tc39.es/ecma262/#sec-serializejsonproperty
+ value = value.valueOf();
+ }
+ const { aliasDuplicateObjects, onAnchor, onTagObj, schema, sourceObjects } = ctx;
+ // Detect duplicate references to the same object & use Alias nodes for all
+ // after first. The `ref` wrapper allows for circular references to resolve.
+ let ref = undefined;
+ if (aliasDuplicateObjects && value && typeof value === 'object') {
+ ref = sourceObjects.get(value);
+ if (ref) {
+ if (!ref.anchor)
+ ref.anchor = onAnchor(value);
+ return new Alias(ref.anchor);
+ }
+ else {
+ ref = { anchor: null, node: null };
+ sourceObjects.set(value, ref);
+ }
+ }
+ if (tagName?.startsWith('!!'))
+ tagName = defaultTagPrefix + tagName.slice(2);
+ let tagObj = findTagObject(value, tagName, schema.tags);
+ if (!tagObj) {
+ if (value && typeof value.toJSON === 'function') {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+ value = value.toJSON();
+ }
+ if (!value || typeof value !== 'object') {
+ const node = new Scalar(value);
+ if (ref)
+ ref.node = node;
+ return node;
+ }
+ tagObj =
+ value instanceof Map
+ ? schema[MAP]
+ : Symbol.iterator in Object(value)
+ ? schema[SEQ]
+ : schema[MAP];
+ }
+ if (onTagObj) {
+ onTagObj(tagObj);
+ delete ctx.onTagObj;
+ }
+ const node = tagObj?.createNode
+ ? tagObj.createNode(ctx.schema, value, ctx)
+ : new Scalar(value);
+ if (tagName)
+ node.tag = tagName;
+ if (ref)
+ ref.node = node;
+ return node;
+}
+
+export { createNode };
diff --git a/MistyCore/node_modules/yaml/browser/dist/doc/directives.js b/MistyCore/node_modules/yaml/browser/dist/doc/directives.js
new file mode 100644
index 0000000..bdbc153
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/doc/directives.js
@@ -0,0 +1,169 @@
+import { isNode } from '../nodes/Node.js';
+import { visit } from '../visit.js';
+
+const escapeChars = {
+ '!': '%21',
+ ',': '%2C',
+ '[': '%5B',
+ ']': '%5D',
+ '{': '%7B',
+ '}': '%7D'
+};
+const escapeTagName = (tn) => tn.replace(/[!,[\]{}]/g, ch => escapeChars[ch]);
+class Directives {
+ constructor(yaml, tags) {
+ /**
+ * The directives-end/doc-start marker `---`. If `null`, a marker may still be
+ * included in the document's stringified representation.
+ */
+ this.docStart = null;
+ /** The doc-end marker `...`. */
+ this.docEnd = false;
+ this.yaml = Object.assign({}, Directives.defaultYaml, yaml);
+ this.tags = Object.assign({}, Directives.defaultTags, tags);
+ }
+ clone() {
+ const copy = new Directives(this.yaml, this.tags);
+ copy.docStart = this.docStart;
+ return copy;
+ }
+ /**
+ * During parsing, get a Directives instance for the current document and
+ * update the stream state according to the current version's spec.
+ */
+ atDocument() {
+ const res = new Directives(this.yaml, this.tags);
+ switch (this.yaml.version) {
+ case '1.1':
+ this.atNextDocument = true;
+ break;
+ case '1.2':
+ this.atNextDocument = false;
+ this.yaml = {
+ explicit: Directives.defaultYaml.explicit,
+ version: '1.2'
+ };
+ this.tags = Object.assign({}, Directives.defaultTags);
+ break;
+ }
+ return res;
+ }
+ /**
+ * @param onError - May be called even if the action was successful
+ * @returns `true` on success
+ */
+ add(line, onError) {
+ if (this.atNextDocument) {
+ this.yaml = { explicit: Directives.defaultYaml.explicit, version: '1.1' };
+ this.tags = Object.assign({}, Directives.defaultTags);
+ this.atNextDocument = false;
+ }
+ const parts = line.trim().split(/[ \t]+/);
+ const name = parts.shift();
+ switch (name) {
+ case '%TAG': {
+ if (parts.length !== 2) {
+ onError(0, '%TAG directive should contain exactly two parts');
+ if (parts.length < 2)
+ return false;
+ }
+ const [handle, prefix] = parts;
+ this.tags[handle] = prefix;
+ return true;
+ }
+ case '%YAML': {
+ this.yaml.explicit = true;
+ if (parts.length !== 1) {
+ onError(0, '%YAML directive should contain exactly one part');
+ return false;
+ }
+ const [version] = parts;
+ if (version === '1.1' || version === '1.2') {
+ this.yaml.version = version;
+ return true;
+ }
+ else {
+ const isValid = /^\d+\.\d+$/.test(version);
+ onError(6, `Unsupported YAML version ${version}`, isValid);
+ return false;
+ }
+ }
+ default:
+ onError(0, `Unknown directive ${name}`, true);
+ return false;
+ }
+ }
+ /**
+ * Resolves a tag, matching handles to those defined in %TAG directives.
+ *
+ * @returns Resolved tag, which may also be the non-specific tag `'!'` or a
+ * `'!local'` tag, or `null` if unresolvable.
+ */
+ tagName(source, onError) {
+ if (source === '!')
+ return '!'; // non-specific tag
+ if (source[0] !== '!') {
+ onError(`Not a valid tag: ${source}`);
+ return null;
+ }
+ if (source[1] === '<') {
+ const verbatim = source.slice(2, -1);
+ if (verbatim === '!' || verbatim === '!!') {
+ onError(`Verbatim tags aren't resolved, so ${source} is invalid.`);
+ return null;
+ }
+ if (source[source.length - 1] !== '>')
+ onError('Verbatim tags must end with a >');
+ return verbatim;
+ }
+ const [, handle, suffix] = source.match(/^(.*!)([^!]*)$/);
+ if (!suffix)
+ onError(`The ${source} tag has no suffix`);
+ const prefix = this.tags[handle];
+ if (prefix)
+ return prefix + decodeURIComponent(suffix);
+ if (handle === '!')
+ return source; // local tag
+ onError(`Could not resolve tag: ${source}`);
+ return null;
+ }
+ /**
+ * Given a fully resolved tag, returns its printable string form,
+ * taking into account current tag prefixes and defaults.
+ */
+ tagString(tag) {
+ for (const [handle, prefix] of Object.entries(this.tags)) {
+ if (tag.startsWith(prefix))
+ return handle + escapeTagName(tag.substring(prefix.length));
+ }
+ return tag[0] === '!' ? tag : `!<${tag}>`;
+ }
+ toString(doc) {
+ const lines = this.yaml.explicit
+ ? [`%YAML ${this.yaml.version || '1.2'}`]
+ : [];
+ const tagEntries = Object.entries(this.tags);
+ let tagNames;
+ if (doc && tagEntries.length > 0 && isNode(doc.contents)) {
+ const tags = {};
+ visit(doc.contents, (_key, node) => {
+ if (isNode(node) && node.tag)
+ tags[node.tag] = true;
+ });
+ tagNames = Object.keys(tags);
+ }
+ else
+ tagNames = [];
+ for (const [handle, prefix] of tagEntries) {
+ if (handle === '!!' && prefix === 'tag:yaml.org,2002:')
+ continue;
+ if (!doc || tagNames.some(tn => tn.startsWith(prefix)))
+ lines.push(`%TAG ${handle} ${prefix}`);
+ }
+ return lines.join('\n');
+ }
+}
+Directives.defaultYaml = { explicit: false, version: '1.2' };
+Directives.defaultTags = { '!!': 'tag:yaml.org,2002:' };
+
+export { Directives };
diff --git a/MistyCore/node_modules/yaml/browser/dist/errors.js b/MistyCore/node_modules/yaml/browser/dist/errors.js
new file mode 100644
index 0000000..2fac9b7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/errors.js
@@ -0,0 +1,57 @@
+class YAMLError extends Error {
+ constructor(name, pos, code, message) {
+ super();
+ this.name = name;
+ this.code = code;
+ this.message = message;
+ this.pos = pos;
+ }
+}
+class YAMLParseError extends YAMLError {
+ constructor(pos, code, message) {
+ super('YAMLParseError', pos, code, message);
+ }
+}
+class YAMLWarning extends YAMLError {
+ constructor(pos, code, message) {
+ super('YAMLWarning', pos, code, message);
+ }
+}
+const prettifyError = (src, lc) => (error) => {
+ if (error.pos[0] === -1)
+ return;
+ error.linePos = error.pos.map(pos => lc.linePos(pos));
+ const { line, col } = error.linePos[0];
+ error.message += ` at line ${line}, column ${col}`;
+ let ci = col - 1;
+ let lineStr = src
+ .substring(lc.lineStarts[line - 1], lc.lineStarts[line])
+ .replace(/[\n\r]+$/, '');
+ // Trim to max 80 chars, keeping col position near the middle
+ if (ci >= 60 && lineStr.length > 80) {
+ const trimStart = Math.min(ci - 39, lineStr.length - 79);
+ lineStr = '…' + lineStr.substring(trimStart);
+ ci -= trimStart - 1;
+ }
+ if (lineStr.length > 80)
+ lineStr = lineStr.substring(0, 79) + '…';
+ // Include previous line in context if pointing at line start
+ if (line > 1 && /^ *$/.test(lineStr.substring(0, ci))) {
+ // Regexp won't match if start is trimmed
+ let prev = src.substring(lc.lineStarts[line - 2], lc.lineStarts[line - 1]);
+ if (prev.length > 80)
+ prev = prev.substring(0, 79) + '…\n';
+ lineStr = prev + lineStr;
+ }
+ if (/[^ ]/.test(lineStr)) {
+ let count = 1;
+ const end = error.linePos[1];
+ if (end && end.line === line && end.col > col) {
+ count = Math.min(end.col - col, 80 - ci);
+ }
+ const pointer = ' '.repeat(ci) + '^'.repeat(count);
+ error.message += `:\n\n${lineStr}\n${pointer}\n`;
+ }
+};
+
+export { YAMLError, YAMLParseError, YAMLWarning, prettifyError };
diff --git a/MistyCore/node_modules/yaml/browser/dist/index.js b/MistyCore/node_modules/yaml/browser/dist/index.js
new file mode 100644
index 0000000..96765af
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/index.js
@@ -0,0 +1,17 @@
+export { Composer } from './compose/composer.js';
+export { Document } from './doc/Document.js';
+export { Schema } from './schema/Schema.js';
+export { YAMLError, YAMLParseError, YAMLWarning } from './errors.js';
+export { Alias } from './nodes/Alias.js';
+export { isAlias, isCollection, isDocument, isMap, isNode, isPair, isScalar, isSeq } from './nodes/Node.js';
+export { Pair } from './nodes/Pair.js';
+export { Scalar } from './nodes/Scalar.js';
+export { YAMLMap } from './nodes/YAMLMap.js';
+export { YAMLSeq } from './nodes/YAMLSeq.js';
+import * as cst from './parse/cst.js';
+export { cst as CST };
+export { Lexer } from './parse/lexer.js';
+export { LineCounter } from './parse/line-counter.js';
+export { Parser } from './parse/parser.js';
+export { parse, parseAllDocuments, parseDocument, stringify } from './public-api.js';
+export { visit, visitAsync } from './visit.js';
diff --git a/MistyCore/node_modules/yaml/browser/dist/log.js b/MistyCore/node_modules/yaml/browser/dist/log.js
new file mode 100644
index 0000000..aa5ba56
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/log.js
@@ -0,0 +1,14 @@
+function debug(logLevel, ...messages) {
+ if (logLevel === 'debug')
+ console.log(...messages);
+}
+function warn(logLevel, warning) {
+ if (logLevel === 'debug' || logLevel === 'warn') {
+ if (typeof process !== 'undefined' && process.emitWarning)
+ process.emitWarning(warning);
+ else
+ console.warn(warning);
+ }
+}
+
+export { debug, warn };
diff --git a/MistyCore/node_modules/yaml/browser/dist/node_modules/tslib/tslib.es6.js b/MistyCore/node_modules/yaml/browser/dist/node_modules/tslib/tslib.es6.js
new file mode 100644
index 0000000..4964191
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/node_modules/tslib/tslib.es6.js
@@ -0,0 +1,164 @@
+/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */
+
+/* global Reflect, Promise */
+var extendStatics = function (d, b) {
+ extendStatics = Object.setPrototypeOf || {
+ __proto__: []
+ } instanceof Array && function (d, b) {
+ d.__proto__ = b;
+ } || function (d, b) {
+ for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
+ };
+
+ return extendStatics(d, b);
+};
+
+function __extends(d, b) {
+ if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
+ extendStatics(d, b);
+
+ function __() {
+ this.constructor = d;
+ }
+
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+}
+function __generator(thisArg, body) {
+ var _ = {
+ label: 0,
+ sent: function () {
+ if (t[0] & 1) throw t[1];
+ return t[1];
+ },
+ trys: [],
+ ops: []
+ },
+ f,
+ y,
+ t,
+ g;
+ return g = {
+ next: verb(0),
+ "throw": verb(1),
+ "return": verb(2)
+ }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
+ return this;
+ }), g;
+
+ function verb(n) {
+ return function (v) {
+ return step([n, v]);
+ };
+ }
+
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+
+ while (_) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+
+ switch (op[0]) {
+ case 0:
+ case 1:
+ t = op;
+ break;
+
+ case 4:
+ _.label++;
+ return {
+ value: op[1],
+ done: false
+ };
+
+ case 5:
+ _.label++;
+ y = op[1];
+ op = [0];
+ continue;
+
+ case 7:
+ op = _.ops.pop();
+
+ _.trys.pop();
+
+ continue;
+
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
+ _ = 0;
+ continue;
+ }
+
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
+ _.label = op[1];
+ break;
+ }
+
+ if (op[0] === 6 && _.label < t[1]) {
+ _.label = t[1];
+ t = op;
+ break;
+ }
+
+ if (t && _.label < t[2]) {
+ _.label = t[2];
+
+ _.ops.push(op);
+
+ break;
+ }
+
+ if (t[2]) _.ops.pop();
+
+ _.trys.pop();
+
+ continue;
+ }
+
+ op = body.call(thisArg, _);
+ } catch (e) {
+ op = [6, e];
+ y = 0;
+ } finally {
+ f = t = 0;
+ }
+
+ if (op[0] & 5) throw op[1];
+ return {
+ value: op[0] ? op[1] : void 0,
+ done: true
+ };
+ }
+}
+function __values(o) {
+ var s = typeof Symbol === "function" && Symbol.iterator,
+ m = s && o[s],
+ i = 0;
+ if (m) return m.call(o);
+ if (o && typeof o.length === "number") return {
+ next: function () {
+ if (o && i >= o.length) o = void 0;
+ return {
+ value: o && o[i++],
+ done: !o
+ };
+ }
+ };
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
+}
+
+export { __extends, __generator, __values };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/Alias.js b/MistyCore/node_modules/yaml/browser/dist/nodes/Alias.js
new file mode 100644
index 0000000..141b811
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/Alias.js
@@ -0,0 +1,94 @@
+import { anchorIsValid } from '../doc/anchors.js';
+import { visit } from '../visit.js';
+import { NodeBase, ALIAS, isAlias, isCollection, isPair } from './Node.js';
+
+class Alias extends NodeBase {
+ constructor(source) {
+ super(ALIAS);
+ this.source = source;
+ Object.defineProperty(this, 'tag', {
+ set() {
+ throw new Error('Alias nodes cannot have tags');
+ }
+ });
+ }
+ /**
+ * Resolve the value of this alias within `doc`, finding the last
+ * instance of the `source` anchor before this node.
+ */
+ resolve(doc) {
+ let found = undefined;
+ visit(doc, {
+ Node: (_key, node) => {
+ if (node === this)
+ return visit.BREAK;
+ if (node.anchor === this.source)
+ found = node;
+ }
+ });
+ return found;
+ }
+ toJSON(_arg, ctx) {
+ if (!ctx)
+ return { source: this.source };
+ const { anchors, doc, maxAliasCount } = ctx;
+ const source = this.resolve(doc);
+ if (!source) {
+ const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
+ throw new ReferenceError(msg);
+ }
+ const data = anchors.get(source);
+ /* istanbul ignore if */
+ if (!data || data.res === undefined) {
+ const msg = 'This should not happen: Alias anchor was not resolved?';
+ throw new ReferenceError(msg);
+ }
+ if (maxAliasCount >= 0) {
+ data.count += 1;
+ if (data.aliasCount === 0)
+ data.aliasCount = getAliasCount(doc, source, anchors);
+ if (data.count * data.aliasCount > maxAliasCount) {
+ const msg = 'Excessive alias count indicates a resource exhaustion attack';
+ throw new ReferenceError(msg);
+ }
+ }
+ return data.res;
+ }
+ toString(ctx, _onComment, _onChompKeep) {
+ const src = `*${this.source}`;
+ if (ctx) {
+ anchorIsValid(this.source);
+ if (ctx.options.verifyAliasOrder && !ctx.anchors.has(this.source)) {
+ const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
+ throw new Error(msg);
+ }
+ if (ctx.implicitKey)
+ return `${src} `;
+ }
+ return src;
+ }
+}
+function getAliasCount(doc, node, anchors) {
+ if (isAlias(node)) {
+ const source = node.resolve(doc);
+ const anchor = anchors && source && anchors.get(source);
+ return anchor ? anchor.count * anchor.aliasCount : 0;
+ }
+ else if (isCollection(node)) {
+ let count = 0;
+ for (const item of node.items) {
+ const c = getAliasCount(doc, item, anchors);
+ if (c > count)
+ count = c;
+ }
+ return count;
+ }
+ else if (isPair(node)) {
+ const kc = getAliasCount(doc, node.key, anchors);
+ const vc = getAliasCount(doc, node.value, anchors);
+ return Math.max(kc, vc);
+ }
+ return 1;
+}
+
+export { Alias };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/Collection.js b/MistyCore/node_modules/yaml/browser/dist/nodes/Collection.js
new file mode 100644
index 0000000..7498e86
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/Collection.js
@@ -0,0 +1,147 @@
+import { createNode } from '../doc/createNode.js';
+import { NodeBase, isNode, isPair, isCollection, isScalar } from './Node.js';
+
+function collectionFromPath(schema, path, value) {
+ let v = value;
+ for (let i = path.length - 1; i >= 0; --i) {
+ const k = path[i];
+ if (typeof k === 'number' && Number.isInteger(k) && k >= 0) {
+ const a = [];
+ a[k] = v;
+ v = a;
+ }
+ else {
+ v = new Map([[k, v]]);
+ }
+ }
+ return createNode(v, undefined, {
+ aliasDuplicateObjects: false,
+ keepUndefined: false,
+ onAnchor: () => {
+ throw new Error('This should not happen, please report a bug.');
+ },
+ schema,
+ sourceObjects: new Map()
+ });
+}
+// Type guard is intentionally a little wrong so as to be more useful,
+// as it does not cover untypable empty non-string iterables (e.g. []).
+const isEmptyPath = (path) => path == null ||
+ (typeof path === 'object' && !!path[Symbol.iterator]().next().done);
+class Collection extends NodeBase {
+ constructor(type, schema) {
+ super(type);
+ Object.defineProperty(this, 'schema', {
+ value: schema,
+ configurable: true,
+ enumerable: false,
+ writable: true
+ });
+ }
+ /**
+ * Create a copy of this collection.
+ *
+ * @param schema - If defined, overwrites the original's schema
+ */
+ clone(schema) {
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
+ if (schema)
+ copy.schema = schema;
+ copy.items = copy.items.map(it => isNode(it) || isPair(it) ? it.clone(schema) : it);
+ if (this.range)
+ copy.range = this.range.slice();
+ return copy;
+ }
+ /**
+ * Adds a value to the collection. For `!!map` and `!!omap` the value must
+ * be a Pair instance or a `{ key, value }` object, which may not have a key
+ * that already exists in the map.
+ */
+ addIn(path, value) {
+ if (isEmptyPath(path))
+ this.add(value);
+ else {
+ const [key, ...rest] = path;
+ const node = this.get(key, true);
+ if (isCollection(node))
+ node.addIn(rest, value);
+ else if (node === undefined && this.schema)
+ this.set(key, collectionFromPath(this.schema, rest, value));
+ else
+ throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
+ }
+ }
+ /**
+ * Removes a value from the collection.
+ * @returns `true` if the item was found and removed.
+ */
+ deleteIn(path) {
+ const [key, ...rest] = path;
+ if (rest.length === 0)
+ return this.delete(key);
+ const node = this.get(key, true);
+ if (isCollection(node))
+ return node.deleteIn(rest);
+ else
+ throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
+ }
+ /**
+ * Returns item at `key`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ getIn(path, keepScalar) {
+ const [key, ...rest] = path;
+ const node = this.get(key, true);
+ if (rest.length === 0)
+ return !keepScalar && isScalar(node) ? node.value : node;
+ else
+ return isCollection(node) ? node.getIn(rest, keepScalar) : undefined;
+ }
+ hasAllNullValues(allowScalar) {
+ return this.items.every(node => {
+ if (!isPair(node))
+ return false;
+ const n = node.value;
+ return (n == null ||
+ (allowScalar &&
+ isScalar(n) &&
+ n.value == null &&
+ !n.commentBefore &&
+ !n.comment &&
+ !n.tag));
+ });
+ }
+ /**
+ * Checks if the collection includes a value with the key `key`.
+ */
+ hasIn(path) {
+ const [key, ...rest] = path;
+ if (rest.length === 0)
+ return this.has(key);
+ const node = this.get(key, true);
+ return isCollection(node) ? node.hasIn(rest) : false;
+ }
+ /**
+ * Sets a value in this collection. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ setIn(path, value) {
+ const [key, ...rest] = path;
+ if (rest.length === 0) {
+ this.set(key, value);
+ }
+ else {
+ const node = this.get(key, true);
+ if (isCollection(node))
+ node.setIn(rest, value);
+ else if (node === undefined && this.schema)
+ this.set(key, collectionFromPath(this.schema, rest, value));
+ else
+ throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
+ }
+ }
+}
+Collection.maxFlowStringSingleLineLength = 60;
+
+export { Collection, collectionFromPath, isEmptyPath };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/Node.js b/MistyCore/node_modules/yaml/browser/dist/nodes/Node.js
new file mode 100644
index 0000000..718f363
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/Node.js
@@ -0,0 +1,48 @@
+const ALIAS = Symbol.for('yaml.alias');
+const DOC = Symbol.for('yaml.document');
+const MAP = Symbol.for('yaml.map');
+const PAIR = Symbol.for('yaml.pair');
+const SCALAR = Symbol.for('yaml.scalar');
+const SEQ = Symbol.for('yaml.seq');
+const NODE_TYPE = Symbol.for('yaml.node.type');
+const isAlias = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === ALIAS;
+const isDocument = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === DOC;
+const isMap = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === MAP;
+const isPair = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === PAIR;
+const isScalar = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SCALAR;
+const isSeq = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SEQ;
+function isCollection(node) {
+ if (node && typeof node === 'object')
+ switch (node[NODE_TYPE]) {
+ case MAP:
+ case SEQ:
+ return true;
+ }
+ return false;
+}
+function isNode(node) {
+ if (node && typeof node === 'object')
+ switch (node[NODE_TYPE]) {
+ case ALIAS:
+ case MAP:
+ case SCALAR:
+ case SEQ:
+ return true;
+ }
+ return false;
+}
+const hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor;
+class NodeBase {
+ constructor(type) {
+ Object.defineProperty(this, NODE_TYPE, { value: type });
+ }
+ /** Create a copy of this node. */
+ clone() {
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
+ if (this.range)
+ copy.range = this.range.slice();
+ return copy;
+ }
+}
+
+export { ALIAS, DOC, MAP, NODE_TYPE, NodeBase, PAIR, SCALAR, SEQ, hasAnchor, isAlias, isCollection, isDocument, isMap, isNode, isPair, isScalar, isSeq };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/Pair.js b/MistyCore/node_modules/yaml/browser/dist/nodes/Pair.js
new file mode 100644
index 0000000..5a628a2
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/Pair.js
@@ -0,0 +1,36 @@
+import { createNode } from '../doc/createNode.js';
+import { stringifyPair } from '../stringify/stringifyPair.js';
+import { addPairToJSMap } from './addPairToJSMap.js';
+import { NODE_TYPE, PAIR, isNode } from './Node.js';
+
+function createPair(key, value, ctx) {
+ const k = createNode(key, undefined, ctx);
+ const v = createNode(value, undefined, ctx);
+ return new Pair(k, v);
+}
+class Pair {
+ constructor(key, value = null) {
+ Object.defineProperty(this, NODE_TYPE, { value: PAIR });
+ this.key = key;
+ this.value = value;
+ }
+ clone(schema) {
+ let { key, value } = this;
+ if (isNode(key))
+ key = key.clone(schema);
+ if (isNode(value))
+ value = value.clone(schema);
+ return new Pair(key, value);
+ }
+ toJSON(_, ctx) {
+ const pair = ctx?.mapAsMap ? new Map() : {};
+ return addPairToJSMap(ctx, pair, this);
+ }
+ toString(ctx, onComment, onChompKeep) {
+ return ctx?.doc
+ ? stringifyPair(this, ctx, onComment, onChompKeep)
+ : JSON.stringify(this);
+ }
+}
+
+export { Pair, createPair };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/Scalar.js b/MistyCore/node_modules/yaml/browser/dist/nodes/Scalar.js
new file mode 100644
index 0000000..691283a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/Scalar.js
@@ -0,0 +1,23 @@
+import { NodeBase, SCALAR } from './Node.js';
+import { toJS } from './toJS.js';
+
+const isScalarValue = (value) => !value || (typeof value !== 'function' && typeof value !== 'object');
+class Scalar extends NodeBase {
+ constructor(value) {
+ super(SCALAR);
+ this.value = value;
+ }
+ toJSON(arg, ctx) {
+ return ctx?.keep ? this.value : toJS(this.value, arg, ctx);
+ }
+ toString() {
+ return String(this.value);
+ }
+}
+Scalar.BLOCK_FOLDED = 'BLOCK_FOLDED';
+Scalar.BLOCK_LITERAL = 'BLOCK_LITERAL';
+Scalar.PLAIN = 'PLAIN';
+Scalar.QUOTE_DOUBLE = 'QUOTE_DOUBLE';
+Scalar.QUOTE_SINGLE = 'QUOTE_SINGLE';
+
+export { Scalar, isScalarValue };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/YAMLMap.js b/MistyCore/node_modules/yaml/browser/dist/nodes/YAMLMap.js
new file mode 100644
index 0000000..0159dc5
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/YAMLMap.js
@@ -0,0 +1,116 @@
+import { stringifyCollection } from '../stringify/stringifyCollection.js';
+import { addPairToJSMap } from './addPairToJSMap.js';
+import { Collection } from './Collection.js';
+import { isPair, isScalar, MAP } from './Node.js';
+import { Pair } from './Pair.js';
+import { isScalarValue } from './Scalar.js';
+
+function findPair(items, key) {
+ const k = isScalar(key) ? key.value : key;
+ for (const it of items) {
+ if (isPair(it)) {
+ if (it.key === key || it.key === k)
+ return it;
+ if (isScalar(it.key) && it.key.value === k)
+ return it;
+ }
+ }
+ return undefined;
+}
+class YAMLMap extends Collection {
+ constructor(schema) {
+ super(MAP, schema);
+ this.items = [];
+ }
+ static get tagName() {
+ return 'tag:yaml.org,2002:map';
+ }
+ /**
+ * Adds a value to the collection.
+ *
+ * @param overwrite - If not set `true`, using a key that is already in the
+ * collection will throw. Otherwise, overwrites the previous value.
+ */
+ add(pair, overwrite) {
+ let _pair;
+ if (isPair(pair))
+ _pair = pair;
+ else if (!pair || typeof pair !== 'object' || !('key' in pair)) {
+ // In TypeScript, this never happens.
+ _pair = new Pair(pair, pair?.value);
+ }
+ else
+ _pair = new Pair(pair.key, pair.value);
+ const prev = findPair(this.items, _pair.key);
+ const sortEntries = this.schema?.sortMapEntries;
+ if (prev) {
+ if (!overwrite)
+ throw new Error(`Key ${_pair.key} already set`);
+ // For scalars, keep the old node & its comments and anchors
+ if (isScalar(prev.value) && isScalarValue(_pair.value))
+ prev.value.value = _pair.value;
+ else
+ prev.value = _pair.value;
+ }
+ else if (sortEntries) {
+ const i = this.items.findIndex(item => sortEntries(_pair, item) < 0);
+ if (i === -1)
+ this.items.push(_pair);
+ else
+ this.items.splice(i, 0, _pair);
+ }
+ else {
+ this.items.push(_pair);
+ }
+ }
+ delete(key) {
+ const it = findPair(this.items, key);
+ if (!it)
+ return false;
+ const del = this.items.splice(this.items.indexOf(it), 1);
+ return del.length > 0;
+ }
+ get(key, keepScalar) {
+ const it = findPair(this.items, key);
+ const node = it?.value;
+ return (!keepScalar && isScalar(node) ? node.value : node) ?? undefined;
+ }
+ has(key) {
+ return !!findPair(this.items, key);
+ }
+ set(key, value) {
+ this.add(new Pair(key, value), true);
+ }
+ /**
+ * @param ctx - Conversion context, originally set in Document#toJS()
+ * @param {Class} Type - If set, forces the returned collection type
+ * @returns Instance of Type, Map, or Object
+ */
+ toJSON(_, ctx, Type) {
+ const map = Type ? new Type() : ctx?.mapAsMap ? new Map() : {};
+ if (ctx?.onCreate)
+ ctx.onCreate(map);
+ for (const item of this.items)
+ addPairToJSMap(ctx, map, item);
+ return map;
+ }
+ toString(ctx, onComment, onChompKeep) {
+ if (!ctx)
+ return JSON.stringify(this);
+ for (const item of this.items) {
+ if (!isPair(item))
+ throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`);
+ }
+ if (!ctx.allNullValues && this.hasAllNullValues(false))
+ ctx = Object.assign({}, ctx, { allNullValues: true });
+ return stringifyCollection(this, ctx, {
+ blockItemPrefix: '',
+ flowChars: { start: '{', end: '}' },
+ itemIndent: ctx.indent || '',
+ onChompKeep,
+ onComment
+ });
+ }
+}
+
+export { YAMLMap, findPair };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/YAMLSeq.js b/MistyCore/node_modules/yaml/browser/dist/nodes/YAMLSeq.js
new file mode 100644
index 0000000..3243cb0
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/YAMLSeq.js
@@ -0,0 +1,97 @@
+import { stringifyCollection } from '../stringify/stringifyCollection.js';
+import { Collection } from './Collection.js';
+import { SEQ, isScalar } from './Node.js';
+import { isScalarValue } from './Scalar.js';
+import { toJS } from './toJS.js';
+
+class YAMLSeq extends Collection {
+ constructor(schema) {
+ super(SEQ, schema);
+ this.items = [];
+ }
+ static get tagName() {
+ return 'tag:yaml.org,2002:seq';
+ }
+ add(value) {
+ this.items.push(value);
+ }
+ /**
+ * Removes a value from the collection.
+ *
+ * `key` must contain a representation of an integer for this to succeed.
+ * It may be wrapped in a `Scalar`.
+ *
+ * @returns `true` if the item was found and removed.
+ */
+ delete(key) {
+ const idx = asItemIndex(key);
+ if (typeof idx !== 'number')
+ return false;
+ const del = this.items.splice(idx, 1);
+ return del.length > 0;
+ }
+ get(key, keepScalar) {
+ const idx = asItemIndex(key);
+ if (typeof idx !== 'number')
+ return undefined;
+ const it = this.items[idx];
+ return !keepScalar && isScalar(it) ? it.value : it;
+ }
+ /**
+ * Checks if the collection includes a value with the key `key`.
+ *
+ * `key` must contain a representation of an integer for this to succeed.
+ * It may be wrapped in a `Scalar`.
+ */
+ has(key) {
+ const idx = asItemIndex(key);
+ return typeof idx === 'number' && idx < this.items.length;
+ }
+ /**
+ * Sets a value in this collection. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ *
+ * If `key` does not contain a representation of an integer, this will throw.
+ * It may be wrapped in a `Scalar`.
+ */
+ set(key, value) {
+ const idx = asItemIndex(key);
+ if (typeof idx !== 'number')
+ throw new Error(`Expected a valid index, not ${key}.`);
+ const prev = this.items[idx];
+ if (isScalar(prev) && isScalarValue(value))
+ prev.value = value;
+ else
+ this.items[idx] = value;
+ }
+ toJSON(_, ctx) {
+ const seq = [];
+ if (ctx?.onCreate)
+ ctx.onCreate(seq);
+ let i = 0;
+ for (const item of this.items)
+ seq.push(toJS(item, String(i++), ctx));
+ return seq;
+ }
+ toString(ctx, onComment, onChompKeep) {
+ if (!ctx)
+ return JSON.stringify(this);
+ return stringifyCollection(this, ctx, {
+ blockItemPrefix: '- ',
+ flowChars: { start: '[', end: ']' },
+ itemIndent: (ctx.indent || '') + ' ',
+ onChompKeep,
+ onComment
+ });
+ }
+}
+function asItemIndex(key) {
+ let idx = isScalar(key) ? key.value : key;
+ if (idx && typeof idx === 'string')
+ idx = Number(idx);
+ return typeof idx === 'number' && Number.isInteger(idx) && idx >= 0
+ ? idx
+ : null;
+}
+
+export { YAMLSeq };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js b/MistyCore/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js
new file mode 100644
index 0000000..70deb43
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js
@@ -0,0 +1,104 @@
+import { warn } from '../log.js';
+import { createStringifyContext } from '../stringify/stringify.js';
+import { isAlias, isSeq, isScalar, isMap, isNode } from './Node.js';
+import { Scalar } from './Scalar.js';
+import { toJS } from './toJS.js';
+
+const MERGE_KEY = '<<';
+function addPairToJSMap(ctx, map, { key, value }) {
+ if (ctx?.doc.schema.merge && isMergeKey(key)) {
+ value = isAlias(value) ? value.resolve(ctx.doc) : value;
+ if (isSeq(value))
+ for (const it of value.items)
+ mergeToJSMap(ctx, map, it);
+ else if (Array.isArray(value))
+ for (const it of value)
+ mergeToJSMap(ctx, map, it);
+ else
+ mergeToJSMap(ctx, map, value);
+ }
+ else {
+ const jsKey = toJS(key, '', ctx);
+ if (map instanceof Map) {
+ map.set(jsKey, toJS(value, jsKey, ctx));
+ }
+ else if (map instanceof Set) {
+ map.add(jsKey);
+ }
+ else {
+ const stringKey = stringifyKey(key, jsKey, ctx);
+ const jsValue = toJS(value, stringKey, ctx);
+ if (stringKey in map)
+ Object.defineProperty(map, stringKey, {
+ value: jsValue,
+ writable: true,
+ enumerable: true,
+ configurable: true
+ });
+ else
+ map[stringKey] = jsValue;
+ }
+ }
+ return map;
+}
+const isMergeKey = (key) => key === MERGE_KEY ||
+ (isScalar(key) &&
+ key.value === MERGE_KEY &&
+ (!key.type || key.type === Scalar.PLAIN));
+// If the value associated with a merge key is a single mapping node, each of
+// its key/value pairs is inserted into the current mapping, unless the key
+// already exists in it. If the value associated with the merge key is a
+// sequence, then this sequence is expected to contain mapping nodes and each
+// of these nodes is merged in turn according to its order in the sequence.
+// Keys in mapping nodes earlier in the sequence override keys specified in
+// later mapping nodes. -- http://yaml.org/type/merge.html
+function mergeToJSMap(ctx, map, value) {
+ const source = ctx && isAlias(value) ? value.resolve(ctx.doc) : value;
+ if (!isMap(source))
+ throw new Error('Merge sources must be maps or map aliases');
+ const srcMap = source.toJSON(null, ctx, Map);
+ for (const [key, value] of srcMap) {
+ if (map instanceof Map) {
+ if (!map.has(key))
+ map.set(key, value);
+ }
+ else if (map instanceof Set) {
+ map.add(key);
+ }
+ else if (!Object.prototype.hasOwnProperty.call(map, key)) {
+ Object.defineProperty(map, key, {
+ value,
+ writable: true,
+ enumerable: true,
+ configurable: true
+ });
+ }
+ }
+ return map;
+}
+function stringifyKey(key, jsKey, ctx) {
+ if (jsKey === null)
+ return '';
+ if (typeof jsKey !== 'object')
+ return String(jsKey);
+ if (isNode(key) && ctx && ctx.doc) {
+ const strCtx = createStringifyContext(ctx.doc, {});
+ strCtx.anchors = new Set();
+ for (const node of ctx.anchors.keys())
+ strCtx.anchors.add(node.anchor);
+ strCtx.inFlow = true;
+ strCtx.inStringifyKey = true;
+ const strKey = key.toString(strCtx);
+ if (!ctx.mapKeyWarned) {
+ let jsonStr = JSON.stringify(strKey);
+ if (jsonStr.length > 40)
+ jsonStr = jsonStr.substring(0, 36) + '..."';
+ warn(ctx.doc.options.logLevel, `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use object keys.`);
+ ctx.mapKeyWarned = true;
+ }
+ return strKey;
+ }
+ return JSON.stringify(jsKey);
+}
+
+export { addPairToJSMap };
diff --git a/MistyCore/node_modules/yaml/browser/dist/nodes/toJS.js b/MistyCore/node_modules/yaml/browser/dist/nodes/toJS.js
new file mode 100644
index 0000000..a9f3681
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/nodes/toJS.js
@@ -0,0 +1,37 @@
+import { hasAnchor } from './Node.js';
+
+/**
+ * Recursively convert any node or its contents to native JavaScript
+ *
+ * @param value - The input value
+ * @param arg - If `value` defines a `toJSON()` method, use this
+ * as its first argument
+ * @param ctx - Conversion context, originally set in Document#toJS(). If
+ * `{ keep: true }` is not set, output should be suitable for JSON
+ * stringification.
+ */
+function toJS(value, arg, ctx) {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ if (Array.isArray(value))
+ return value.map((v, i) => toJS(v, String(i), ctx));
+ if (value && typeof value.toJSON === 'function') {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+ if (!ctx || !hasAnchor(value))
+ return value.toJSON(arg, ctx);
+ const data = { aliasCount: 0, count: 1, res: undefined };
+ ctx.anchors.set(value, data);
+ ctx.onCreate = res => {
+ data.res = res;
+ delete ctx.onCreate;
+ };
+ const res = value.toJSON(arg, ctx);
+ if (ctx.onCreate)
+ ctx.onCreate(res);
+ return res;
+ }
+ if (typeof value === 'bigint' && !ctx?.keep)
+ return Number(value);
+ return value;
+}
+
+export { toJS };
diff --git a/MistyCore/node_modules/yaml/browser/dist/parse/cst-scalar.js b/MistyCore/node_modules/yaml/browser/dist/parse/cst-scalar.js
new file mode 100644
index 0000000..d4def99
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/parse/cst-scalar.js
@@ -0,0 +1,214 @@
+import { resolveBlockScalar } from '../compose/resolve-block-scalar.js';
+import { resolveFlowScalar } from '../compose/resolve-flow-scalar.js';
+import { YAMLParseError } from '../errors.js';
+import { stringifyString } from '../stringify/stringifyString.js';
+
+function resolveAsScalar(token, strict = true, onError) {
+ if (token) {
+ const _onError = (pos, code, message) => {
+ const offset = typeof pos === 'number' ? pos : Array.isArray(pos) ? pos[0] : pos.offset;
+ if (onError)
+ onError(offset, code, message);
+ else
+ throw new YAMLParseError([offset, offset + 1], code, message);
+ };
+ switch (token.type) {
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ return resolveFlowScalar(token, strict, _onError);
+ case 'block-scalar':
+ return resolveBlockScalar(token, strict, _onError);
+ }
+ }
+ return null;
+}
+/**
+ * Create a new scalar token with `value`
+ *
+ * Values that represent an actual string but may be parsed as a different type should use a `type` other than `'PLAIN'`,
+ * as this function does not support any schema operations and won't check for such conflicts.
+ *
+ * @param value The string representation of the value, which will have its content properly indented.
+ * @param context.end Comments and whitespace after the end of the value, or after the block scalar header. If undefined, a newline will be added.
+ * @param context.implicitKey Being within an implicit key may affect the resolved type of the token's value.
+ * @param context.indent The indent level of the token.
+ * @param context.inFlow Is this scalar within a flow collection? This may affect the resolved type of the token's value.
+ * @param context.offset The offset position of the token.
+ * @param context.type The preferred type of the scalar token. If undefined, the previous type of the `token` will be used, defaulting to `'PLAIN'`.
+ */
+function createScalarToken(value, context) {
+ const { implicitKey = false, indent, inFlow = false, offset = -1, type = 'PLAIN' } = context;
+ const source = stringifyString({ type, value }, {
+ implicitKey,
+ indent: indent > 0 ? ' '.repeat(indent) : '',
+ inFlow,
+ options: { blockQuote: true, lineWidth: -1 }
+ });
+ const end = context.end ?? [
+ { type: 'newline', offset: -1, indent, source: '\n' }
+ ];
+ switch (source[0]) {
+ case '|':
+ case '>': {
+ const he = source.indexOf('\n');
+ const head = source.substring(0, he);
+ const body = source.substring(he + 1) + '\n';
+ const props = [
+ { type: 'block-scalar-header', offset, indent, source: head }
+ ];
+ if (!addEndtoBlockProps(props, end))
+ props.push({ type: 'newline', offset: -1, indent, source: '\n' });
+ return { type: 'block-scalar', offset, indent, props, source: body };
+ }
+ case '"':
+ return { type: 'double-quoted-scalar', offset, indent, source, end };
+ case "'":
+ return { type: 'single-quoted-scalar', offset, indent, source, end };
+ default:
+ return { type: 'scalar', offset, indent, source, end };
+ }
+}
+/**
+ * Set the value of `token` to the given string `value`, overwriting any previous contents and type that it may have.
+ *
+ * Best efforts are made to retain any comments previously associated with the `token`,
+ * though all contents within a collection's `items` will be overwritten.
+ *
+ * Values that represent an actual string but may be parsed as a different type should use a `type` other than `'PLAIN'`,
+ * as this function does not support any schema operations and won't check for such conflicts.
+ *
+ * @param token Any token. If it does not include an `indent` value, the value will be stringified as if it were an implicit key.
+ * @param value The string representation of the value, which will have its content properly indented.
+ * @param context.afterKey In most cases, values after a key should have an additional level of indentation.
+ * @param context.implicitKey Being within an implicit key may affect the resolved type of the token's value.
+ * @param context.inFlow Being within a flow collection may affect the resolved type of the token's value.
+ * @param context.type The preferred type of the scalar token. If undefined, the previous type of the `token` will be used, defaulting to `'PLAIN'`.
+ */
+function setScalarValue(token, value, context = {}) {
+ let { afterKey = false, implicitKey = false, inFlow = false, type } = context;
+ let indent = 'indent' in token ? token.indent : null;
+ if (afterKey && typeof indent === 'number')
+ indent += 2;
+ if (!type)
+ switch (token.type) {
+ case 'single-quoted-scalar':
+ type = 'QUOTE_SINGLE';
+ break;
+ case 'double-quoted-scalar':
+ type = 'QUOTE_DOUBLE';
+ break;
+ case 'block-scalar': {
+ const header = token.props[0];
+ if (header.type !== 'block-scalar-header')
+ throw new Error('Invalid block scalar header');
+ type = header.source[0] === '>' ? 'BLOCK_FOLDED' : 'BLOCK_LITERAL';
+ break;
+ }
+ default:
+ type = 'PLAIN';
+ }
+ const source = stringifyString({ type, value }, {
+ implicitKey: implicitKey || indent === null,
+ indent: indent !== null && indent > 0 ? ' '.repeat(indent) : '',
+ inFlow,
+ options: { blockQuote: true, lineWidth: -1 }
+ });
+ switch (source[0]) {
+ case '|':
+ case '>':
+ setBlockScalarValue(token, source);
+ break;
+ case '"':
+ setFlowScalarValue(token, source, 'double-quoted-scalar');
+ break;
+ case "'":
+ setFlowScalarValue(token, source, 'single-quoted-scalar');
+ break;
+ default:
+ setFlowScalarValue(token, source, 'scalar');
+ }
+}
+function setBlockScalarValue(token, source) {
+ const he = source.indexOf('\n');
+ const head = source.substring(0, he);
+ const body = source.substring(he + 1) + '\n';
+ if (token.type === 'block-scalar') {
+ const header = token.props[0];
+ if (header.type !== 'block-scalar-header')
+ throw new Error('Invalid block scalar header');
+ header.source = head;
+ token.source = body;
+ }
+ else {
+ const { offset } = token;
+ const indent = 'indent' in token ? token.indent : -1;
+ const props = [
+ { type: 'block-scalar-header', offset, indent, source: head }
+ ];
+ if (!addEndtoBlockProps(props, 'end' in token ? token.end : undefined))
+ props.push({ type: 'newline', offset: -1, indent, source: '\n' });
+ for (const key of Object.keys(token))
+ if (key !== 'type' && key !== 'offset')
+ delete token[key];
+ Object.assign(token, { type: 'block-scalar', indent, props, source: body });
+ }
+}
+/** @returns `true` if last token is a newline */
+function addEndtoBlockProps(props, end) {
+ if (end)
+ for (const st of end)
+ switch (st.type) {
+ case 'space':
+ case 'comment':
+ props.push(st);
+ break;
+ case 'newline':
+ props.push(st);
+ return true;
+ }
+ return false;
+}
+function setFlowScalarValue(token, source, type) {
+ switch (token.type) {
+ case 'scalar':
+ case 'double-quoted-scalar':
+ case 'single-quoted-scalar':
+ token.type = type;
+ token.source = source;
+ break;
+ case 'block-scalar': {
+ const end = token.props.slice(1);
+ let oa = source.length;
+ if (token.props[0].type === 'block-scalar-header')
+ oa -= token.props[0].source.length;
+ for (const tok of end)
+ tok.offset += oa;
+ delete token.props;
+ Object.assign(token, { type, source, end });
+ break;
+ }
+ case 'block-map':
+ case 'block-seq': {
+ const offset = token.offset + source.length;
+ const nl = { type: 'newline', offset, indent: token.indent, source: '\n' };
+ delete token.items;
+ Object.assign(token, { type, source, end: [nl] });
+ break;
+ }
+ default: {
+ const indent = 'indent' in token ? token.indent : -1;
+ const end = 'end' in token && Array.isArray(token.end)
+ ? token.end.filter(st => st.type === 'space' ||
+ st.type === 'comment' ||
+ st.type === 'newline')
+ : [];
+ for (const key of Object.keys(token))
+ if (key !== 'type' && key !== 'offset')
+ delete token[key];
+ Object.assign(token, { type, indent, source, end });
+ }
+ }
+}
+
+export { createScalarToken, resolveAsScalar, setScalarValue };
diff --git a/MistyCore/node_modules/yaml/browser/dist/parse/cst-stringify.js b/MistyCore/node_modules/yaml/browser/dist/parse/cst-stringify.js
new file mode 100644
index 0000000..d6ab58c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/parse/cst-stringify.js
@@ -0,0 +1,61 @@
+/**
+ * Stringify a CST document, token, or collection item
+ *
+ * Fair warning: This applies no validation whatsoever, and
+ * simply concatenates the sources in their logical order.
+ */
+const stringify = (cst) => 'type' in cst ? stringifyToken(cst) : stringifyItem(cst);
+function stringifyToken(token) {
+ switch (token.type) {
+ case 'block-scalar': {
+ let res = '';
+ for (const tok of token.props)
+ res += stringifyToken(tok);
+ return res + token.source;
+ }
+ case 'block-map':
+ case 'block-seq': {
+ let res = '';
+ for (const item of token.items)
+ res += stringifyItem(item);
+ return res;
+ }
+ case 'flow-collection': {
+ let res = token.start.source;
+ for (const item of token.items)
+ res += stringifyItem(item);
+ for (const st of token.end)
+ res += st.source;
+ return res;
+ }
+ case 'document': {
+ let res = stringifyItem(token);
+ if (token.end)
+ for (const st of token.end)
+ res += st.source;
+ return res;
+ }
+ default: {
+ let res = token.source;
+ if ('end' in token && token.end)
+ for (const st of token.end)
+ res += st.source;
+ return res;
+ }
+ }
+}
+function stringifyItem({ start, key, sep, value }) {
+ let res = '';
+ for (const st of start)
+ res += st.source;
+ if (key)
+ res += stringifyToken(key);
+ if (sep)
+ for (const st of sep)
+ res += st.source;
+ if (value)
+ res += stringifyToken(value);
+ return res;
+}
+
+export { stringify };
diff --git a/MistyCore/node_modules/yaml/browser/dist/parse/cst-visit.js b/MistyCore/node_modules/yaml/browser/dist/parse/cst-visit.js
new file mode 100644
index 0000000..deca086
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/parse/cst-visit.js
@@ -0,0 +1,97 @@
+const BREAK = Symbol('break visit');
+const SKIP = Symbol('skip children');
+const REMOVE = Symbol('remove item');
+/**
+ * Apply a visitor to a CST document or item.
+ *
+ * Walks through the tree (depth-first) starting from the root, calling a
+ * `visitor` function with two arguments when entering each item:
+ * - `item`: The current item, which included the following members:
+ * - `start: SourceToken[]` – Source tokens before the key or value,
+ * possibly including its anchor or tag.
+ * - `key?: Token | null` – Set for pair values. May then be `null`, if
+ * the key before the `:` separator is empty.
+ * - `sep?: SourceToken[]` – Source tokens between the key and the value,
+ * which should include the `:` map value indicator if `value` is set.
+ * - `value?: Token` – The value of a sequence item, or of a map pair.
+ * - `path`: The steps from the root to the current node, as an array of
+ * `['key' | 'value', number]` tuples.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this token, continue with
+ * next sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current item, then continue with the next one
+ * - `number`: Set the index of the next step. This is useful especially if
+ * the index of the current token has changed.
+ * - `function`: Define the next visitor for this item. After the original
+ * visitor is called on item entry, next visitors are called after handling
+ * a non-empty `key` and when exiting the item.
+ */
+function visit(cst, visitor) {
+ if ('type' in cst && cst.type === 'document')
+ cst = { start: cst.start, value: cst.value };
+ _visit(Object.freeze([]), cst, visitor);
+}
+// Without the `as symbol` casts, TS declares these in the `visit`
+// namespace using `var`, but then complains about that because
+// `unique symbol` must be `const`.
+/** Terminate visit traversal completely */
+visit.BREAK = BREAK;
+/** Do not visit the children of the current item */
+visit.SKIP = SKIP;
+/** Remove the current item */
+visit.REMOVE = REMOVE;
+/** Find the item at `path` from `cst` as the root */
+visit.itemAtPath = (cst, path) => {
+ let item = cst;
+ for (const [field, index] of path) {
+ const tok = item?.[field];
+ if (tok && 'items' in tok) {
+ item = tok.items[index];
+ }
+ else
+ return undefined;
+ }
+ return item;
+};
+/**
+ * Get the immediate parent collection of the item at `path` from `cst` as the root.
+ *
+ * Throws an error if the collection is not found, which should never happen if the item itself exists.
+ */
+visit.parentCollection = (cst, path) => {
+ const parent = visit.itemAtPath(cst, path.slice(0, -1));
+ const field = path[path.length - 1][0];
+ const coll = parent?.[field];
+ if (coll && 'items' in coll)
+ return coll;
+ throw new Error('Parent collection not found');
+};
+function _visit(path, item, visitor) {
+ let ctrl = visitor(item, path);
+ if (typeof ctrl === 'symbol')
+ return ctrl;
+ for (const field of ['key', 'value']) {
+ const token = item[field];
+ if (token && 'items' in token) {
+ for (let i = 0; i < token.items.length; ++i) {
+ const ci = _visit(Object.freeze(path.concat([[field, i]])), token.items[i], visitor);
+ if (typeof ci === 'number')
+ i = ci - 1;
+ else if (ci === BREAK)
+ return BREAK;
+ else if (ci === REMOVE) {
+ token.items.splice(i, 1);
+ i -= 1;
+ }
+ }
+ if (typeof ctrl === 'function' && field === 'key')
+ ctrl = ctrl(item, path);
+ }
+ }
+ return typeof ctrl === 'function' ? ctrl(item, path) : ctrl;
+}
+
+export { visit };
diff --git a/MistyCore/node_modules/yaml/browser/dist/parse/cst.js b/MistyCore/node_modules/yaml/browser/dist/parse/cst.js
new file mode 100644
index 0000000..8bb2f4a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/parse/cst.js
@@ -0,0 +1,98 @@
+export { createScalarToken, resolveAsScalar, setScalarValue } from './cst-scalar.js';
+export { stringify } from './cst-stringify.js';
+export { visit } from './cst-visit.js';
+
+/** The byte order mark */
+const BOM = '\u{FEFF}';
+/** Start of doc-mode */
+const DOCUMENT = '\x02'; // C0: Start of Text
+/** Unexpected end of flow-mode */
+const FLOW_END = '\x18'; // C0: Cancel
+/** Next token is a scalar value */
+const SCALAR = '\x1f'; // C0: Unit Separator
+/** @returns `true` if `token` is a flow or block collection */
+const isCollection = (token) => !!token && 'items' in token;
+/** @returns `true` if `token` is a flow or block scalar; not an alias */
+const isScalar = (token) => !!token &&
+ (token.type === 'scalar' ||
+ token.type === 'single-quoted-scalar' ||
+ token.type === 'double-quoted-scalar' ||
+ token.type === 'block-scalar');
+/* istanbul ignore next */
+/** Get a printable representation of a lexer token */
+function prettyToken(token) {
+ switch (token) {
+ case BOM:
+ return '<BOM>';
+ case DOCUMENT:
+ return '<DOC>';
+ case FLOW_END:
+ return '<FLOW_END>';
+ case SCALAR:
+ return '<SCALAR>';
+ default:
+ return JSON.stringify(token);
+ }
+}
+/** Identify the type of a lexer token. May return `null` for unknown tokens. */
+function tokenType(source) {
+ switch (source) {
+ case BOM:
+ return 'byte-order-mark';
+ case DOCUMENT:
+ return 'doc-mode';
+ case FLOW_END:
+ return 'flow-error-end';
+ case SCALAR:
+ return 'scalar';
+ case '---':
+ return 'doc-start';
+ case '...':
+ return 'doc-end';
+ case '':
+ case '\n':
+ case '\r\n':
+ return 'newline';
+ case '-':
+ return 'seq-item-ind';
+ case '?':
+ return 'explicit-key-ind';
+ case ':':
+ return 'map-value-ind';
+ case '{':
+ return 'flow-map-start';
+ case '}':
+ return 'flow-map-end';
+ case '[':
+ return 'flow-seq-start';
+ case ']':
+ return 'flow-seq-end';
+ case ',':
+ return 'comma';
+ }
+ switch (source[0]) {
+ case ' ':
+ case '\t':
+ return 'space';
+ case '#':
+ return 'comment';
+ case '%':
+ return 'directive-line';
+ case '*':
+ return 'alias';
+ case '&':
+ return 'anchor';
+ case '!':
+ return 'tag';
+ case "'":
+ return 'single-quoted-scalar';
+ case '"':
+ return 'double-quoted-scalar';
+ case '|':
+ case '>':
+ return 'block-scalar-header';
+ }
+ return null;
+}
+
+export { BOM, DOCUMENT, FLOW_END, SCALAR, isCollection, isScalar, prettyToken, tokenType };
diff --git a/MistyCore/node_modules/yaml/browser/dist/parse/lexer.js b/MistyCore/node_modules/yaml/browser/dist/parse/lexer.js
new file mode 100644
index 0000000..20fe13c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/parse/lexer.js
@@ -0,0 +1,701 @@
+import { BOM, DOCUMENT, FLOW_END, SCALAR } from './cst.js';
+
+/*
+START -> stream
+
+stream
+ directive -> line-end -> stream
+ indent + line-end -> stream
+ [else] -> line-start
+
+line-end
+ comment -> line-end
+ newline -> .
+ input-end -> END
+
+line-start
+ doc-start -> doc
+ doc-end -> stream
+ [else] -> indent -> block-start
+
+block-start
+ seq-item-start -> block-start
+ explicit-key-start -> block-start
+ map-value-start -> block-start
+ [else] -> doc
+
+doc
+ line-end -> line-start
+ spaces -> doc
+ anchor -> doc
+ tag -> doc
+ flow-start -> flow -> doc
+ flow-end -> error -> doc
+ seq-item-start -> error -> doc
+ explicit-key-start -> error -> doc
+ map-value-start -> doc
+ alias -> doc
+ quote-start -> quoted-scalar -> doc
+ block-scalar-header -> line-end -> block-scalar(min) -> line-start
+ [else] -> plain-scalar(false, min) -> doc
+
+flow
+ line-end -> flow
+ spaces -> flow
+ anchor -> flow
+ tag -> flow
+ flow-start -> flow -> flow
+ flow-end -> .
+ seq-item-start -> error -> flow
+ explicit-key-start -> flow
+ map-value-start -> flow
+ alias -> flow
+ quote-start -> quoted-scalar -> flow
+ comma -> flow
+ [else] -> plain-scalar(true, 0) -> flow
+
+quoted-scalar
+ quote-end -> .
+ [else] -> quoted-scalar
+
+block-scalar(min)
+ newline + peek(indent < min) -> .
+ [else] -> block-scalar(min)
+
+plain-scalar(is-flow, min)
+ scalar-end(is-flow) -> .
+ peek(newline + (indent < min)) -> .
+ [else] -> plain-scalar(min)
+*/
+function isEmpty(ch) {
+ switch (ch) {
+ case undefined:
+ case ' ':
+ case '\n':
+ case '\r':
+ case '\t':
+ return true;
+ default:
+ return false;
+ }
+}
+const hexDigits = '0123456789ABCDEFabcdef'.split('');
+const tagChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()".split('');
+const invalidFlowScalarChars = ',[]{}'.split('');
+const invalidAnchorChars = ' ,[]{}\n\r\t'.split('');
+const isNotAnchorChar = (ch) => !ch || invalidAnchorChars.includes(ch);
+/**
+ * Splits an input string into lexical tokens, i.e. smaller strings that are
+ * easily identifiable by `tokens.tokenType()`.
+ *
+ * Lexing starts always in a "stream" context. Incomplete input may be buffered
+ * until a complete token can be emitted.
+ *
+ * In addition to slices of the original input, the following control characters
+ * may also be emitted:
+ *
+ * - `\x02` (Start of Text): A document starts with the next token
+ * - `\x18` (Cancel): Unexpected end of flow-mode (indicates an error)
+ * - `\x1f` (Unit Separator): Next token is a scalar value
+ * - `\u{FEFF}` (Byte order mark): Emitted separately outside documents
+ */
+class Lexer {
+ constructor() {
+ /**
+ * Flag indicating whether the end of the current buffer marks the end of
+ * all input
+ */
+ this.atEnd = false;
+ /**
+ * Explicit indent set in block scalar header, as an offset from the current
+ * minimum indent, so e.g. set to 1 from a header `|2+`. Set to -1 if not
+ * explicitly set.
+ */
+ this.blockScalarIndent = -1;
+ /**
+ * Block scalars that include a + (keep) chomping indicator in their header
+ * include trailing empty lines, which are otherwise excluded from the
+ * scalar's contents.
+ */
+ this.blockScalarKeep = false;
+ /** Current input */
+ this.buffer = '';
+ /**
+ * Flag noting whether the map value indicator : can immediately follow this
+ * node within a flow context.
+ */
+ this.flowKey = false;
+ /** Count of surrounding flow collection levels. */
+ this.flowLevel = 0;
+ /**
+ * Minimum level of indentation required for next lines to be parsed as a
+ * part of the current scalar value.
+ */
+ this.indentNext = 0;
+ /** Indentation level of the current line. */
+ this.indentValue = 0;
+ /** Position of the next \n character. */
+ this.lineEndPos = null;
+ /** Stores the state of the lexer if reaching the end of incpomplete input */
+ this.next = null;
+ /** A pointer to `buffer`; the current position of the lexer. */
+ this.pos = 0;
+ }
+ /**
+ * Generate YAML tokens from the `source` string. If `incomplete`,
+ * a part of the last line may be left as a buffer for the next call.
+ *
+ * @returns A generator of lexical tokens
+ */
+ *lex(source, incomplete = false) {
+ if (source) {
+ this.buffer = this.buffer ? this.buffer + source : source;
+ this.lineEndPos = null;
+ }
+ this.atEnd = !incomplete;
+ let next = this.next ?? 'stream';
+ while (next && (incomplete || this.hasChars(1)))
+ next = yield* this.parseNext(next);
+ }
+ atLineEnd() {
+ let i = this.pos;
+ let ch = this.buffer[i];
+ while (ch === ' ' || ch === '\t')
+ ch = this.buffer[++i];
+ if (!ch || ch === '#' || ch === '\n')
+ return true;
+ if (ch === '\r')
+ return this.buffer[i + 1] === '\n';
+ return false;
+ }
+ charAt(n) {
+ return this.buffer[this.pos + n];
+ }
+ continueScalar(offset) {
+ let ch = this.buffer[offset];
+ if (this.indentNext > 0) {
+ let indent = 0;
+ while (ch === ' ')
+ ch = this.buffer[++indent + offset];
+ if (ch === '\r') {
+ const next = this.buffer[indent + offset + 1];
+ if (next === '\n' || (!next && !this.atEnd))
+ return offset + indent + 1;
+ }
+ return ch === '\n' || indent >= this.indentNext || (!ch && !this.atEnd)
+ ? offset + indent
+ : -1;
+ }
+ if (ch === '-' || ch === '.') {
+ const dt = this.buffer.substr(offset, 3);
+ if ((dt === '---' || dt === '...') && isEmpty(this.buffer[offset + 3]))
+ return -1;
+ }
+ return offset;
+ }
+ getLine() {
+ let end = this.lineEndPos;
+ if (typeof end !== 'number' || (end !== -1 && end < this.pos)) {
+ end = this.buffer.indexOf('\n', this.pos);
+ this.lineEndPos = end;
+ }
+ if (end === -1)
+ return this.atEnd ? this.buffer.substring(this.pos) : null;
+ if (this.buffer[end - 1] === '\r')
+ end -= 1;
+ return this.buffer.substring(this.pos, end);
+ }
+ hasChars(n) {
+ return this.pos + n <= this.buffer.length;
+ }
+ setNext(state) {
+ this.buffer = this.buffer.substring(this.pos);
+ this.pos = 0;
+ this.lineEndPos = null;
+ this.next = state;
+ return null;
+ }
+ peek(n) {
+ return this.buffer.substr(this.pos, n);
+ }
+ *parseNext(next) {
+ switch (next) {
+ case 'stream':
+ return yield* this.parseStream();
+ case 'line-start':
+ return yield* this.parseLineStart();
+ case 'block-start':
+ return yield* this.parseBlockStart();
+ case 'doc':
+ return yield* this.parseDocument();
+ case 'flow':
+ return yield* this.parseFlowCollection();
+ case 'quoted-scalar':
+ return yield* this.parseQuotedScalar();
+ case 'block-scalar':
+ return yield* this.parseBlockScalar();
+ case 'plain-scalar':
+ return yield* this.parsePlainScalar();
+ }
+ }
+ *parseStream() {
+ let line = this.getLine();
+ if (line === null)
+ return this.setNext('stream');
+ if (line[0] === BOM) {
+ yield* this.pushCount(1);
+ line = line.substring(1);
+ }
+ if (line[0] === '%') {
+ let dirEnd = line.length;
+ const cs = line.indexOf('#');
+ if (cs !== -1) {
+ const ch = line[cs - 1];
+ if (ch === ' ' || ch === '\t')
+ dirEnd = cs - 1;
+ }
+ while (true) {
+ const ch = line[dirEnd - 1];
+ if (ch === ' ' || ch === '\t')
+ dirEnd -= 1;
+ else
+ break;
+ }
+ const n = (yield* this.pushCount(dirEnd)) + (yield* this.pushSpaces(true));
+ yield* this.pushCount(line.length - n); // possible comment
+ this.pushNewline();
+ return 'stream';
+ }
+ if (this.atLineEnd()) {
+ const sp = yield* this.pushSpaces(true);
+ yield* this.pushCount(line.length - sp);
+ yield* this.pushNewline();
+ return 'stream';
+ }
+ yield DOCUMENT;
+ return yield* this.parseLineStart();
+ }
+ *parseLineStart() {
+ const ch = this.charAt(0);
+ if (!ch && !this.atEnd)
+ return this.setNext('line-start');
+ if (ch === '-' || ch === '.') {
+ if (!this.atEnd && !this.hasChars(4))
+ return this.setNext('line-start');
+ const s = this.peek(3);
+ if (s === '---' && isEmpty(this.charAt(3))) {
+ yield* this.pushCount(3);
+ this.indentValue = 0;
+ this.indentNext = 0;
+ return 'doc';
+ }
+ else if (s === '...' && isEmpty(this.charAt(3))) {
+ yield* this.pushCount(3);
+ return 'stream';
+ }
+ }
+ this.indentValue = yield* this.pushSpaces(false);
+ if (this.indentNext > this.indentValue && !isEmpty(this.charAt(1)))
+ this.indentNext = this.indentValue;
+ return yield* this.parseBlockStart();
+ }
+ *parseBlockStart() {
+ const [ch0, ch1] = this.peek(2);
+ if (!ch1 && !this.atEnd)
+ return this.setNext('block-start');
+ if ((ch0 === '-' || ch0 === '?' || ch0 === ':') && isEmpty(ch1)) {
+ const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
+ this.indentNext = this.indentValue + 1;
+ this.indentValue += n;
+ return yield* this.parseBlockStart();
+ }
+ return 'doc';
+ }
+ *parseDocument() {
+ yield* this.pushSpaces(true);
+ const line = this.getLine();
+ if (line === null)
+ return this.setNext('doc');
+ let n = yield* this.pushIndicators();
+ switch (line[n]) {
+ case '#':
+ yield* this.pushCount(line.length - n);
+ // fallthrough
+ case undefined:
+ yield* this.pushNewline();
+ return yield* this.parseLineStart();
+ case '{':
+ case '[':
+ yield* this.pushCount(1);
+ this.flowKey = false;
+ this.flowLevel = 1;
+ return 'flow';
+ case '}':
+ case ']':
+ // this is an error
+ yield* this.pushCount(1);
+ return 'doc';
+ case '*':
+ yield* this.pushUntil(isNotAnchorChar);
+ return 'doc';
+ case '"':
+ case "'":
+ return yield* this.parseQuotedScalar();
+ case '|':
+ case '>':
+ n += yield* this.parseBlockScalarHeader();
+ n += yield* this.pushSpaces(true);
+ yield* this.pushCount(line.length - n);
+ yield* this.pushNewline();
+ return yield* this.parseBlockScalar();
+ default:
+ return yield* this.parsePlainScalar();
+ }
+ }
+ *parseFlowCollection() {
+ let nl, sp;
+ let indent = -1;
+ do {
+ nl = yield* this.pushNewline();
+ if (nl > 0) {
+ sp = yield* this.pushSpaces(false);
+ this.indentValue = indent = sp;
+ }
+ else {
+ sp = 0;
+ }
+ sp += yield* this.pushSpaces(true);
+ } while (nl + sp > 0);
+ const line = this.getLine();
+ if (line === null)
+ return this.setNext('flow');
+ if ((indent !== -1 && indent < this.indentNext && line[0] !== '#') ||
+ (indent === 0 &&
+ (line.startsWith('---') || line.startsWith('...')) &&
+ isEmpty(line[3]))) {
+ // Allowing for the terminal ] or } at the same (rather than greater)
+ // indent level as the initial [ or { is technically invalid, but
+ // failing here would be surprising to users.
+ const atFlowEndMarker = indent === this.indentNext - 1 &&
+ this.flowLevel === 1 &&
+ (line[0] === ']' || line[0] === '}');
+ if (!atFlowEndMarker) {
+ // this is an error
+ this.flowLevel = 0;
+ yield FLOW_END;
+ return yield* this.parseLineStart();
+ }
+ }
+ let n = 0;
+ while (line[n] === ',') {
+ n += yield* this.pushCount(1);
+ n += yield* this.pushSpaces(true);
+ this.flowKey = false;
+ }
+ n += yield* this.pushIndicators();
+ switch (line[n]) {
+ case undefined:
+ return 'flow';
+ case '#':
+ yield* this.pushCount(line.length - n);
+ return 'flow';
+ case '{':
+ case '[':
+ yield* this.pushCount(1);
+ this.flowKey = false;
+ this.flowLevel += 1;
+ return 'flow';
+ case '}':
+ case ']':
+ yield* this.pushCount(1);
+ this.flowKey = true;
+ this.flowLevel -= 1;
+ return this.flowLevel ? 'flow' : 'doc';
+ case '*':
+ yield* this.pushUntil(isNotAnchorChar);
+ return 'flow';
+ case '"':
+ case "'":
+ this.flowKey = true;
+ return yield* this.parseQuotedScalar();
+ case ':': {
+ const next = this.charAt(1);
+ if (this.flowKey || isEmpty(next) || next === ',') {
+ this.flowKey = false;
+ yield* this.pushCount(1);
+ yield* this.pushSpaces(true);
+ return 'flow';
+ }
+ }
+ // fallthrough
+ default:
+ this.flowKey = false;
+ return yield* this.parsePlainScalar();
+ }
+ }
+ *parseQuotedScalar() {
+ const quote = this.charAt(0);
+ let end = this.buffer.indexOf(quote, this.pos + 1);
+ if (quote === "'") {
+ while (end !== -1 && this.buffer[end + 1] === "'")
+ end = this.buffer.indexOf("'", end + 2);
+ }
+ else {
+ // double-quote
+ while (end !== -1) {
+ let n = 0;
+ while (this.buffer[end - 1 - n] === '\\')
+ n += 1;
+ if (n % 2 === 0)
+ break;
+ end = this.buffer.indexOf('"', end + 1);
+ }
+ }
+ // Only looking for newlines within the quotes
+ const qb = this.buffer.substring(0, end);
+ let nl = qb.indexOf('\n', this.pos);
+ if (nl !== -1) {
+ while (nl !== -1) {
+ const cs = this.continueScalar(nl + 1);
+ if (cs === -1)
+ break;
+ nl = qb.indexOf('\n', cs);
+ }
+ if (nl !== -1) {
+ // this is an error caused by an unexpected unindent
+ end = nl - (qb[nl - 1] === '\r' ? 2 : 1);
+ }
+ }
+ if (end === -1) {
+ if (!this.atEnd)
+ return this.setNext('quoted-scalar');
+ end = this.buffer.length;
+ }
+ yield* this.pushToIndex(end + 1, false);
+ return this.flowLevel ? 'flow' : 'doc';
+ }
+ *parseBlockScalarHeader() {
+ this.blockScalarIndent = -1;
+ this.blockScalarKeep = false;
+ let i = this.pos;
+ while (true) {
+ const ch = this.buffer[++i];
+ if (ch === '+')
+ this.blockScalarKeep = true;
+ else if (ch > '0' && ch <= '9')
+ this.blockScalarIndent = Number(ch) - 1;
+ else if (ch !== '-')
+ break;
+ }
+ return yield* this.pushUntil(ch => isEmpty(ch) || ch === '#');
+ }
+ *parseBlockScalar() {
+ let nl = this.pos - 1; // may be -1 if this.pos === 0
+ let indent = 0;
+ let ch;
+ loop: for (let i = this.pos; (ch = this.buffer[i]); ++i) {
+ switch (ch) {
+ case ' ':
+ indent += 1;
+ break;
+ case '\n':
+ nl = i;
+ indent = 0;
+ break;
+ case '\r': {
+ const next = this.buffer[i + 1];
+ if (!next && !this.atEnd)
+ return this.setNext('block-scalar');
+ if (next === '\n')
+ break;
+ } // fallthrough
+ default:
+ break loop;
+ }
+ }
+ if (!ch && !this.atEnd)
+ return this.setNext('block-scalar');
+ if (indent >= this.indentNext) {
+ if (this.blockScalarIndent === -1)
+ this.indentNext = indent;
+ else
+ this.indentNext += this.blockScalarIndent;
+ do {
+ const cs = this.continueScalar(nl + 1);
+ if (cs === -1)
+ break;
+ nl = this.buffer.indexOf('\n', cs);
+ } while (nl !== -1);
+ if (nl === -1) {
+ if (!this.atEnd)
+ return this.setNext('block-scalar');
+ nl = this.buffer.length;
+ }
+ }
+ if (!this.blockScalarKeep) {
+ do {
+ let i = nl - 1;
+ let ch = this.buffer[i];
+ if (ch === '\r')
+ ch = this.buffer[--i];
+ const lastChar = i; // Drop the line if last char not more indented
+ while (ch === ' ' || ch === '\t')
+ ch = this.buffer[--i];
+ if (ch === '\n' && i >= this.pos && i + 1 + indent > lastChar)
+ nl = i;
+ else
+ break;
+ } while (true);
+ }
+ yield SCALAR;
+ yield* this.pushToIndex(nl + 1, true);
+ return yield* this.parseLineStart();
+ }
+ *parsePlainScalar() {
+ const inFlow = this.flowLevel > 0;
+ let end = this.pos - 1;
+ let i = this.pos - 1;
+ let ch;
+ while ((ch = this.buffer[++i])) {
+ if (ch === ':') {
+ const next = this.buffer[i + 1];
+ if (isEmpty(next) || (inFlow && next === ','))
+ break;
+ end = i;
+ }
+ else if (isEmpty(ch)) {
+ let next = this.buffer[i + 1];
+ if (ch === '\r') {
+ if (next === '\n') {
+ i += 1;
+ ch = '\n';
+ next = this.buffer[i + 1];
+ }
+ else
+ end = i;
+ }
+ if (next === '#' || (inFlow && invalidFlowScalarChars.includes(next)))
+ break;
+ if (ch === '\n') {
+ const cs = this.continueScalar(i + 1);
+ if (cs === -1)
+ break;
+ i = Math.max(i, cs - 2); // to advance, but still account for ' #'
+ }
+ }
+ else {
+ if (inFlow && invalidFlowScalarChars.includes(ch))
+ break;
+ end = i;
+ }
+ }
+ if (!ch && !this.atEnd)
+ return this.setNext('plain-scalar');
+ yield SCALAR;
+ yield* this.pushToIndex(end + 1, true);
+ return inFlow ? 'flow' : 'doc';
+ }
+ *pushCount(n) {
+ if (n > 0) {
+ yield this.buffer.substr(this.pos, n);
+ this.pos += n;
+ return n;
+ }
+ return 0;
+ }
+ *pushToIndex(i, allowEmpty) {
+ const s = this.buffer.slice(this.pos, i);
+ if (s) {
+ yield s;
+ this.pos += s.length;
+ return s.length;
+ }
+ else if (allowEmpty)
+ yield '';
+ return 0;
+ }
+ *pushIndicators() {
+ switch (this.charAt(0)) {
+ case '!':
+ return ((yield* this.pushTag()) +
+ (yield* this.pushSpaces(true)) +
+ (yield* this.pushIndicators()));
+ case '&':
+ return ((yield* this.pushUntil(isNotAnchorChar)) +
+ (yield* this.pushSpaces(true)) +
+ (yield* this.pushIndicators()));
+ case '-': // this is an error
+ case '?': // this is an error outside flow collections
+ case ':': {
+ const inFlow = this.flowLevel > 0;
+ const ch1 = this.charAt(1);
+ if (isEmpty(ch1) || (inFlow && invalidFlowScalarChars.includes(ch1))) {
+ if (!inFlow)
+ this.indentNext = this.indentValue + 1;
+ else if (this.flowKey)
+ this.flowKey = false;
+ return ((yield* this.pushCount(1)) +
+ (yield* this.pushSpaces(true)) +
+ (yield* this.pushIndicators()));
+ }
+ }
+ }
+ return 0;
+ }
+ *pushTag() {
+ if (this.charAt(1) === '<') {
+ let i = this.pos + 2;
+ let ch = this.buffer[i];
+ while (!isEmpty(ch) && ch !== '>')
+ ch = this.buffer[++i];
+ return yield* this.pushToIndex(ch === '>' ? i + 1 : i, false);
+ }
+ else {
+ let i = this.pos + 1;
+ let ch = this.buffer[i];
+ while (ch) {
+ if (tagChars.includes(ch))
+ ch = this.buffer[++i];
+ else if (ch === '%' &&
+ hexDigits.includes(this.buffer[i + 1]) &&
+ hexDigits.includes(this.buffer[i + 2])) {
+ ch = this.buffer[(i += 3)];
+ }
+ else
+ break;
+ }
+ return yield* this.pushToIndex(i, false);
+ }
+ }
+ *pushNewline() {
+ const ch = this.buffer[this.pos];
+ if (ch === '\n')
+ return yield* this.pushCount(1);
+ else if (ch === '\r' && this.charAt(1) === '\n')
+ return yield* this.pushCount(2);
+ else
+ return 0;
+ }
+ *pushSpaces(allowTabs) {
+ let i = this.pos - 1;
+ let ch;
+ do {
+ ch = this.buffer[++i];
+ } while (ch === ' ' || (allowTabs && ch === '\t'));
+ const n = i - this.pos;
+ if (n > 0) {
+ yield this.buffer.substr(this.pos, n);
+ this.pos = i;
+ }
+ return n;
+ }
+ *pushUntil(test) {
+ let i = this.pos;
+ let ch = this.buffer[i];
+ while (!test(ch))
+ ch = this.buffer[++i];
+ return yield* this.pushToIndex(i, false);
+ }
+}
+
+export { Lexer };
diff --git a/MistyCore/node_modules/yaml/browser/dist/parse/line-counter.js b/MistyCore/node_modules/yaml/browser/dist/parse/line-counter.js
new file mode 100644
index 0000000..002ce24
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/parse/line-counter.js
@@ -0,0 +1,39 @@
+/**
+ * Tracks newlines during parsing in order to provide an efficient API for
+ * determining the one-indexed `{ line, col }` position for any offset
+ * within the input.
+ */
+class LineCounter {
+ constructor() {
+ this.lineStarts = [];
+ /**
+ * Should be called in ascending order. Otherwise, call
+ * `lineCounter.lineStarts.sort()` before calling `linePos()`.
+ */
+ this.addNewLine = (offset) => this.lineStarts.push(offset);
+ /**
+ * Performs a binary search and returns the 1-indexed { line, col }
+ * position of `offset`. If `line === 0`, `addNewLine` has never been
+ * called or `offset` is before the first known newline.
+ */
+ this.linePos = (offset) => {
+ let low = 0;
+ let high = this.lineStarts.length;
+ while (low < high) {
+ const mid = (low + high) >> 1; // Math.floor((low + high) / 2)
+ if (this.lineStarts[mid] < offset)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+ if (this.lineStarts[low] === offset)
+ return { line: low + 1, col: 1 };
+ if (low === 0)
+ return { line: 0, col: offset };
+ const start = this.lineStarts[low - 1];
+ return { line: low, col: offset - start + 1 };
+ };
+ }
+}
+
+export { LineCounter };
diff --git a/MistyCore/node_modules/yaml/browser/dist/parse/parser.js b/MistyCore/node_modules/yaml/browser/dist/parse/parser.js
new file mode 100644
index 0000000..d75e1ee
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/parse/parser.js
@@ -0,0 +1,950 @@
+import { tokenType } from './cst.js';
+import { Lexer } from './lexer.js';
+
+function includesToken(list, type) {
+ for (let i = 0; i < list.length; ++i)
+ if (list[i].type === type)
+ return true;
+ return false;
+}
+function findNonEmptyIndex(list) {
+ for (let i = 0; i < list.length; ++i) {
+ switch (list[i].type) {
+ case 'space':
+ case 'comment':
+ case 'newline':
+ break;
+ default:
+ return i;
+ }
+ }
+ return -1;
+}
+function isFlowToken(token) {
+ switch (token?.type) {
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ case 'flow-collection':
+ return true;
+ default:
+ return false;
+ }
+}
+function getPrevProps(parent) {
+ switch (parent.type) {
+ case 'document':
+ return parent.start;
+ case 'block-map': {
+ const it = parent.items[parent.items.length - 1];
+ return it.sep ?? it.start;
+ }
+ case 'block-seq':
+ return parent.items[parent.items.length - 1].start;
+ /* istanbul ignore next should not happen */
+ default:
+ return [];
+ }
+}
+/** Note: May modify input array */
+function getFirstKeyStartProps(prev) {
+ if (prev.length === 0)
+ return [];
+ let i = prev.length;
+ loop: while (--i >= 0) {
+ switch (prev[i].type) {
+ case 'doc-start':
+ case 'explicit-key-ind':
+ case 'map-value-ind':
+ case 'seq-item-ind':
+ case 'newline':
+ break loop;
+ }
+ }
+ while (prev[++i]?.type === 'space') {
+ /* loop */
+ }
+ return prev.splice(i, prev.length);
+}
+function fixFlowSeqItems(fc) {
+ if (fc.start.type === 'flow-seq-start') {
+ for (const it of fc.items) {
+ if (it.sep &&
+ !it.value &&
+ !includesToken(it.start, 'explicit-key-ind') &&
+ !includesToken(it.sep, 'map-value-ind')) {
+ if (it.key)
+ it.value = it.key;
+ delete it.key;
+ if (isFlowToken(it.value)) {
+ if (it.value.end)
+ Array.prototype.push.apply(it.value.end, it.sep);
+ else
+ it.value.end = it.sep;
+ }
+ else
+ Array.prototype.push.apply(it.start, it.sep);
+ delete it.sep;
+ }
+ }
+ }
+}
+/**
+ * A YAML concrete syntax tree (CST) parser
+ *
+ * ```ts
+ * const src: string = ...
+ * for (const token of new Parser().parse(src)) {
+ * // token: Token
+ * }
+ * ```
+ *
+ * To use the parser with a user-provided lexer:
+ *
+ * ```ts
+ * function* parse(source: string, lexer: Lexer) {
+ * const parser = new Parser()
+ * for (const lexeme of lexer.lex(source))
+ * yield* parser.next(lexeme)
+ * yield* parser.end()
+ * }
+ *
+ * const src: string = ...
+ * const lexer = new Lexer()
+ * for (const token of parse(src, lexer)) {
+ * // token: Token
+ * }
+ * ```
+ */
+class Parser {
+ /**
+ * @param onNewLine - If defined, called separately with the start position of
+ * each new line (in `parse()`, including the start of input).
+ */
+ constructor(onNewLine) {
+ /** If true, space and sequence indicators count as indentation */
+ this.atNewLine = true;
+ /** If true, next token is a scalar value */
+ this.atScalar = false;
+ /** Current indentation level */
+ this.indent = 0;
+ /** Current offset since the start of parsing */
+ this.offset = 0;
+ /** On the same line with a block map key */
+ this.onKeyLine = false;
+ /** Top indicates the node that's currently being built */
+ this.stack = [];
+ /** The source of the current token, set in parse() */
+ this.source = '';
+ /** The type of the current token, set in parse() */
+ this.type = '';
+ // Must be defined after `next()`
+ this.lexer = new Lexer();
+ this.onNewLine = onNewLine;
+ }
+ /**
+ * Parse `source` as a YAML stream.
+ * If `incomplete`, a part of the last line may be left as a buffer for the next call.
+ *
+ * Errors are not thrown, but yielded as `{ type: 'error', message }` tokens.
+ *
+ * @returns A generator of tokens representing each directive, document, and other structure.
+ */
+ *parse(source, incomplete = false) {
+ if (this.onNewLine && this.offset === 0)
+ this.onNewLine(0);
+ for (const lexeme of this.lexer.lex(source, incomplete))
+ yield* this.next(lexeme);
+ if (!incomplete)
+ yield* this.end();
+ }
+ /**
+ * Advance the parser by the `source` of one lexical token.
+ */
+ *next(source) {
+ this.source = source;
+ if (this.atScalar) {
+ this.atScalar = false;
+ yield* this.step();
+ this.offset += source.length;
+ return;
+ }
+ const type = tokenType(source);
+ if (!type) {
+ const message = `Not a YAML token: ${source}`;
+ yield* this.pop({ type: 'error', offset: this.offset, message, source });
+ this.offset += source.length;
+ }
+ else if (type === 'scalar') {
+ this.atNewLine = false;
+ this.atScalar = true;
+ this.type = 'scalar';
+ }
+ else {
+ this.type = type;
+ yield* this.step();
+ switch (type) {
+ case 'newline':
+ this.atNewLine = true;
+ this.indent = 0;
+ if (this.onNewLine)
+ this.onNewLine(this.offset + source.length);
+ break;
+ case 'space':
+ if (this.atNewLine && source[0] === ' ')
+ this.indent += source.length;
+ break;
+ case 'explicit-key-ind':
+ case 'map-value-ind':
+ case 'seq-item-ind':
+ if (this.atNewLine)
+ this.indent += source.length;
+ break;
+ case 'doc-mode':
+ case 'flow-error-end':
+ return;
+ default:
+ this.atNewLine = false;
+ }
+ this.offset += source.length;
+ }
+ }
+ /** Call at end of input to push out any remaining constructions */
+ *end() {
+ while (this.stack.length > 0)
+ yield* this.pop();
+ }
+ get sourceToken() {
+ const st = {
+ type: this.type,
+ offset: this.offset,
+ indent: this.indent,
+ source: this.source
+ };
+ return st;
+ }
+ *step() {
+ const top = this.peek(1);
+ if (this.type === 'doc-end' && (!top || top.type !== 'doc-end')) {
+ while (this.stack.length > 0)
+ yield* this.pop();
+ this.stack.push({
+ type: 'doc-end',
+ offset: this.offset,
+ source: this.source
+ });
+ return;
+ }
+ if (!top)
+ return yield* this.stream();
+ switch (top.type) {
+ case 'document':
+ return yield* this.document(top);
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ return yield* this.scalar(top);
+ case 'block-scalar':
+ return yield* this.blockScalar(top);
+ case 'block-map':
+ return yield* this.blockMap(top);
+ case 'block-seq':
+ return yield* this.blockSequence(top);
+ case 'flow-collection':
+ return yield* this.flowCollection(top);
+ case 'doc-end':
+ return yield* this.documentEnd(top);
+ }
+ /* istanbul ignore next should not happen */
+ yield* this.pop();
+ }
+ peek(n) {
+ return this.stack[this.stack.length - n];
+ }
+ *pop(error) {
+ const token = error ?? this.stack.pop();
+ /* istanbul ignore if should not happen */
+ if (!token) {
+ const message = 'Tried to pop an empty stack';
+ yield { type: 'error', offset: this.offset, source: '', message };
+ }
+ else if (this.stack.length === 0) {
+ yield token;
+ }
+ else {
+ const top = this.peek(1);
+ if (token.type === 'block-scalar') {
+ // Block scalars use their parent rather than header indent
+ token.indent = 'indent' in top ? top.indent : 0;
+ }
+ else if (token.type === 'flow-collection' && top.type === 'document') {
+ // Ignore all indent for top-level flow collections
+ token.indent = 0;
+ }
+ if (token.type === 'flow-collection')
+ fixFlowSeqItems(token);
+ switch (top.type) {
+ case 'document':
+ top.value = token;
+ break;
+ case 'block-scalar':
+ top.props.push(token); // error
+ break;
+ case 'block-map': {
+ const it = top.items[top.items.length - 1];
+ if (it.value) {
+ top.items.push({ start: [], key: token, sep: [] });
+ this.onKeyLine = true;
+ return;
+ }
+ else if (it.sep) {
+ it.value = token;
+ }
+ else {
+ Object.assign(it, { key: token, sep: [] });
+ this.onKeyLine = !includesToken(it.start, 'explicit-key-ind');
+ return;
+ }
+ break;
+ }
+ case 'block-seq': {
+ const it = top.items[top.items.length - 1];
+ if (it.value)
+ top.items.push({ start: [], value: token });
+ else
+ it.value = token;
+ break;
+ }
+ case 'flow-collection': {
+ const it = top.items[top.items.length - 1];
+ if (!it || it.value)
+ top.items.push({ start: [], key: token, sep: [] });
+ else if (it.sep)
+ it.value = token;
+ else
+ Object.assign(it, { key: token, sep: [] });
+ return;
+ }
+ /* istanbul ignore next should not happen */
+ default:
+ yield* this.pop();
+ yield* this.pop(token);
+ }
+ if ((top.type === 'document' ||
+ top.type === 'block-map' ||
+ top.type === 'block-seq') &&
+ (token.type === 'block-map' || token.type === 'block-seq')) {
+ const last = token.items[token.items.length - 1];
+ if (last &&
+ !last.sep &&
+ !last.value &&
+ last.start.length > 0 &&
+ findNonEmptyIndex(last.start) === -1 &&
+ (token.indent === 0 ||
+ last.start.every(st => st.type !== 'comment' || st.indent < token.indent))) {
+ if (top.type === 'document')
+ top.end = last.start;
+ else
+ top.items.push({ start: last.start });
+ token.items.splice(-1, 1);
+ }
+ }
+ }
+ }
+ *stream() {
+ switch (this.type) {
+ case 'directive-line':
+ yield { type: 'directive', offset: this.offset, source: this.source };
+ return;
+ case 'byte-order-mark':
+ case 'space':
+ case 'comment':
+ case 'newline':
+ yield this.sourceToken;
+ return;
+ case 'doc-mode':
+ case 'doc-start': {
+ const doc = {
+ type: 'document',
+ offset: this.offset,
+ start: []
+ };
+ if (this.type === 'doc-start')
+ doc.start.push(this.sourceToken);
+ this.stack.push(doc);
+ return;
+ }
+ }
+ yield {
+ type: 'error',
+ offset: this.offset,
+ message: `Unexpected ${this.type} token in YAML stream`,
+ source: this.source
+ };
+ }
+ *document(doc) {
+ if (doc.value)
+ return yield* this.lineEnd(doc);
+ switch (this.type) {
+ case 'doc-start': {
+ if (findNonEmptyIndex(doc.start) !== -1) {
+ yield* this.pop();
+ yield* this.step();
+ }
+ else
+ doc.start.push(this.sourceToken);
+ return;
+ }
+ case 'anchor':
+ case 'tag':
+ case 'space':
+ case 'comment':
+ case 'newline':
+ doc.start.push(this.sourceToken);
+ return;
+ }
+ const bv = this.startBlockValue(doc);
+ if (bv)
+ this.stack.push(bv);
+ else {
+ yield {
+ type: 'error',
+ offset: this.offset,
+ message: `Unexpected ${this.type} token in YAML document`,
+ source: this.source
+ };
+ }
+ }
+ *scalar(scalar) {
+ if (this.type === 'map-value-ind') {
+ const prev = getPrevProps(this.peek(2));
+ const start = getFirstKeyStartProps(prev);
+ let sep;
+ if (scalar.end) {
+ sep = scalar.end;
+ sep.push(this.sourceToken);
+ delete scalar.end;
+ }
+ else
+ sep = [this.sourceToken];
+ const map = {
+ type: 'block-map',
+ offset: scalar.offset,
+ indent: scalar.indent,
+ items: [{ start, key: scalar, sep }]
+ };
+ this.onKeyLine = true;
+ this.stack[this.stack.length - 1] = map;
+ }
+ else
+ yield* this.lineEnd(scalar);
+ }
+ *blockScalar(scalar) {
+ switch (this.type) {
+ case 'space':
+ case 'comment':
+ case 'newline':
+ scalar.props.push(this.sourceToken);
+ return;
+ case 'scalar':
+ scalar.source = this.source;
+ // block-scalar source includes trailing newline
+ this.atNewLine = true;
+ this.indent = 0;
+ if (this.onNewLine) {
+ let nl = this.source.indexOf('\n') + 1;
+ while (nl !== 0) {
+ this.onNewLine(this.offset + nl);
+ nl = this.source.indexOf('\n', nl) + 1;
+ }
+ }
+ yield* this.pop();
+ break;
+ /* istanbul ignore next should not happen */
+ default:
+ yield* this.pop();
+ yield* this.step();
+ }
+ }
+ *blockMap(map) {
+ const it = map.items[map.items.length - 1];
+ // it.sep is true-ish if pair already has key or : separator
+ switch (this.type) {
+ case 'newline':
+ this.onKeyLine = false;
+ if (it.value) {
+ const end = 'end' in it.value ? it.value.end : undefined;
+ const last = Array.isArray(end) ? end[end.length - 1] : undefined;
+ if (last?.type === 'comment')
+ end?.push(this.sourceToken);
+ else
+ map.items.push({ start: [this.sourceToken] });
+ }
+ else if (it.sep) {
+ it.sep.push(this.sourceToken);
+ }
+ else {
+ it.start.push(this.sourceToken);
+ }
+ return;
+ case 'space':
+ case 'comment':
+ if (it.value) {
+ map.items.push({ start: [this.sourceToken] });
+ }
+ else if (it.sep) {
+ it.sep.push(this.sourceToken);
+ }
+ else {
+ if (this.atIndentedComment(it.start, map.indent)) {
+ const prev = map.items[map.items.length - 2];
+ const end = prev?.value?.end;
+ if (Array.isArray(end)) {
+ Array.prototype.push.apply(end, it.start);
+ end.push(this.sourceToken);
+ map.items.pop();
+ return;
+ }
+ }
+ it.start.push(this.sourceToken);
+ }
+ return;
+ }
+ if (this.indent >= map.indent) {
+ const atNextItem = !this.onKeyLine && this.indent === map.indent && it.sep;
+ // For empty nodes, assign newline-separated not indented empty tokens to following node
+ let start = [];
+ if (atNextItem && it.sep && !it.value) {
+ const nl = [];
+ for (let i = 0; i < it.sep.length; ++i) {
+ const st = it.sep[i];
+ switch (st.type) {
+ case 'newline':
+ nl.push(i);
+ break;
+ case 'space':
+ break;
+ case 'comment':
+ if (st.indent > map.indent)
+ nl.length = 0;
+ break;
+ default:
+ nl.length = 0;
+ }
+ }
+ if (nl.length >= 2)
+ start = it.sep.splice(nl[1]);
+ }
+ switch (this.type) {
+ case 'anchor':
+ case 'tag':
+ if (atNextItem || it.value) {
+ start.push(this.sourceToken);
+ map.items.push({ start });
+ this.onKeyLine = true;
+ }
+ else if (it.sep) {
+ it.sep.push(this.sourceToken);
+ }
+ else {
+ it.start.push(this.sourceToken);
+ }
+ return;
+ case 'explicit-key-ind':
+ if (!it.sep && !includesToken(it.start, 'explicit-key-ind')) {
+ it.start.push(this.sourceToken);
+ }
+ else if (atNextItem || it.value) {
+ start.push(this.sourceToken);
+ map.items.push({ start });
+ }
+ else {
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start: [this.sourceToken] }]
+ });
+ }
+ this.onKeyLine = true;
+ return;
+ case 'map-value-ind':
+ if (includesToken(it.start, 'explicit-key-ind')) {
+ if (!it.sep) {
+ if (includesToken(it.start, 'newline')) {
+ Object.assign(it, { key: null, sep: [this.sourceToken] });
+ }
+ else {
+ const start = getFirstKeyStartProps(it.start);
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start, key: null, sep: [this.sourceToken] }]
+ });
+ }
+ }
+ else if (it.value) {
+ map.items.push({ start: [], key: null, sep: [this.sourceToken] });
+ }
+ else if (includesToken(it.sep, 'map-value-ind')) {
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start, key: null, sep: [this.sourceToken] }]
+ });
+ }
+ else if (isFlowToken(it.key) &&
+ !includesToken(it.sep, 'newline')) {
+ const start = getFirstKeyStartProps(it.start);
+ const key = it.key;
+ const sep = it.sep;
+ sep.push(this.sourceToken);
+ // @ts-expect-error type guard is wrong here
+ delete it.key, delete it.sep;
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start, key, sep }]
+ });
+ }
+ else if (start.length > 0) {
+ // Not actually at next item
+ it.sep = it.sep.concat(start, this.sourceToken);
+ }
+ else {
+ it.sep.push(this.sourceToken);
+ }
+ }
+ else {
+ if (!it.sep) {
+ Object.assign(it, { key: null, sep: [this.sourceToken] });
+ }
+ else if (it.value || atNextItem) {
+ map.items.push({ start, key: null, sep: [this.sourceToken] });
+ }
+ else if (includesToken(it.sep, 'map-value-ind')) {
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start: [], key: null, sep: [this.sourceToken] }]
+ });
+ }
+ else {
+ it.sep.push(this.sourceToken);
+ }
+ }
+ this.onKeyLine = true;
+ return;
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar': {
+ const fs = this.flowScalar(this.type);
+ if (atNextItem || it.value) {
+ map.items.push({ start, key: fs, sep: [] });
+ this.onKeyLine = true;
+ }
+ else if (it.sep) {
+ this.stack.push(fs);
+ }
+ else {
+ Object.assign(it, { key: fs, sep: [] });
+ this.onKeyLine = true;
+ }
+ return;
+ }
+ default: {
+ const bv = this.startBlockValue(map);
+ if (bv) {
+ if (atNextItem &&
+ bv.type !== 'block-seq' &&
+ includesToken(it.start, 'explicit-key-ind')) {
+ map.items.push({ start });
+ }
+ this.stack.push(bv);
+ return;
+ }
+ }
+ }
+ }
+ yield* this.pop();
+ yield* this.step();
+ }
+ *blockSequence(seq) {
+ const it = seq.items[seq.items.length - 1];
+ switch (this.type) {
+ case 'newline':
+ if (it.value) {
+ const end = 'end' in it.value ? it.value.end : undefined;
+ const last = Array.isArray(end) ? end[end.length - 1] : undefined;
+ if (last?.type === 'comment')
+ end?.push(this.sourceToken);
+ else
+ seq.items.push({ start: [this.sourceToken] });
+ }
+ else
+ it.start.push(this.sourceToken);
+ return;
+ case 'space':
+ case 'comment':
+ if (it.value)
+ seq.items.push({ start: [this.sourceToken] });
+ else {
+ if (this.atIndentedComment(it.start, seq.indent)) {
+ const prev = seq.items[seq.items.length - 2];
+ const end = prev?.value?.end;
+ if (Array.isArray(end)) {
+ Array.prototype.push.apply(end, it.start);
+ end.push(this.sourceToken);
+ seq.items.pop();
+ return;
+ }
+ }
+ it.start.push(this.sourceToken);
+ }
+ return;
+ case 'anchor':
+ case 'tag':
+ if (it.value || this.indent <= seq.indent)
+ break;
+ it.start.push(this.sourceToken);
+ return;
+ case 'seq-item-ind':
+ if (this.indent !== seq.indent)
+ break;
+ if (it.value || includesToken(it.start, 'seq-item-ind'))
+ seq.items.push({ start: [this.sourceToken] });
+ else
+ it.start.push(this.sourceToken);
+ return;
+ }
+ if (this.indent > seq.indent) {
+ const bv = this.startBlockValue(seq);
+ if (bv) {
+ this.stack.push(bv);
+ return;
+ }
+ }
+ yield* this.pop();
+ yield* this.step();
+ }
+ *flowCollection(fc) {
+ const it = fc.items[fc.items.length - 1];
+ if (this.type === 'flow-error-end') {
+ let top;
+ do {
+ yield* this.pop();
+ top = this.peek(1);
+ } while (top && top.type === 'flow-collection');
+ }
+ else if (fc.end.length === 0) {
+ switch (this.type) {
+ case 'comma':
+ case 'explicit-key-ind':
+ if (!it || it.sep)
+ fc.items.push({ start: [this.sourceToken] });
+ else
+ it.start.push(this.sourceToken);
+ return;
+ case 'map-value-ind':
+ if (!it || it.value)
+ fc.items.push({ start: [], key: null, sep: [this.sourceToken] });
+ else if (it.sep)
+ it.sep.push(this.sourceToken);
+ else
+ Object.assign(it, { key: null, sep: [this.sourceToken] });
+ return;
+ case 'space':
+ case 'comment':
+ case 'newline':
+ case 'anchor':
+ case 'tag':
+ if (!it || it.value)
+ fc.items.push({ start: [this.sourceToken] });
+ else if (it.sep)
+ it.sep.push(this.sourceToken);
+ else
+ it.start.push(this.sourceToken);
+ return;
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar': {
+ const fs = this.flowScalar(this.type);
+ if (!it || it.value)
+ fc.items.push({ start: [], key: fs, sep: [] });
+ else if (it.sep)
+ this.stack.push(fs);
+ else
+ Object.assign(it, { key: fs, sep: [] });
+ return;
+ }
+ case 'flow-map-end':
+ case 'flow-seq-end':
+ fc.end.push(this.sourceToken);
+ return;
+ }
+ const bv = this.startBlockValue(fc);
+ /* istanbul ignore else should not happen */
+ if (bv)
+ this.stack.push(bv);
+ else {
+ yield* this.pop();
+ yield* this.step();
+ }
+ }
+ else {
+ const parent = this.peek(2);
+ if (parent.type === 'block-map' &&
+ ((this.type === 'map-value-ind' && parent.indent === fc.indent) ||
+ (this.type === 'newline' &&
+ !parent.items[parent.items.length - 1].sep))) {
+ yield* this.pop();
+ yield* this.step();
+ }
+ else if (this.type === 'map-value-ind' &&
+ parent.type !== 'flow-collection') {
+ const prev = getPrevProps(parent);
+ const start = getFirstKeyStartProps(prev);
+ fixFlowSeqItems(fc);
+ const sep = fc.end.splice(1, fc.end.length);
+ sep.push(this.sourceToken);
+ const map = {
+ type: 'block-map',
+ offset: fc.offset,
+ indent: fc.indent,
+ items: [{ start, key: fc, sep }]
+ };
+ this.onKeyLine = true;
+ this.stack[this.stack.length - 1] = map;
+ }
+ else {
+ yield* this.lineEnd(fc);
+ }
+ }
+ }
+ flowScalar(type) {
+ if (this.onNewLine) {
+ let nl = this.source.indexOf('\n') + 1;
+ while (nl !== 0) {
+ this.onNewLine(this.offset + nl);
+ nl = this.source.indexOf('\n', nl) + 1;
+ }
+ }
+ return {
+ type,
+ offset: this.offset,
+ indent: this.indent,
+ source: this.source
+ };
+ }
+ startBlockValue(parent) {
+ switch (this.type) {
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ return this.flowScalar(this.type);
+ case 'block-scalar-header':
+ return {
+ type: 'block-scalar',
+ offset: this.offset,
+ indent: this.indent,
+ props: [this.sourceToken],
+ source: ''
+ };
+ case 'flow-map-start':
+ case 'flow-seq-start':
+ return {
+ type: 'flow-collection',
+ offset: this.offset,
+ indent: this.indent,
+ start: this.sourceToken,
+ items: [],
+ end: []
+ };
+ case 'seq-item-ind':
+ return {
+ type: 'block-seq',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start: [this.sourceToken] }]
+ };
+ case 'explicit-key-ind': {
+ this.onKeyLine = true;
+ const prev = getPrevProps(parent);
+ const start = getFirstKeyStartProps(prev);
+ start.push(this.sourceToken);
+ return {
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start }]
+ };
+ }
+ case 'map-value-ind': {
+ this.onKeyLine = true;
+ const prev = getPrevProps(parent);
+ const start = getFirstKeyStartProps(prev);
+ return {
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start, key: null, sep: [this.sourceToken] }]
+ };
+ }
+ }
+ return null;
+ }
+ atIndentedComment(start, indent) {
+ if (this.type !== 'comment')
+ return false;
+ if (this.indent <= indent)
+ return false;
+ return start.every(st => st.type === 'newline' || st.type === 'space');
+ }
+ *documentEnd(docEnd) {
+ if (this.type !== 'doc-mode') {
+ if (docEnd.end)
+ docEnd.end.push(this.sourceToken);
+ else
+ docEnd.end = [this.sourceToken];
+ if (this.type === 'newline')
+ yield* this.pop();
+ }
+ }
+ *lineEnd(token) {
+ switch (this.type) {
+ case 'comma':
+ case 'doc-start':
+ case 'doc-end':
+ case 'flow-seq-end':
+ case 'flow-map-end':
+ case 'map-value-ind':
+ yield* this.pop();
+ yield* this.step();
+ break;
+ case 'newline':
+ this.onKeyLine = false;
+ // fallthrough
+ case 'space':
+ case 'comment':
+ default:
+ // all other values are errors
+ if (token.end)
+ token.end.push(this.sourceToken);
+ else
+ token.end = [this.sourceToken];
+ if (this.type === 'newline')
+ yield* this.pop();
+ }
+ }
+}
+
+export { Parser };
diff --git a/MistyCore/node_modules/yaml/browser/dist/public-api.js b/MistyCore/node_modules/yaml/browser/dist/public-api.js
new file mode 100644
index 0000000..b711aa0
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/public-api.js
@@ -0,0 +1,99 @@
+import { Composer } from './compose/composer.js';
+import { Document } from './doc/Document.js';
+import { prettifyError, YAMLParseError } from './errors.js';
+import { warn } from './log.js';
+import { LineCounter } from './parse/line-counter.js';
+import { Parser } from './parse/parser.js';
+
+function parseOptions(options) {
+ const prettyErrors = options.prettyErrors !== false;
+ const lineCounter = options.lineCounter || (prettyErrors && new LineCounter()) || null;
+ return { lineCounter, prettyErrors };
+}
+/**
+ * Parse the input as a stream of YAML documents.
+ *
+ * Documents should be separated from each other by `...` or `---` marker lines.
+ *
+ * @returns If an empty `docs` array is returned, it will be of type
+ * EmptyStream and contain additional stream information. In
+ * TypeScript, you should use `'empty' in docs` as a type guard for it.
+ */
+function parseAllDocuments(source, options = {}) {
+ const { lineCounter, prettyErrors } = parseOptions(options);
+ const parser = new Parser(lineCounter?.addNewLine);
+ const composer = new Composer(options);
+ const docs = Array.from(composer.compose(parser.parse(source)));
+ if (prettyErrors && lineCounter)
+ for (const doc of docs) {
+ doc.errors.forEach(prettifyError(source, lineCounter));
+ doc.warnings.forEach(prettifyError(source, lineCounter));
+ }
+ if (docs.length > 0)
+ return docs;
+ return Object.assign([], { empty: true }, composer.streamInfo());
+}
+/** Parse an input string into a single YAML.Document */
+function parseDocument(source, options = {}) {
+ const { lineCounter, prettyErrors } = parseOptions(options);
+ const parser = new Parser(lineCounter?.addNewLine);
+ const composer = new Composer(options);
+ // `doc` is always set by compose.end(true) at the very latest
+ let doc = null;
+ for (const _doc of composer.compose(parser.parse(source), true, source.length)) {
+ if (!doc)
+ doc = _doc;
+ else if (doc.options.logLevel !== 'silent') {
+ doc.errors.push(new YAMLParseError(_doc.range.slice(0, 2), 'MULTIPLE_DOCS', 'Source contains multiple documents; please use YAML.parseAllDocuments()'));
+ break;
+ }
+ }
+ if (prettyErrors && lineCounter) {
+ doc.errors.forEach(prettifyError(source, lineCounter));
+ doc.warnings.forEach(prettifyError(source, lineCounter));
+ }
+ return doc;
+}
+function parse(src, reviver, options) {
+ let _reviver = undefined;
+ if (typeof reviver === 'function') {
+ _reviver = reviver;
+ }
+ else if (options === undefined && reviver && typeof reviver === 'object') {
+ options = reviver;
+ }
+ const doc = parseDocument(src, options);
+ if (!doc)
+ return null;
+ doc.warnings.forEach(warning => warn(doc.options.logLevel, warning));
+ if (doc.errors.length > 0) {
+ if (doc.options.logLevel !== 'silent')
+ throw doc.errors[0];
+ else
+ doc.errors = [];
+ }
+ return doc.toJS(Object.assign({ reviver: _reviver }, options));
+}
+function stringify(value, replacer, options) {
+ let _replacer = null;
+ if (typeof replacer === 'function' || Array.isArray(replacer)) {
+ _replacer = replacer;
+ }
+ else if (options === undefined && replacer) {
+ options = replacer;
+ }
+ if (typeof options === 'string')
+ options = options.length;
+ if (typeof options === 'number') {
+ const indent = Math.round(options);
+ options = indent < 1 ? undefined : indent > 8 ? { indent: 8 } : { indent };
+ }
+ if (value === undefined) {
+ const { keepUndefined } = options ?? replacer ?? {};
+ if (!keepUndefined)
+ return undefined;
+ }
+ return new Document(value, _replacer, options).toString(options);
+}
+
+export { parse, parseAllDocuments, parseDocument, stringify };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/Schema.js b/MistyCore/node_modules/yaml/browser/dist/schema/Schema.js
new file mode 100644
index 0000000..9b8094b
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/Schema.js
@@ -0,0 +1,38 @@
+import { MAP, SCALAR, SEQ } from '../nodes/Node.js';
+import { map } from './common/map.js';
+import { seq } from './common/seq.js';
+import { string } from './common/string.js';
+import { getTags, coreKnownTags } from './tags.js';
+
+const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
+class Schema {
+ constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }) {
+ this.compat = Array.isArray(compat)
+ ? getTags(compat, 'compat')
+ : compat
+ ? getTags(null, compat)
+ : null;
+ this.merge = !!merge;
+ this.name = (typeof schema === 'string' && schema) || 'core';
+ this.knownTags = resolveKnownTags ? coreKnownTags : {};
+ this.tags = getTags(customTags, this.name);
+ this.toStringOptions = toStringDefaults ?? null;
+ Object.defineProperty(this, MAP, { value: map });
+ Object.defineProperty(this, SCALAR, { value: string });
+ Object.defineProperty(this, SEQ, { value: seq });
+ // Used by createMap()
+ this.sortMapEntries =
+ typeof sortMapEntries === 'function'
+ ? sortMapEntries
+ : sortMapEntries === true
+ ? sortMapEntriesByKey
+ : null;
+ }
+ clone() {
+ const copy = Object.create(Schema.prototype, Object.getOwnPropertyDescriptors(this));
+ copy.tags = this.tags.slice();
+ return copy;
+ }
+}
+
+export { Schema };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/common/map.js b/MistyCore/node_modules/yaml/browser/dist/schema/common/map.js
new file mode 100644
index 0000000..133d861
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/common/map.js
@@ -0,0 +1,42 @@
+import { isMap } from '../../nodes/Node.js';
+import { createPair } from '../../nodes/Pair.js';
+import { YAMLMap } from '../../nodes/YAMLMap.js';
+
+function createMap(schema, obj, ctx) {
+ const { keepUndefined, replacer } = ctx;
+ const map = new YAMLMap(schema);
+ const add = (key, value) => {
+ if (typeof replacer === 'function')
+ value = replacer.call(obj, key, value);
+ else if (Array.isArray(replacer) && !replacer.includes(key))
+ return;
+ if (value !== undefined || keepUndefined)
+ map.items.push(createPair(key, value, ctx));
+ };
+ if (obj instanceof Map) {
+ for (const [key, value] of obj)
+ add(key, value);
+ }
+ else if (obj && typeof obj === 'object') {
+ for (const key of Object.keys(obj))
+ add(key, obj[key]);
+ }
+ if (typeof schema.sortMapEntries === 'function') {
+ map.items.sort(schema.sortMapEntries);
+ }
+ return map;
+}
+const map = {
+ collection: 'map',
+ createNode: createMap,
+ default: true,
+ nodeClass: YAMLMap,
+ tag: 'tag:yaml.org,2002:map',
+ resolve(map, onError) {
+ if (!isMap(map))
+ onError('Expected a mapping for this tag');
+ return map;
+ }
+};
+
+export { map };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/common/null.js b/MistyCore/node_modules/yaml/browser/dist/schema/common/null.js
new file mode 100644
index 0000000..fcbe1b7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/common/null.js
@@ -0,0 +1,15 @@
+import { Scalar } from '../../nodes/Scalar.js';
+
+const nullTag = {
+ identify: value => value == null,
+ createNode: () => new Scalar(null),
+ default: true,
+ tag: 'tag:yaml.org,2002:null',
+ test: /^(?:~|[Nn]ull|NULL)?$/,
+ resolve: () => new Scalar(null),
+ stringify: ({ source }, ctx) => typeof source === 'string' && nullTag.test.test(source)
+ ? source
+ : ctx.options.nullStr
+};
+
+export { nullTag };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/common/seq.js b/MistyCore/node_modules/yaml/browser/dist/schema/common/seq.js
new file mode 100644
index 0000000..2aa7639
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/common/seq.js
@@ -0,0 +1,33 @@
+import { createNode } from '../../doc/createNode.js';
+import { isSeq } from '../../nodes/Node.js';
+import { YAMLSeq } from '../../nodes/YAMLSeq.js';
+
+function createSeq(schema, obj, ctx) {
+ const { replacer } = ctx;
+ const seq = new YAMLSeq(schema);
+ if (obj && Symbol.iterator in Object(obj)) {
+ let i = 0;
+ for (let it of obj) {
+ if (typeof replacer === 'function') {
+ const key = obj instanceof Set ? it : String(i++);
+ it = replacer.call(obj, key, it);
+ }
+ seq.items.push(createNode(it, undefined, ctx));
+ }
+ }
+ return seq;
+}
+const seq = {
+ collection: 'seq',
+ createNode: createSeq,
+ default: true,
+ nodeClass: YAMLSeq,
+ tag: 'tag:yaml.org,2002:seq',
+ resolve(seq, onError) {
+ if (!isSeq(seq))
+ onError('Expected a sequence for this tag');
+ return seq;
+ }
+};
+
+export { seq };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/common/string.js b/MistyCore/node_modules/yaml/browser/dist/schema/common/string.js
new file mode 100644
index 0000000..a064f7b
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/common/string.js
@@ -0,0 +1,14 @@
+import { stringifyString } from '../../stringify/stringifyString.js';
+
+const string = {
+ identify: value => typeof value === 'string',
+ default: true,
+ tag: 'tag:yaml.org,2002:str',
+ resolve: str => str,
+ stringify(item, ctx, onComment, onChompKeep) {
+ ctx = Object.assign({ actualString: true }, ctx);
+ return stringifyString(item, ctx, onComment, onChompKeep);
+ }
+};
+
+export { string };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/core/bool.js b/MistyCore/node_modules/yaml/browser/dist/schema/core/bool.js
new file mode 100644
index 0000000..ab3c943
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/core/bool.js
@@ -0,0 +1,19 @@
+import { Scalar } from '../../nodes/Scalar.js';
+
+const boolTag = {
+ identify: value => typeof value === 'boolean',
+ default: true,
+ tag: 'tag:yaml.org,2002:bool',
+ test: /^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,
+ resolve: str => new Scalar(str[0] === 't' || str[0] === 'T'),
+ stringify({ source, value }, ctx) {
+ if (source && boolTag.test.test(source)) {
+ const sv = source[0] === 't' || source[0] === 'T';
+ if (value === sv)
+ return source;
+ }
+ return value ? ctx.options.trueStr : ctx.options.falseStr;
+ }
+};
+
+export { boolTag };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/core/float.js b/MistyCore/node_modules/yaml/browser/dist/schema/core/float.js
new file mode 100644
index 0000000..a632cb7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/core/float.js
@@ -0,0 +1,43 @@
+import { Scalar } from '../../nodes/Scalar.js';
+import { stringifyNumber } from '../../stringify/stringifyNumber.js';
+
+const floatNaN = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^(?:[-+]?\.(?:inf|Inf|INF|nan|NaN|NAN))$/,
+ resolve: str => str.slice(-3).toLowerCase() === 'nan'
+ ? NaN
+ : str[0] === '-'
+ ? Number.NEGATIVE_INFINITY
+ : Number.POSITIVE_INFINITY,
+ stringify: stringifyNumber
+};
+const floatExp = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ format: 'EXP',
+ test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
+ resolve: str => parseFloat(str),
+ stringify(node) {
+ const num = Number(node.value);
+ return isFinite(num) ? num.toExponential() : stringifyNumber(node);
+ }
+};
+const float = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,
+ resolve(str) {
+ const node = new Scalar(parseFloat(str));
+ const dot = str.indexOf('.');
+ if (dot !== -1 && str[str.length - 1] === '0')
+ node.minFractionDigits = str.length - dot - 1;
+ return node;
+ },
+ stringify: stringifyNumber
+};
+
+export { float, floatExp, floatNaN };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/core/int.js b/MistyCore/node_modules/yaml/browser/dist/schema/core/int.js
new file mode 100644
index 0000000..7091235
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/core/int.js
@@ -0,0 +1,38 @@
+import { stringifyNumber } from '../../stringify/stringifyNumber.js';
+
+const intIdentify = (value) => typeof value === 'bigint' || Number.isInteger(value);
+const intResolve = (str, offset, radix, { intAsBigInt }) => (intAsBigInt ? BigInt(str) : parseInt(str.substring(offset), radix));
+function intStringify(node, radix, prefix) {
+ const { value } = node;
+ if (intIdentify(value) && value >= 0)
+ return prefix + value.toString(radix);
+ return stringifyNumber(node);
+}
+const intOct = {
+ identify: value => intIdentify(value) && value >= 0,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'OCT',
+ test: /^0o[0-7]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 2, 8, opt),
+ stringify: node => intStringify(node, 8, '0o')
+};
+const int = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ test: /^[-+]?[0-9]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
+ stringify: stringifyNumber
+};
+const intHex = {
+ identify: value => intIdentify(value) && value >= 0,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'HEX',
+ test: /^0x[0-9a-fA-F]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
+ stringify: node => intStringify(node, 16, '0x')
+};
+
+export { int, intHex, intOct };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/core/schema.js b/MistyCore/node_modules/yaml/browser/dist/schema/core/schema.js
new file mode 100644
index 0000000..dd02b2e
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/core/schema.js
@@ -0,0 +1,23 @@
+import { map } from '../common/map.js';
+import { nullTag } from '../common/null.js';
+import { seq } from '../common/seq.js';
+import { string } from '../common/string.js';
+import { boolTag } from './bool.js';
+import { floatNaN, floatExp, float } from './float.js';
+import { intOct, int, intHex } from './int.js';
+
+const schema = [
+ map,
+ seq,
+ string,
+ nullTag,
+ boolTag,
+ intOct,
+ int,
+ intHex,
+ floatNaN,
+ floatExp,
+ float
+];
+
+export { schema };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/json/schema.js b/MistyCore/node_modules/yaml/browser/dist/schema/json/schema.js
new file mode 100644
index 0000000..16d75ce
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/json/schema.js
@@ -0,0 +1,62 @@
+import { Scalar } from '../../nodes/Scalar.js';
+import { map } from '../common/map.js';
+import { seq } from '../common/seq.js';
+
+function intIdentify(value) {
+ return typeof value === 'bigint' || Number.isInteger(value);
+}
+const stringifyJSON = ({ value }) => JSON.stringify(value);
+const jsonScalars = [
+ {
+ identify: value => typeof value === 'string',
+ default: true,
+ tag: 'tag:yaml.org,2002:str',
+ resolve: str => str,
+ stringify: stringifyJSON
+ },
+ {
+ identify: value => value == null,
+ createNode: () => new Scalar(null),
+ default: true,
+ tag: 'tag:yaml.org,2002:null',
+ test: /^null$/,
+ resolve: () => null,
+ stringify: stringifyJSON
+ },
+ {
+ identify: value => typeof value === 'boolean',
+ default: true,
+ tag: 'tag:yaml.org,2002:bool',
+ test: /^true|false$/,
+ resolve: str => str === 'true',
+ stringify: stringifyJSON
+ },
+ {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ test: /^-?(?:0|[1-9][0-9]*)$/,
+ resolve: (str, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str, 10),
+ stringify: ({ value }) => intIdentify(value) ? value.toString() : JSON.stringify(value)
+ },
+ {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,
+ resolve: str => parseFloat(str),
+ stringify: stringifyJSON
+ }
+];
+const jsonError = {
+ default: true,
+ tag: '',
+ test: /^/,
+ resolve(str, onError) {
+ onError(`Unresolved plain scalar ${JSON.stringify(str)}`);
+ return str;
+ }
+};
+const schema = [map, seq].concat(jsonScalars, jsonError);
+
+export { schema };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/tags.js b/MistyCore/node_modules/yaml/browser/dist/schema/tags.js
new file mode 100644
index 0000000..f67e3e0
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/tags.js
@@ -0,0 +1,83 @@
+import { map } from './common/map.js';
+import { nullTag } from './common/null.js';
+import { seq } from './common/seq.js';
+import { string } from './common/string.js';
+import { boolTag } from './core/bool.js';
+import { float, floatExp, floatNaN } from './core/float.js';
+import { int, intHex, intOct } from './core/int.js';
+import { schema } from './core/schema.js';
+import { schema as schema$1 } from './json/schema.js';
+import { binary } from './yaml-1.1/binary.js';
+import { omap } from './yaml-1.1/omap.js';
+import { pairs } from './yaml-1.1/pairs.js';
+import { schema as schema$2 } from './yaml-1.1/schema.js';
+import { set } from './yaml-1.1/set.js';
+import { floatTime, intTime, timestamp } from './yaml-1.1/timestamp.js';
+
+const schemas = new Map([
+ ['core', schema],
+ ['failsafe', [map, seq, string]],
+ ['json', schema$1],
+ ['yaml11', schema$2],
+ ['yaml-1.1', schema$2]
+]);
+const tagsByName = {
+ binary,
+ bool: boolTag,
+ float,
+ floatExp,
+ floatNaN,
+ floatTime,
+ int,
+ intHex,
+ intOct,
+ intTime,
+ map,
+ null: nullTag,
+ omap,
+ pairs,
+ seq,
+ set,
+ timestamp
+};
+const coreKnownTags = {
+ 'tag:yaml.org,2002:binary': binary,
+ 'tag:yaml.org,2002:omap': omap,
+ 'tag:yaml.org,2002:pairs': pairs,
+ 'tag:yaml.org,2002:set': set,
+ 'tag:yaml.org,2002:timestamp': timestamp
+};
+function getTags(customTags, schemaName) {
+ let tags = schemas.get(schemaName);
+ if (!tags) {
+ if (Array.isArray(customTags))
+ tags = [];
+ else {
+ const keys = Array.from(schemas.keys())
+ .filter(key => key !== 'yaml11')
+ .map(key => JSON.stringify(key))
+ .join(', ');
+ throw new Error(`Unknown schema "${schemaName}"; use one of ${keys} or define customTags array`);
+ }
+ }
+ if (Array.isArray(customTags)) {
+ for (const tag of customTags)
+ tags = tags.concat(tag);
+ }
+ else if (typeof customTags === 'function') {
+ tags = customTags(tags.slice());
+ }
+ return tags.map(tag => {
+ if (typeof tag !== 'string')
+ return tag;
+ const tagObj = tagsByName[tag];
+ if (tagObj)
+ return tagObj;
+ const keys = Object.keys(tagsByName)
+ .map(key => JSON.stringify(key))
+ .join(', ');
+ throw new Error(`Unknown custom tag "${tag}"; use one of ${keys}`);
+ });
+}
+
+export { coreKnownTags, getTags };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js
new file mode 100644
index 0000000..a700819
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js
@@ -0,0 +1,66 @@
+import { Scalar } from '../../nodes/Scalar.js';
+import { stringifyString } from '../../stringify/stringifyString.js';
+
+const binary = {
+ identify: value => value instanceof Uint8Array,
+ default: false,
+ tag: 'tag:yaml.org,2002:binary',
+ /**
+ * Returns a Buffer in node and an Uint8Array in browsers
+ *
+ * To use the resulting buffer as an image, you'll want to do something like:
+ *
+ * const blob = new Blob([buffer], { type: 'image/jpeg' })
+ * document.querySelector('#photo').src = URL.createObjectURL(blob)
+ */
+ resolve(src, onError) {
+ if (typeof Buffer === 'function') {
+ return Buffer.from(src, 'base64');
+ }
+ else if (typeof atob === 'function') {
+ // On IE 11, atob() can't handle newlines
+ const str = atob(src.replace(/[\n\r]/g, ''));
+ const buffer = new Uint8Array(str.length);
+ for (let i = 0; i < str.length; ++i)
+ buffer[i] = str.charCodeAt(i);
+ return buffer;
+ }
+ else {
+ onError('This environment does not support reading binary tags; either Buffer or atob is required');
+ return src;
+ }
+ },
+ stringify({ comment, type, value }, ctx, onComment, onChompKeep) {
+ const buf = value; // checked earlier by binary.identify()
+ let str;
+ if (typeof Buffer === 'function') {
+ str =
+ buf instanceof Buffer
+ ? buf.toString('base64')
+ : Buffer.from(buf.buffer).toString('base64');
+ }
+ else if (typeof btoa === 'function') {
+ let s = '';
+ for (let i = 0; i < buf.length; ++i)
+ s += String.fromCharCode(buf[i]);
+ str = btoa(s);
+ }
+ else {
+ throw new Error('This environment does not support writing binary tags; either Buffer or btoa is required');
+ }
+ if (!type)
+ type = Scalar.BLOCK_LITERAL;
+ if (type !== Scalar.QUOTE_DOUBLE) {
+ const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth);
+ const n = Math.ceil(str.length / lineWidth);
+ const lines = new Array(n);
+ for (let i = 0, o = 0; i < n; ++i, o += lineWidth) {
+ lines[i] = str.substr(o, lineWidth);
+ }
+ str = lines.join(type === Scalar.BLOCK_LITERAL ? '\n' : ' ');
+ }
+ return stringifyString({ comment, type, value: str }, ctx, onComment, onChompKeep);
+ }
+};
+
+export { binary };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js
new file mode 100644
index 0000000..1ced791
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js
@@ -0,0 +1,26 @@
+import { Scalar } from '../../nodes/Scalar.js';
+
+function boolStringify({ value, source }, ctx) {
+ const boolObj = value ? trueTag : falseTag;
+ if (source && boolObj.test.test(source))
+ return source;
+ return value ? ctx.options.trueStr : ctx.options.falseStr;
+}
+const trueTag = {
+ identify: value => value === true,
+ default: true,
+ tag: 'tag:yaml.org,2002:bool',
+ test: /^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/,
+ resolve: () => new Scalar(true),
+ stringify: boolStringify
+};
+const falseTag = {
+ identify: value => value === false,
+ default: true,
+ tag: 'tag:yaml.org,2002:bool',
+ test: /^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/i,
+ resolve: () => new Scalar(false),
+ stringify: boolStringify
+};
+
+export { falseTag, trueTag };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js
new file mode 100644
index 0000000..9097266
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js
@@ -0,0 +1,46 @@
+import { Scalar } from '../../nodes/Scalar.js';
+import { stringifyNumber } from '../../stringify/stringifyNumber.js';
+
+const floatNaN = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^[-+]?\.(?:inf|Inf|INF|nan|NaN|NAN)$/,
+ resolve: (str) => str.slice(-3).toLowerCase() === 'nan'
+ ? NaN
+ : str[0] === '-'
+ ? Number.NEGATIVE_INFINITY
+ : Number.POSITIVE_INFINITY,
+ stringify: stringifyNumber
+};
+const floatExp = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ format: 'EXP',
+ test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
+ resolve: (str) => parseFloat(str.replace(/_/g, '')),
+ stringify(node) {
+ const num = Number(node.value);
+ return isFinite(num) ? num.toExponential() : stringifyNumber(node);
+ }
+};
+const float = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,
+ resolve(str) {
+ const node = new Scalar(parseFloat(str.replace(/_/g, '')));
+ const dot = str.indexOf('.');
+ if (dot !== -1) {
+ const f = str.substring(dot + 1).replace(/_/g, '');
+ if (f[f.length - 1] === '0')
+ node.minFractionDigits = f.length;
+ }
+ return node;
+ },
+ stringify: stringifyNumber
+};
+
+export { float, floatExp, floatNaN };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js
new file mode 100644
index 0000000..f572823
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js
@@ -0,0 +1,71 @@
+import { stringifyNumber } from '../../stringify/stringifyNumber.js';
+
+const intIdentify = (value) => typeof value === 'bigint' || Number.isInteger(value);
+function intResolve(str, offset, radix, { intAsBigInt }) {
+ const sign = str[0];
+ if (sign === '-' || sign === '+')
+ offset += 1;
+ str = str.substring(offset).replace(/_/g, '');
+ if (intAsBigInt) {
+ switch (radix) {
+ case 2:
+ str = `0b${str}`;
+ break;
+ case 8:
+ str = `0o${str}`;
+ break;
+ case 16:
+ str = `0x${str}`;
+ break;
+ }
+ const n = BigInt(str);
+ return sign === '-' ? BigInt(-1) * n : n;
+ }
+ const n = parseInt(str, radix);
+ return sign === '-' ? -1 * n : n;
+}
+function intStringify(node, radix, prefix) {
+ const { value } = node;
+ if (intIdentify(value)) {
+ const str = value.toString(radix);
+ return value < 0 ? '-' + prefix + str.substr(1) : prefix + str;
+ }
+ return stringifyNumber(node);
+}
+const intBin = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'BIN',
+ test: /^[-+]?0b[0-1_]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 2, 2, opt),
+ stringify: node => intStringify(node, 2, '0b')
+};
+const intOct = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'OCT',
+ test: /^[-+]?0[0-7_]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 1, 8, opt),
+ stringify: node => intStringify(node, 8, '0')
+};
+const int = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ test: /^[-+]?[0-9][0-9_]*$/,
+ resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
+ stringify: stringifyNumber
+};
+const intHex = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'HEX',
+ test: /^[-+]?0x[0-9a-fA-F_]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
+ stringify: node => intStringify(node, 16, '0x')
+};
+
+export { int, intBin, intHex, intOct };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js
new file mode 100644
index 0000000..de46d21
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js
@@ -0,0 +1,73 @@
+import { YAMLSeq } from '../../nodes/YAMLSeq.js';
+import { toJS } from '../../nodes/toJS.js';
+import { isScalar, isPair } from '../../nodes/Node.js';
+import { YAMLMap } from '../../nodes/YAMLMap.js';
+import { resolvePairs, createPairs } from './pairs.js';
+
+class YAMLOMap extends YAMLSeq {
+ constructor() {
+ super();
+ this.add = YAMLMap.prototype.add.bind(this);
+ this.delete = YAMLMap.prototype.delete.bind(this);
+ this.get = YAMLMap.prototype.get.bind(this);
+ this.has = YAMLMap.prototype.has.bind(this);
+ this.set = YAMLMap.prototype.set.bind(this);
+ this.tag = YAMLOMap.tag;
+ }
+ /**
+ * If `ctx` is given, the return type is actually `Map<unknown, unknown>`,
+ * but TypeScript won't allow widening the signature of a child method.
+ */
+ toJSON(_, ctx) {
+ if (!ctx)
+ return super.toJSON(_);
+ const map = new Map();
+ if (ctx?.onCreate)
+ ctx.onCreate(map);
+ for (const pair of this.items) {
+ let key, value;
+ if (isPair(pair)) {
+ key = toJS(pair.key, '', ctx);
+ value = toJS(pair.value, key, ctx);
+ }
+ else {
+ key = toJS(pair, '', ctx);
+ }
+ if (map.has(key))
+ throw new Error('Ordered maps must not include duplicate keys');
+ map.set(key, value);
+ }
+ return map;
+ }
+}
+YAMLOMap.tag = 'tag:yaml.org,2002:omap';
+const omap = {
+ collection: 'seq',
+ identify: value => value instanceof Map,
+ nodeClass: YAMLOMap,
+ default: false,
+ tag: 'tag:yaml.org,2002:omap',
+ resolve(seq, onError) {
+ const pairs = resolvePairs(seq, onError);
+ const seenKeys = [];
+ for (const { key } of pairs.items) {
+ if (isScalar(key)) {
+ if (seenKeys.includes(key.value)) {
+ onError(`Ordered maps must not include duplicate keys: ${key.value}`);
+ }
+ else {
+ seenKeys.push(key.value);
+ }
+ }
+ }
+ return Object.assign(new YAMLOMap(), pairs);
+ },
+ createNode(schema, iterable, ctx) {
+ const pairs = createPairs(schema, iterable, ctx);
+ const omap = new YAMLOMap();
+ omap.items = pairs.items;
+ return omap;
+ }
+};
+
+export { YAMLOMap, omap };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js
new file mode 100644
index 0000000..dd73983
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js
@@ -0,0 +1,77 @@
+import { isSeq, isPair, isMap } from '../../nodes/Node.js';
+import { Pair, createPair } from '../../nodes/Pair.js';
+import { Scalar } from '../../nodes/Scalar.js';
+import { YAMLSeq } from '../../nodes/YAMLSeq.js';
+
+function resolvePairs(seq, onError) {
+ if (isSeq(seq)) {
+ for (let i = 0; i < seq.items.length; ++i) {
+ let item = seq.items[i];
+ if (isPair(item))
+ continue;
+ else if (isMap(item)) {
+ if (item.items.length > 1)
+ onError('Each pair must have its own sequence indicator');
+ const pair = item.items[0] || new Pair(new Scalar(null));
+ if (item.commentBefore)
+ pair.key.commentBefore = pair.key.commentBefore
+ ? `${item.commentBefore}\n${pair.key.commentBefore}`
+ : item.commentBefore;
+ if (item.comment) {
+ const cn = pair.value ?? pair.key;
+ cn.comment = cn.comment
+ ? `${item.comment}\n${cn.comment}`
+ : item.comment;
+ }
+ item = pair;
+ }
+ seq.items[i] = isPair(item) ? item : new Pair(item);
+ }
+ }
+ else
+ onError('Expected a sequence for this tag');
+ return seq;
+}
+function createPairs(schema, iterable, ctx) {
+ const { replacer } = ctx;
+ const pairs = new YAMLSeq(schema);
+ pairs.tag = 'tag:yaml.org,2002:pairs';
+ let i = 0;
+ if (iterable && Symbol.iterator in Object(iterable))
+ for (let it of iterable) {
+ if (typeof replacer === 'function')
+ it = replacer.call(iterable, String(i++), it);
+ let key, value;
+ if (Array.isArray(it)) {
+ if (it.length === 2) {
+ key = it[0];
+ value = it[1];
+ }
+ else
+ throw new TypeError(`Expected [key, value] tuple: ${it}`);
+ }
+ else if (it && it instanceof Object) {
+ const keys = Object.keys(it);
+ if (keys.length === 1) {
+ key = keys[0];
+ value = it[key];
+ }
+ else
+ throw new TypeError(`Expected { key: value } tuple: ${it}`);
+ }
+ else {
+ key = it;
+ }
+ pairs.items.push(createPair(key, value, ctx));
+ }
+ return pairs;
+}
+const pairs = {
+ collection: 'seq',
+ default: false,
+ tag: 'tag:yaml.org,2002:pairs',
+ resolve: resolvePairs,
+ createNode: createPairs
+};
+
+export { createPairs, pairs, resolvePairs };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js
new file mode 100644
index 0000000..dc5be5f
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js
@@ -0,0 +1,37 @@
+import { map } from '../common/map.js';
+import { nullTag } from '../common/null.js';
+import { seq } from '../common/seq.js';
+import { string } from '../common/string.js';
+import { binary } from './binary.js';
+import { trueTag, falseTag } from './bool.js';
+import { floatNaN, floatExp, float } from './float.js';
+import { intBin, intOct, int, intHex } from './int.js';
+import { omap } from './omap.js';
+import { pairs } from './pairs.js';
+import { set } from './set.js';
+import { intTime, floatTime, timestamp } from './timestamp.js';
+
+const schema = [
+ map,
+ seq,
+ string,
+ nullTag,
+ trueTag,
+ falseTag,
+ intBin,
+ intOct,
+ int,
+ intHex,
+ floatNaN,
+ floatExp,
+ float,
+ binary,
+ omap,
+ pairs,
+ set,
+ intTime,
+ floatTime,
+ timestamp
+];
+
+export { schema };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js
new file mode 100644
index 0000000..9e43dad
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js
@@ -0,0 +1,92 @@
+import { isMap, isPair, isScalar } from '../../nodes/Node.js';
+import { createPair, Pair } from '../../nodes/Pair.js';
+import { YAMLMap, findPair } from '../../nodes/YAMLMap.js';
+
+class YAMLSet extends YAMLMap {
+ constructor(schema) {
+ super(schema);
+ this.tag = YAMLSet.tag;
+ }
+ add(key) {
+ let pair;
+ if (isPair(key))
+ pair = key;
+ else if (key &&
+ typeof key === 'object' &&
+ 'key' in key &&
+ 'value' in key &&
+ key.value === null)
+ pair = new Pair(key.key, null);
+ else
+ pair = new Pair(key, null);
+ const prev = findPair(this.items, pair.key);
+ if (!prev)
+ this.items.push(pair);
+ }
+ /**
+ * If `keepPair` is `true`, returns the Pair matching `key`.
+ * Otherwise, returns the value of that Pair's key.
+ */
+ get(key, keepPair) {
+ const pair = findPair(this.items, key);
+ return !keepPair && isPair(pair)
+ ? isScalar(pair.key)
+ ? pair.key.value
+ : pair.key
+ : pair;
+ }
+ set(key, value) {
+ if (typeof value !== 'boolean')
+ throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof value}`);
+ const prev = findPair(this.items, key);
+ if (prev && !value) {
+ this.items.splice(this.items.indexOf(prev), 1);
+ }
+ else if (!prev && value) {
+ this.items.push(new Pair(key));
+ }
+ }
+ toJSON(_, ctx) {
+ return super.toJSON(_, ctx, Set);
+ }
+ toString(ctx, onComment, onChompKeep) {
+ if (!ctx)
+ return JSON.stringify(this);
+ if (this.hasAllNullValues(true))
+ return super.toString(Object.assign({}, ctx, { allNullValues: true }), onComment, onChompKeep);
+ else
+ throw new Error('Set items must all have null values');
+ }
+}
+YAMLSet.tag = 'tag:yaml.org,2002:set';
+const set = {
+ collection: 'map',
+ identify: value => value instanceof Set,
+ nodeClass: YAMLSet,
+ default: false,
+ tag: 'tag:yaml.org,2002:set',
+ resolve(map, onError) {
+ if (isMap(map)) {
+ if (map.hasAllNullValues(true))
+ return Object.assign(new YAMLSet(), map);
+ else
+ onError('Set items must all have null values');
+ }
+ else
+ onError('Expected a mapping for this tag');
+ return map;
+ },
+ createNode(schema, iterable, ctx) {
+ const { replacer } = ctx;
+ const set = new YAMLSet(schema);
+ if (iterable && Symbol.iterator in Object(iterable))
+ for (let value of iterable) {
+ if (typeof replacer === 'function')
+ value = replacer.call(iterable, value, value);
+ set.items.push(createPair(value, null, ctx));
+ }
+ return set;
+ }
+};
+
+export { YAMLSet, set };
diff --git a/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js
new file mode 100644
index 0000000..7013cda
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js
@@ -0,0 +1,101 @@
+import { stringifyNumber } from '../../stringify/stringifyNumber.js';
+
+/** Internal types handle bigint as number, because TS can't figure it out. */
+function parseSexagesimal(str, asBigInt) {
+ const sign = str[0];
+ const parts = sign === '-' || sign === '+' ? str.substring(1) : str;
+ const num = (n) => asBigInt ? BigInt(n) : Number(n);
+ const res = parts
+ .replace(/_/g, '')
+ .split(':')
+ .reduce((res, p) => res * num(60) + num(p), num(0));
+ return (sign === '-' ? num(-1) * res : res);
+}
+/**
+ * hhhh:mm:ss.sss
+ *
+ * Internal types handle bigint as number, because TS can't figure it out.
+ */
+function stringifySexagesimal(node) {
+ let { value } = node;
+ let num = (n) => n;
+ if (typeof value === 'bigint')
+ num = n => BigInt(n);
+ else if (isNaN(value) || !isFinite(value))
+ return stringifyNumber(node);
+ let sign = '';
+ if (value < 0) {
+ sign = '-';
+ value *= num(-1);
+ }
+ const _60 = num(60);
+ const parts = [value % _60]; // seconds, including ms
+ if (value < 60) {
+ parts.unshift(0); // at least one : is required
+ }
+ else {
+ value = (value - parts[0]) / _60;
+ parts.unshift(value % _60); // minutes
+ if (value >= 60) {
+ value = (value - parts[0]) / _60;
+ parts.unshift(value); // hours
+ }
+ }
+ return (sign +
+ parts
+ .map(n => (n < 10 ? '0' + String(n) : String(n)))
+ .join(':')
+ .replace(/000000\d*$/, '') // % 60 may introduce error
+ );
+}
+const intTime = {
+ identify: value => typeof value === 'bigint' || Number.isInteger(value),
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'TIME',
+ test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,
+ resolve: (str, _onError, { intAsBigInt }) => parseSexagesimal(str, intAsBigInt),
+ stringify: stringifySexagesimal
+};
+const floatTime = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ format: 'TIME',
+ test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,
+ resolve: str => parseSexagesimal(str, false),
+ stringify: stringifySexagesimal
+};
+const timestamp = {
+ identify: value => value instanceof Date,
+ default: true,
+ tag: 'tag:yaml.org,2002:timestamp',
+ // If the time zone is omitted, the timestamp is assumed to be specified in UTC. The time part
+ // may be omitted altogether, resulting in a date format. In such a case, the time part is
+ // assumed to be 00:00:00Z (start of day, UTC).
+ test: RegExp('^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})' + // YYYY-Mm-Dd
+ '(?:' + // time is optional
+ '(?:t|T|[ \\t]+)' + // t | T | whitespace
+ '([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)' + // Hh:Mm:Ss(.ss)?
+ '(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?' + // Z | +5 | -03:30
+ ')?$'),
+ resolve(str) {
+ const match = str.match(timestamp.test);
+ if (!match)
+ throw new Error('!!timestamp expects a date, starting with yyyy-mm-dd');
+ const [, year, month, day, hour, minute, second] = match.map(Number);
+ const millisec = match[7] ? Number((match[7] + '00').substr(1, 3)) : 0;
+ let date = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
+ const tz = match[8];
+ if (tz && tz !== 'Z') {
+ let d = parseSexagesimal(tz, false);
+ if (Math.abs(d) < 30)
+ d *= 60;
+ date -= 60000 * d;
+ }
+ return new Date(date);
+ },
+ stringify: ({ value }) => value.toISOString().replace(/((T00:00)?:00)?\.000Z$/, '')
+};
+
+export { floatTime, intTime, timestamp };
diff --git a/MistyCore/node_modules/yaml/browser/dist/stringify/foldFlowLines.js b/MistyCore/node_modules/yaml/browser/dist/stringify/foldFlowLines.js
new file mode 100644
index 0000000..01fe787
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/stringify/foldFlowLines.js
@@ -0,0 +1,135 @@
+const FOLD_FLOW = 'flow';
+const FOLD_BLOCK = 'block';
+const FOLD_QUOTED = 'quoted';
+/**
+ * Tries to keep input at up to `lineWidth` characters, splitting only on spaces
+ * not followed by newlines or spaces unless `mode` is `'quoted'`. Lines are
+ * terminated with `\n` and started with `indent`.
+ */
+function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
+ if (!lineWidth || lineWidth < 0)
+ return text;
+ const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
+ if (text.length <= endStep)
+ return text;
+ const folds = [];
+ const escapedFolds = {};
+ let end = lineWidth - indent.length;
+ if (typeof indentAtStart === 'number') {
+ if (indentAtStart > lineWidth - Math.max(2, minContentWidth))
+ folds.push(0);
+ else
+ end = lineWidth - indentAtStart;
+ }
+ let split = undefined;
+ let prev = undefined;
+ let overflow = false;
+ let i = -1;
+ let escStart = -1;
+ let escEnd = -1;
+ if (mode === FOLD_BLOCK) {
+ i = consumeMoreIndentedLines(text, i);
+ if (i !== -1)
+ end = i + endStep;
+ }
+ for (let ch; (ch = text[(i += 1)]);) {
+ if (mode === FOLD_QUOTED && ch === '\\') {
+ escStart = i;
+ switch (text[i + 1]) {
+ case 'x':
+ i += 3;
+ break;
+ case 'u':
+ i += 5;
+ break;
+ case 'U':
+ i += 9;
+ break;
+ default:
+ i += 1;
+ }
+ escEnd = i;
+ }
+ if (ch === '\n') {
+ if (mode === FOLD_BLOCK)
+ i = consumeMoreIndentedLines(text, i);
+ end = i + endStep;
+ split = undefined;
+ }
+ else {
+ if (ch === ' ' &&
+ prev &&
+ prev !== ' ' &&
+ prev !== '\n' &&
+ prev !== '\t') {
+ // space surrounded by non-space can be replaced with newline + indent
+ const next = text[i + 1];
+ if (next && next !== ' ' && next !== '\n' && next !== '\t')
+ split = i;
+ }
+ if (i >= end) {
+ if (split) {
+ folds.push(split);
+ end = split + endStep;
+ split = undefined;
+ }
+ else if (mode === FOLD_QUOTED) {
+ // white-space collected at end may stretch past lineWidth
+ while (prev === ' ' || prev === '\t') {
+ prev = ch;
+ ch = text[(i += 1)];
+ overflow = true;
+ }
+ // Account for newline escape, but don't break preceding escape
+ const j = i > escEnd + 1 ? i - 2 : escStart - 1;
+ // Bail out if lineWidth & minContentWidth are shorter than an escape string
+ if (escapedFolds[j])
+ return text;
+ folds.push(j);
+ escapedFolds[j] = true;
+ end = j + endStep;
+ split = undefined;
+ }
+ else {
+ overflow = true;
+ }
+ }
+ }
+ prev = ch;
+ }
+ if (overflow && onOverflow)
+ onOverflow();
+ if (folds.length === 0)
+ return text;
+ if (onFold)
+ onFold();
+ let res = text.slice(0, folds[0]);
+ for (let i = 0; i < folds.length; ++i) {
+ const fold = folds[i];
+ const end = folds[i + 1] || text.length;
+ if (fold === 0)
+ res = `\n${indent}${text.slice(0, end)}`;
+ else {
+ if (mode === FOLD_QUOTED && escapedFolds[fold])
+ res += `${text[fold]}\\`;
+ res += `\n${indent}${text.slice(fold + 1, end)}`;
+ }
+ }
+ return res;
+}
+/**
+ * Presumes `i + 1` is at the start of a line
+ * @returns index of last newline in more-indented block
+ */
+function consumeMoreIndentedLines(text, i) {
+ let ch = text[i + 1];
+ while (ch === ' ' || ch === '\t') {
+ do {
+ ch = text[(i += 1)];
+ } while (ch && ch !== '\n');
+ ch = text[i + 1];
+ }
+ return i;
+}
+
+export { FOLD_BLOCK, FOLD_FLOW, FOLD_QUOTED, foldFlowLines };
diff --git a/MistyCore/node_modules/yaml/browser/dist/stringify/stringify.js b/MistyCore/node_modules/yaml/browser/dist/stringify/stringify.js
new file mode 100644
index 0000000..133e162
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/stringify/stringify.js
@@ -0,0 +1,122 @@
+import { anchorIsValid } from '../doc/anchors.js';
+import { isPair, isAlias, isNode, isScalar, isCollection } from '../nodes/Node.js';
+import { stringifyComment } from './stringifyComment.js';
+import { stringifyString } from './stringifyString.js';
+
+function createStringifyContext(doc, options) {
+ const opt = Object.assign({
+ blockQuote: true,
+ commentString: stringifyComment,
+ defaultKeyType: null,
+ defaultStringType: 'PLAIN',
+ directives: null,
+ doubleQuotedAsJSON: false,
+ doubleQuotedMinMultiLineLength: 40,
+ falseStr: 'false',
+ indentSeq: true,
+ lineWidth: 80,
+ minContentWidth: 20,
+ nullStr: 'null',
+ simpleKeys: false,
+ singleQuote: null,
+ trueStr: 'true',
+ verifyAliasOrder: true
+ }, doc.schema.toStringOptions, options);
+ let inFlow;
+ switch (opt.collectionStyle) {
+ case 'block':
+ inFlow = false;
+ break;
+ case 'flow':
+ inFlow = true;
+ break;
+ default:
+ inFlow = null;
+ }
+ return {
+ anchors: new Set(),
+ doc,
+ indent: '',
+ indentStep: typeof opt.indent === 'number' ? ' '.repeat(opt.indent) : ' ',
+ inFlow,
+ options: opt
+ };
+}
+function getTagObject(tags, item) {
+ if (item.tag) {
+ const match = tags.filter(t => t.tag === item.tag);
+ if (match.length > 0)
+ return match.find(t => t.format === item.format) ?? match[0];
+ }
+ let tagObj = undefined;
+ let obj;
+ if (isScalar(item)) {
+ obj = item.value;
+ const match = tags.filter(t => t.identify?.(obj));
+ tagObj =
+ match.find(t => t.format === item.format) ?? match.find(t => !t.format);
+ }
+ else {
+ obj = item;
+ tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass);
+ }
+ if (!tagObj) {
+ const name = obj?.constructor?.name ?? typeof obj;
+ throw new Error(`Tag not resolved for ${name} value`);
+ }
+ return tagObj;
+}
+// needs to be called before value stringifier to allow for circular anchor refs
+function stringifyProps(node, tagObj, { anchors, doc }) {
+ if (!doc.directives)
+ return '';
+ const props = [];
+ const anchor = (isScalar(node) || isCollection(node)) && node.anchor;
+ if (anchor && anchorIsValid(anchor)) {
+ anchors.add(anchor);
+ props.push(`&${anchor}`);
+ }
+ const tag = node.tag ? node.tag : tagObj.default ? null : tagObj.tag;
+ if (tag)
+ props.push(doc.directives.tagString(tag));
+ return props.join(' ');
+}
+function stringify(item, ctx, onComment, onChompKeep) {
+ if (isPair(item))
+ return item.toString(ctx, onComment, onChompKeep);
+ if (isAlias(item)) {
+ if (ctx.doc.directives)
+ return item.toString(ctx);
+ if (ctx.resolvedAliases?.has(item)) {
+ throw new TypeError(`Cannot stringify circular structure without alias nodes`);
+ }
+ else {
+ if (ctx.resolvedAliases)
+ ctx.resolvedAliases.add(item);
+ else
+ ctx.resolvedAliases = new Set([item]);
+ item = item.resolve(ctx.doc);
+ }
+ }
+ let tagObj = undefined;
+ const node = isNode(item)
+ ? item
+ : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) });
+ if (!tagObj)
+ tagObj = getTagObject(ctx.doc.schema.tags, node);
+ const props = stringifyProps(node, tagObj, ctx);
+ if (props.length > 0)
+ ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
+ const str = typeof tagObj.stringify === 'function'
+ ? tagObj.stringify(node, ctx, onComment, onChompKeep)
+ : isScalar(node)
+ ? stringifyString(node, ctx, onComment, onChompKeep)
+ : node.toString(ctx, onComment, onChompKeep);
+ if (!props)
+ return str;
+ return isScalar(node) || str[0] === '{' || str[0] === '['
+ ? `${props} ${str}`
+ : `${props}\n${ctx.indent}${str}`;
+}
+
+export { createStringifyContext, stringify };
diff --git a/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyCollection.js b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyCollection.js
new file mode 100644
index 0000000..8296318
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyCollection.js
@@ -0,0 +1,151 @@
+import { Collection } from '../nodes/Collection.js';
+import { isNode, isPair } from '../nodes/Node.js';
+import { stringify } from './stringify.js';
+import { lineComment, indentComment } from './stringifyComment.js';
+
+function stringifyCollection(collection, ctx, options) {
+ const flow = ctx.inFlow ?? collection.flow;
+ const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
+ return stringify(collection, ctx, options);
+}
+function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
+ const { indent, options: { commentString } } = ctx;
+ const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
+ let chompKeep = false; // flag for the preceding node's status
+ const lines = [];
+ for (let i = 0; i < items.length; ++i) {
+ const item = items[i];
+ let comment = null;
+ if (isNode(item)) {
+ if (!chompKeep && item.spaceBefore)
+ lines.push('');
+ addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
+ if (item.comment)
+ comment = item.comment;
+ }
+ else if (isPair(item)) {
+ const ik = isNode(item.key) ? item.key : null;
+ if (ik) {
+ if (!chompKeep && ik.spaceBefore)
+ lines.push('');
+ addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
+ }
+ }
+ chompKeep = false;
+ let str = stringify(item, itemCtx, () => (comment = null), () => (chompKeep = true));
+ if (comment)
+ str += lineComment(str, itemIndent, commentString(comment));
+ if (chompKeep && comment)
+ chompKeep = false;
+ lines.push(blockItemPrefix + str);
+ }
+ let str;
+ if (lines.length === 0) {
+ str = flowChars.start + flowChars.end;
+ }
+ else {
+ str = lines[0];
+ for (let i = 1; i < lines.length; ++i) {
+ const line = lines[i];
+ str += line ? `\n${indent}${line}` : '\n';
+ }
+ }
+ if (comment) {
+ str += '\n' + indentComment(commentString(comment), indent);
+ if (onComment)
+ onComment();
+ }
+ else if (chompKeep && onChompKeep)
+ onChompKeep();
+ return str;
+}
+function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemIndent, onComment }) {
+ const { indent, indentStep, options: { commentString } } = ctx;
+ itemIndent += indentStep;
+ const itemCtx = Object.assign({}, ctx, {
+ indent: itemIndent,
+ inFlow: true,
+ type: null
+ });
+ let reqNewline = false;
+ let linesAtValue = 0;
+ const lines = [];
+ for (let i = 0; i < items.length; ++i) {
+ const item = items[i];
+ let comment = null;
+ if (isNode(item)) {
+ if (item.spaceBefore)
+ lines.push('');
+ addCommentBefore(ctx, lines, item.commentBefore, false);
+ if (item.comment)
+ comment = item.comment;
+ }
+ else if (isPair(item)) {
+ const ik = isNode(item.key) ? item.key : null;
+ if (ik) {
+ if (ik.spaceBefore)
+ lines.push('');
+ addCommentBefore(ctx, lines, ik.commentBefore, false);
+ if (ik.comment)
+ reqNewline = true;
+ }
+ const iv = isNode(item.value) ? item.value : null;
+ if (iv) {
+ if (iv.comment)
+ comment = iv.comment;
+ if (iv.commentBefore)
+ reqNewline = true;
+ }
+ else if (item.value == null && ik && ik.comment) {
+ comment = ik.comment;
+ }
+ }
+ if (comment)
+ reqNewline = true;
+ let str = stringify(item, itemCtx, () => (comment = null));
+ if (i < items.length - 1)
+ str += ',';
+ if (comment)
+ str += lineComment(str, itemIndent, commentString(comment));
+ if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
+ reqNewline = true;
+ lines.push(str);
+ linesAtValue = lines.length;
+ }
+ let str;
+ const { start, end } = flowChars;
+ if (lines.length === 0) {
+ str = start + end;
+ }
+ else {
+ if (!reqNewline) {
+ const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
+ reqNewline = len > Collection.maxFlowStringSingleLineLength;
+ }
+ if (reqNewline) {
+ str = start;
+ for (const line of lines)
+ str += line ? `\n${indentStep}${indent}${line}` : '\n';
+ str += `\n${indent}${end}`;
+ }
+ else {
+ str = `${start} ${lines.join(' ')} ${end}`;
+ }
+ }
+ if (comment) {
+ str += lineComment(str, commentString(comment), indent);
+ if (onComment)
+ onComment();
+ }
+ return str;
+}
+function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
+ if (comment && chompKeep)
+ comment = comment.replace(/^\n+/, '');
+ if (comment) {
+ const ic = indentComment(commentString(comment), indent);
+ lines.push(ic.trimStart()); // Avoid double indent on first line
+ }
+}
+
+export { stringifyCollection };
diff --git a/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyComment.js b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyComment.js
new file mode 100644
index 0000000..f16fc91
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyComment.js
@@ -0,0 +1,20 @@
+/**
+ * Stringifies a comment.
+ *
+ * Empty comment lines are left empty,
+ * lines consisting of a single space are replaced by `#`,
+ * and all other lines are prefixed with a `#`.
+ */
+const stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, '#');
+function indentComment(comment, indent) {
+ if (/^\n+$/.test(comment))
+ return comment.substring(1);
+ return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
+}
+const lineComment = (str, indent, comment) => str.endsWith('\n')
+ ? indentComment(comment, indent)
+ : comment.includes('\n')
+ ? '\n' + indentComment(comment, indent)
+ : (str.endsWith(' ') ? '' : ' ') + comment;
+
+export { indentComment, lineComment, stringifyComment };
diff --git a/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyDocument.js b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyDocument.js
new file mode 100644
index 0000000..e288c5d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyDocument.js
@@ -0,0 +1,85 @@
+import { isNode } from '../nodes/Node.js';
+import { createStringifyContext, stringify } from './stringify.js';
+import { indentComment, lineComment } from './stringifyComment.js';
+
+function stringifyDocument(doc, options) {
+ const lines = [];
+ let hasDirectives = options.directives === true;
+ if (options.directives !== false && doc.directives) {
+ const dir = doc.directives.toString(doc);
+ if (dir) {
+ lines.push(dir);
+ hasDirectives = true;
+ }
+ else if (doc.directives.docStart)
+ hasDirectives = true;
+ }
+ if (hasDirectives)
+ lines.push('---');
+ const ctx = createStringifyContext(doc, options);
+ const { commentString } = ctx.options;
+ if (doc.commentBefore) {
+ if (lines.length !== 1)
+ lines.unshift('');
+ const cs = commentString(doc.commentBefore);
+ lines.unshift(indentComment(cs, ''));
+ }
+ let chompKeep = false;
+ let contentComment = null;
+ if (doc.contents) {
+ if (isNode(doc.contents)) {
+ if (doc.contents.spaceBefore && hasDirectives)
+ lines.push('');
+ if (doc.contents.commentBefore) {
+ const cs = commentString(doc.contents.commentBefore);
+ lines.push(indentComment(cs, ''));
+ }
+ // top-level block scalars need to be indented if followed by a comment
+ ctx.forceBlockIndent = !!doc.comment;
+ contentComment = doc.contents.comment;
+ }
+ const onChompKeep = contentComment ? undefined : () => (chompKeep = true);
+ let body = stringify(doc.contents, ctx, () => (contentComment = null), onChompKeep);
+ if (contentComment)
+ body += lineComment(body, '', commentString(contentComment));
+ if ((body[0] === '|' || body[0] === '>') &&
+ lines[lines.length - 1] === '---') {
+ // Top-level block scalars with a preceding doc marker ought to use the
+ // same line for their header.
+ lines[lines.length - 1] = `--- ${body}`;
+ }
+ else
+ lines.push(body);
+ }
+ else {
+ lines.push(stringify(doc.contents, ctx));
+ }
+ if (doc.directives?.docEnd) {
+ if (doc.comment) {
+ const cs = commentString(doc.comment);
+ if (cs.includes('\n')) {
+ lines.push('...');
+ lines.push(indentComment(cs, ''));
+ }
+ else {
+ lines.push(`... ${cs}`);
+ }
+ }
+ else {
+ lines.push('...');
+ }
+ }
+ else {
+ let dc = doc.comment;
+ if (dc && chompKeep)
+ dc = dc.replace(/^\n+/, '');
+ if (dc) {
+ if ((!chompKeep || contentComment) && lines[lines.length - 1] !== '')
+ lines.push('');
+ lines.push(indentComment(commentString(dc), ''));
+ }
+ }
+ return lines.join('\n') + '\n';
+}
+
+export { stringifyDocument };
diff --git a/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyNumber.js b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyNumber.js
new file mode 100644
index 0000000..3fa35f9
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyNumber.js
@@ -0,0 +1,24 @@
+function stringifyNumber({ format, minFractionDigits, tag, value }) {
+ if (typeof value === 'bigint')
+ return String(value);
+ const num = typeof value === 'number' ? value : Number(value);
+ if (!isFinite(num))
+ return isNaN(num) ? '.nan' : num < 0 ? '-.inf' : '.inf';
+ let n = JSON.stringify(value);
+ if (!format &&
+ minFractionDigits &&
+ (!tag || tag === 'tag:yaml.org,2002:float') &&
+ /^\d/.test(n)) {
+ let i = n.indexOf('.');
+ if (i < 0) {
+ i = n.length;
+ n += '.';
+ }
+ let d = minFractionDigits - (n.length - i - 1);
+ while (d-- > 0)
+ n += '0';
+ }
+ return n;
+}
+
+export { stringifyNumber };
diff --git a/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyPair.js b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyPair.js
new file mode 100644
index 0000000..6243b0e
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyPair.js
@@ -0,0 +1,125 @@
+import { isCollection, isNode, isScalar, isSeq } from '../nodes/Node.js';
+import { Scalar } from '../nodes/Scalar.js';
+import { stringify } from './stringify.js';
+import { lineComment, indentComment } from './stringifyComment.js';
+
+function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
+ const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
+ let keyComment = (isNode(key) && key.comment) || null;
+ if (simpleKeys) {
+ if (keyComment) {
+ throw new Error('With simple keys, key nodes cannot have comments');
+ }
+ if (isCollection(key)) {
+ const msg = 'With simple keys, collection cannot be used as a key value';
+ throw new Error(msg);
+ }
+ }
+ let explicitKey = !simpleKeys &&
+ (!key ||
+ (keyComment && value == null && !ctx.inFlow) ||
+ isCollection(key) ||
+ (isScalar(key)
+ ? key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL
+ : typeof key === 'object'));
+ ctx = Object.assign({}, ctx, {
+ allNullValues: false,
+ implicitKey: !explicitKey && (simpleKeys || !allNullValues),
+ indent: indent + indentStep
+ });
+ let keyCommentDone = false;
+ let chompKeep = false;
+ let str = stringify(key, ctx, () => (keyCommentDone = true), () => (chompKeep = true));
+ if (!explicitKey && !ctx.inFlow && str.length > 1024) {
+ if (simpleKeys)
+ throw new Error('With simple keys, single line scalar must not span more than 1024 characters');
+ explicitKey = true;
+ }
+ if (ctx.inFlow) {
+ if (allNullValues || value == null) {
+ if (keyCommentDone && onComment)
+ onComment();
+ return str === '' ? '?' : explicitKey ? `? ${str}` : str;
+ }
+ }
+ else if ((allNullValues && !simpleKeys) || (value == null && explicitKey)) {
+ str = `? ${str}`;
+ if (keyComment && !keyCommentDone) {
+ str += lineComment(str, ctx.indent, commentString(keyComment));
+ }
+ else if (chompKeep && onChompKeep)
+ onChompKeep();
+ return str;
+ }
+ if (keyCommentDone)
+ keyComment = null;
+ if (explicitKey) {
+ if (keyComment)
+ str += lineComment(str, ctx.indent, commentString(keyComment));
+ str = `? ${str}\n${indent}:`;
+ }
+ else {
+ str = `${str}:`;
+ if (keyComment)
+ str += lineComment(str, ctx.indent, commentString(keyComment));
+ }
+ let vcb = '';
+ let valueComment = null;
+ if (isNode(value)) {
+ if (value.spaceBefore)
+ vcb = '\n';
+ if (value.commentBefore) {
+ const cs = commentString(value.commentBefore);
+ vcb += `\n${indentComment(cs, ctx.indent)}`;
+ }
+ valueComment = value.comment;
+ }
+ else if (value && typeof value === 'object') {
+ value = doc.createNode(value);
+ }
+ ctx.implicitKey = false;
+ if (!explicitKey && !keyComment && isScalar(value))
+ ctx.indentAtStart = str.length + 1;
+ chompKeep = false;
+ if (!indentSeq &&
+ indentStep.length >= 2 &&
+ !ctx.inFlow &&
+ !explicitKey &&
+ isSeq(value) &&
+ !value.flow &&
+ !value.tag &&
+ !value.anchor) {
+ // If indentSeq === false, consider '- ' as part of indentation where possible
+ ctx.indent = ctx.indent.substr(2);
+ }
+ let valueCommentDone = false;
+ const valueStr = stringify(value, ctx, () => (valueCommentDone = true), () => (chompKeep = true));
+ let ws = ' ';
+ if (vcb || keyComment) {
+ if (valueStr === '' && !ctx.inFlow)
+ ws = vcb === '\n' ? '\n\n' : vcb;
+ else
+ ws = `${vcb}\n${ctx.indent}`;
+ }
+ else if (!explicitKey && isCollection(value)) {
+ const flow = valueStr[0] === '[' || valueStr[0] === '{';
+ if (!flow || valueStr.includes('\n'))
+ ws = `\n${ctx.indent}`;
+ }
+ else if (valueStr === '' || valueStr[0] === '\n')
+ ws = '';
+ str += ws + valueStr;
+ if (ctx.inFlow) {
+ if (valueCommentDone && onComment)
+ onComment();
+ }
+ else if (valueComment && !valueCommentDone) {
+ str += lineComment(str, ctx.indent, commentString(valueComment));
+ }
+ else if (chompKeep && onChompKeep) {
+ onChompKeep();
+ }
+ return str;
+}
+
+export { stringifyPair };
diff --git a/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyString.js b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyString.js
new file mode 100644
index 0000000..d1373e9
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/stringify/stringifyString.js
@@ -0,0 +1,314 @@
+import { Scalar } from '../nodes/Scalar.js';
+import { foldFlowLines, FOLD_QUOTED, FOLD_FLOW, FOLD_BLOCK } from './foldFlowLines.js';
+
+const getFoldOptions = (ctx) => ({
+ indentAtStart: ctx.indentAtStart,
+ lineWidth: ctx.options.lineWidth,
+ minContentWidth: ctx.options.minContentWidth
+});
+// Also checks for lines starting with %, as parsing the output as YAML 1.1 will
+// presume that's starting a new document.
+const containsDocumentMarker = (str) => /^(%|---|\.\.\.)/m.test(str);
+function lineLengthOverLimit(str, lineWidth, indentLength) {
+ if (!lineWidth || lineWidth < 0)
+ return false;
+ const limit = lineWidth - indentLength;
+ const strLen = str.length;
+ if (strLen <= limit)
+ return false;
+ for (let i = 0, start = 0; i < strLen; ++i) {
+ if (str[i] === '\n') {
+ if (i - start > limit)
+ return true;
+ start = i + 1;
+ if (strLen - start <= limit)
+ return false;
+ }
+ }
+ return true;
+}
+function doubleQuotedString(value, ctx) {
+ const json = JSON.stringify(value);
+ if (ctx.options.doubleQuotedAsJSON)
+ return json;
+ const { implicitKey } = ctx;
+ const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength;
+ const indent = ctx.indent || (containsDocumentMarker(value) ? ' ' : '');
+ let str = '';
+ let start = 0;
+ for (let i = 0, ch = json[i]; ch; ch = json[++i]) {
+ if (ch === ' ' && json[i + 1] === '\\' && json[i + 2] === 'n') {
+ // space before newline needs to be escaped to not be folded
+ str += json.slice(start, i) + '\\ ';
+ i += 1;
+ start = i;
+ ch = '\\';
+ }
+ if (ch === '\\')
+ switch (json[i + 1]) {
+ case 'u':
+ {
+ str += json.slice(start, i);
+ const code = json.substr(i + 2, 4);
+ switch (code) {
+ case '0000':
+ str += '\\0';
+ break;
+ case '0007':
+ str += '\\a';
+ break;
+ case '000b':
+ str += '\\v';
+ break;
+ case '001b':
+ str += '\\e';
+ break;
+ case '0085':
+ str += '\\N';
+ break;
+ case '00a0':
+ str += '\\_';
+ break;
+ case '2028':
+ str += '\\L';
+ break;
+ case '2029':
+ str += '\\P';
+ break;
+ default:
+ if (code.substr(0, 2) === '00')
+ str += '\\x' + code.substr(2);
+ else
+ str += json.substr(i, 6);
+ }
+ i += 5;
+ start = i + 1;
+ }
+ break;
+ case 'n':
+ if (implicitKey ||
+ json[i + 2] === '"' ||
+ json.length < minMultiLineLength) {
+ i += 1;
+ }
+ else {
+ // folding will eat first newline
+ str += json.slice(start, i) + '\n\n';
+ while (json[i + 2] === '\\' &&
+ json[i + 3] === 'n' &&
+ json[i + 4] !== '"') {
+ str += '\n';
+ i += 2;
+ }
+ str += indent;
+ // space after newline needs to be escaped to not be folded
+ if (json[i + 2] === ' ')
+ str += '\\';
+ i += 1;
+ start = i + 1;
+ }
+ break;
+ default:
+ i += 1;
+ }
+ }
+ str = start ? str + json.slice(start) : json;
+ return implicitKey
+ ? str
+ : foldFlowLines(str, indent, FOLD_QUOTED, getFoldOptions(ctx));
+}
+function singleQuotedString(value, ctx) {
+ if (ctx.options.singleQuote === false ||
+ (ctx.implicitKey && value.includes('\n')) ||
+ /[ \t]\n|\n[ \t]/.test(value) // single quoted string can't have leading or trailing whitespace around newline
+ )
+ return doubleQuotedString(value, ctx);
+ const indent = ctx.indent || (containsDocumentMarker(value) ? ' ' : '');
+ const res = "'" + value.replace(/'/g, "''").replace(/\n+/g, `$&\n${indent}`) + "'";
+ return ctx.implicitKey
+ ? res
+ : foldFlowLines(res, indent, FOLD_FLOW, getFoldOptions(ctx));
+}
+function quotedString(value, ctx) {
+ const { singleQuote } = ctx.options;
+ let qs;
+ if (singleQuote === false)
+ qs = doubleQuotedString;
+ else {
+ const hasDouble = value.includes('"');
+ const hasSingle = value.includes("'");
+ if (hasDouble && !hasSingle)
+ qs = singleQuotedString;
+ else if (hasSingle && !hasDouble)
+ qs = doubleQuotedString;
+ else
+ qs = singleQuote ? singleQuotedString : doubleQuotedString;
+ }
+ return qs(value, ctx);
+}
+function blockString({ comment, type, value }, ctx, onComment, onChompKeep) {
+ const { blockQuote, commentString, lineWidth } = ctx.options;
+ // 1. Block can't end in whitespace unless the last line is non-empty.
+ // 2. Strings consisting of only whitespace are best rendered explicitly.
+ if (!blockQuote || /\n[\t ]+$/.test(value) || /^\s*$/.test(value)) {
+ return quotedString(value, ctx);
+ }
+ const indent = ctx.indent ||
+ (ctx.forceBlockIndent || containsDocumentMarker(value) ? ' ' : '');
+ const literal = blockQuote === 'literal'
+ ? true
+ : blockQuote === 'folded' || type === Scalar.BLOCK_FOLDED
+ ? false
+ : type === Scalar.BLOCK_LITERAL
+ ? true
+ : !lineLengthOverLimit(value, lineWidth, indent.length);
+ if (!value)
+ return literal ? '|\n' : '>\n';
+ // determine chomping from whitespace at value end
+ let chomp;
+ let endStart;
+ for (endStart = value.length; endStart > 0; --endStart) {
+ const ch = value[endStart - 1];
+ if (ch !== '\n' && ch !== '\t' && ch !== ' ')
+ break;
+ }
+ let end = value.substring(endStart);
+ const endNlPos = end.indexOf('\n');
+ if (endNlPos === -1) {
+ chomp = '-'; // strip
+ }
+ else if (value === end || endNlPos !== end.length - 1) {
+ chomp = '+'; // keep
+ if (onChompKeep)
+ onChompKeep();
+ }
+ else {
+ chomp = ''; // clip
+ }
+ if (end) {
+ value = value.slice(0, -end.length);
+ if (end[end.length - 1] === '\n')
+ end = end.slice(0, -1);
+ end = end.replace(/\n+(?!\n|$)/g, `$&${indent}`);
+ }
+ // determine indent indicator from whitespace at value start
+ let startWithSpace = false;
+ let startEnd;
+ let startNlPos = -1;
+ for (startEnd = 0; startEnd < value.length; ++startEnd) {
+ const ch = value[startEnd];
+ if (ch === ' ')
+ startWithSpace = true;
+ else if (ch === '\n')
+ startNlPos = startEnd;
+ else
+ break;
+ }
+ let start = value.substring(0, startNlPos < startEnd ? startNlPos + 1 : startEnd);
+ if (start) {
+ value = value.substring(start.length);
+ start = start.replace(/\n+/g, `$&${indent}`);
+ }
+ const indentSize = indent ? '2' : '1'; // root is at -1
+ let header = (literal ? '|' : '>') + (startWithSpace ? indentSize : '') + chomp;
+ if (comment) {
+ header += ' ' + commentString(comment.replace(/ ?[\r\n]+/g, ' '));
+ if (onComment)
+ onComment();
+ }
+ if (literal) {
+ value = value.replace(/\n+/g, `$&${indent}`);
+ return `${header}\n${indent}${start}${value}${end}`;
+ }
+ value = value
+ .replace(/\n+/g, '\n$&')
+ .replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, '$1$2') // more-indented lines aren't folded
+ // ^ more-ind. ^ empty ^ capture next empty lines only at end of indent
+ .replace(/\n+/g, `$&${indent}`);
+ const body = foldFlowLines(`${start}${value}${end}`, indent, FOLD_BLOCK, getFoldOptions(ctx));
+ return `${header}\n${indent}${body}`;
+}
+function plainString(item, ctx, onComment, onChompKeep) {
+ const { type, value } = item;
+ const { actualString, implicitKey, indent, inFlow } = ctx;
+ if ((implicitKey && /[\n[\]{},]/.test(value)) ||
+ (inFlow && /[[\]{},]/.test(value))) {
+ return quotedString(value, ctx);
+ }
+ if (!value ||
+ /^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) {
+ // not allowed:
+ // - empty string, '-' or '?'
+ // - start with an indicator character (except [?:-]) or /[?-] /
+ // - '\n ', ': ' or ' \n' anywhere
+ // - '#' not preceded by a non-space char
+ // - end with ' ' or ':'
+ return implicitKey || inFlow || !value.includes('\n')
+ ? quotedString(value, ctx)
+ : blockString(item, ctx, onComment, onChompKeep);
+ }
+ if (!implicitKey &&
+ !inFlow &&
+ type !== Scalar.PLAIN &&
+ value.includes('\n')) {
+ // Where allowed & type not set explicitly, prefer block style for multiline strings
+ return blockString(item, ctx, onComment, onChompKeep);
+ }
+ if (indent === '' && containsDocumentMarker(value)) {
+ ctx.forceBlockIndent = true;
+ return blockString(item, ctx, onComment, onChompKeep);
+ }
+ const str = value.replace(/\n+/g, `$&\n${indent}`);
+ // Verify that output will be parsed as a string, as e.g. plain numbers and
+ // booleans get parsed with those types in v1.2 (e.g. '42', 'true' & '0.9e-3'),
+ // and others in v1.1.
+ if (actualString) {
+ const test = (tag) => tag.default && tag.tag !== 'tag:yaml.org,2002:str' && tag.test?.test(str);
+ const { compat, tags } = ctx.doc.schema;
+ if (tags.some(test) || compat?.some(test))
+ return quotedString(value, ctx);
+ }
+ return implicitKey
+ ? str
+ : foldFlowLines(str, indent, FOLD_FLOW, getFoldOptions(ctx));
+}
+function stringifyString(item, ctx, onComment, onChompKeep) {
+ const { implicitKey, inFlow } = ctx;
+ const ss = typeof item.value === 'string'
+ ? item
+ : Object.assign({}, item, { value: String(item.value) });
+ let { type } = item;
+ if (type !== Scalar.QUOTE_DOUBLE) {
+ // force double quotes on control characters & unpaired surrogates
+ if (/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(ss.value))
+ type = Scalar.QUOTE_DOUBLE;
+ }
+ const _stringify = (_type) => {
+ switch (_type) {
+ case Scalar.BLOCK_FOLDED:
+ case Scalar.BLOCK_LITERAL:
+ return implicitKey || inFlow
+ ? quotedString(ss.value, ctx) // blocks are not valid inside flow containers
+ : blockString(ss, ctx, onComment, onChompKeep);
+ case Scalar.QUOTE_DOUBLE:
+ return doubleQuotedString(ss.value, ctx);
+ case Scalar.QUOTE_SINGLE:
+ return singleQuotedString(ss.value, ctx);
+ case Scalar.PLAIN:
+ return plainString(ss, ctx, onComment, onChompKeep);
+ default:
+ return null;
+ }
+ };
+ let res = _stringify(type);
+ if (res === null) {
+ const { defaultKeyType, defaultStringType } = ctx.options;
+ const t = (implicitKey && defaultKeyType) || defaultStringType;
+ res = _stringify(t);
+ if (res === null)
+ throw new Error(`Unsupported default string type ${t}`);
+ }
+ return res;
+}
+
+export { stringifyString };
diff --git a/MistyCore/node_modules/yaml/browser/dist/util.js b/MistyCore/node_modules/yaml/browser/dist/util.js
new file mode 100644
index 0000000..eb104a5
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/util.js
@@ -0,0 +1,9 @@
+export { debug, warn } from './log.js';
+export { findPair } from './nodes/YAMLMap.js';
+export { toJS } from './nodes/toJS.js';
+export { map as mapTag } from './schema/common/map.js';
+export { seq as seqTag } from './schema/common/seq.js';
+export { string as stringTag } from './schema/common/string.js';
+export { foldFlowLines } from './stringify/foldFlowLines.js';
+export { stringifyNumber } from './stringify/stringifyNumber.js';
+export { stringifyString } from './stringify/stringifyString.js';
diff --git a/MistyCore/node_modules/yaml/browser/dist/visit.js b/MistyCore/node_modules/yaml/browser/dist/visit.js
new file mode 100644
index 0000000..acabcab
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/dist/visit.js
@@ -0,0 +1,233 @@
+import { isDocument, isNode, isPair, isCollection, isMap, isSeq, isScalar, isAlias } from './nodes/Node.js';
+
+const BREAK = Symbol('break visit');
+const SKIP = Symbol('skip children');
+const REMOVE = Symbol('remove node');
+/**
+ * Apply a visitor to an AST node or document.
+ *
+ * Walks through the tree (depth-first) starting from `node`, calling a
+ * `visitor` function with three arguments:
+ * - `key`: For sequence values and map `Pair`, the node's index in the
+ * collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
+ * `null` for the root node.
+ * - `node`: The current node.
+ * - `path`: The ancestry of the current node.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this node, continue with next
+ * sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current node, then continue with the next one
+ * - `Node`: Replace the current node, then continue by visiting it
+ * - `number`: While iterating the items of a sequence or map, set the index
+ * of the next step. This is useful especially if the index of the current
+ * node has changed.
+ *
+ * If `visitor` is a single function, it will be called with all values
+ * encountered in the tree, including e.g. `null` values. Alternatively,
+ * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
+ * `Alias` and `Scalar` node. To define the same visitor function for more than
+ * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
+ * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
+ * specific defined one will be used for each node.
+ */
+function visit(node, visitor) {
+ const visitor_ = initVisitor(visitor);
+ if (isDocument(node)) {
+ const cd = visit_(null, node.contents, visitor_, Object.freeze([node]));
+ if (cd === REMOVE)
+ node.contents = null;
+ }
+ else
+ visit_(null, node, visitor_, Object.freeze([]));
+}
+// Without the `as symbol` casts, TS declares these in the `visit`
+// namespace using `var`, but then complains about that because
+// `unique symbol` must be `const`.
+/** Terminate visit traversal completely */
+visit.BREAK = BREAK;
+/** Do not visit the children of the current node */
+visit.SKIP = SKIP;
+/** Remove the current node */
+visit.REMOVE = REMOVE;
+function visit_(key, node, visitor, path) {
+ const ctrl = callVisitor(key, node, visitor, path);
+ if (isNode(ctrl) || isPair(ctrl)) {
+ replaceNode(key, path, ctrl);
+ return visit_(key, ctrl, visitor, path);
+ }
+ if (typeof ctrl !== 'symbol') {
+ if (isCollection(node)) {
+ path = Object.freeze(path.concat(node));
+ for (let i = 0; i < node.items.length; ++i) {
+ const ci = visit_(i, node.items[i], visitor, path);
+ if (typeof ci === 'number')
+ i = ci - 1;
+ else if (ci === BREAK)
+ return BREAK;
+ else if (ci === REMOVE) {
+ node.items.splice(i, 1);
+ i -= 1;
+ }
+ }
+ }
+ else if (isPair(node)) {
+ path = Object.freeze(path.concat(node));
+ const ck = visit_('key', node.key, visitor, path);
+ if (ck === BREAK)
+ return BREAK;
+ else if (ck === REMOVE)
+ node.key = null;
+ const cv = visit_('value', node.value, visitor, path);
+ if (cv === BREAK)
+ return BREAK;
+ else if (cv === REMOVE)
+ node.value = null;
+ }
+ }
+ return ctrl;
+}
+/**
+ * Apply an async visitor to an AST node or document.
+ *
+ * Walks through the tree (depth-first) starting from `node`, calling a
+ * `visitor` function with three arguments:
+ * - `key`: For sequence values and map `Pair`, the node's index in the
+ * collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
+ * `null` for the root node.
+ * - `node`: The current node.
+ * - `path`: The ancestry of the current node.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `Promise`: Must resolve to one of the following values
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this node, continue with next
+ * sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current node, then continue with the next one
+ * - `Node`: Replace the current node, then continue by visiting it
+ * - `number`: While iterating the items of a sequence or map, set the index
+ * of the next step. This is useful especially if the index of the current
+ * node has changed.
+ *
+ * If `visitor` is a single function, it will be called with all values
+ * encountered in the tree, including e.g. `null` values. Alternatively,
+ * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
+ * `Alias` and `Scalar` node. To define the same visitor function for more than
+ * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
+ * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
+ * specific defined one will be used for each node.
+ */
+async function visitAsync(node, visitor) {
+ const visitor_ = initVisitor(visitor);
+ if (isDocument(node)) {
+ const cd = await visitAsync_(null, node.contents, visitor_, Object.freeze([node]));
+ if (cd === REMOVE)
+ node.contents = null;
+ }
+ else
+ await visitAsync_(null, node, visitor_, Object.freeze([]));
+}
+// Without the `as symbol` casts, TS declares these in the `visit`
+// namespace using `var`, but then complains about that because
+// `unique symbol` must be `const`.
+/** Terminate visit traversal completely */
+visitAsync.BREAK = BREAK;
+/** Do not visit the children of the current node */
+visitAsync.SKIP = SKIP;
+/** Remove the current node */
+visitAsync.REMOVE = REMOVE;
+async function visitAsync_(key, node, visitor, path) {
+ const ctrl = await callVisitor(key, node, visitor, path);
+ if (isNode(ctrl) || isPair(ctrl)) {
+ replaceNode(key, path, ctrl);
+ return visitAsync_(key, ctrl, visitor, path);
+ }
+ if (typeof ctrl !== 'symbol') {
+ if (isCollection(node)) {
+ path = Object.freeze(path.concat(node));
+ for (let i = 0; i < node.items.length; ++i) {
+ const ci = await visitAsync_(i, node.items[i], visitor, path);
+ if (typeof ci === 'number')
+ i = ci - 1;
+ else if (ci === BREAK)
+ return BREAK;
+ else if (ci === REMOVE) {
+ node.items.splice(i, 1);
+ i -= 1;
+ }
+ }
+ }
+ else if (isPair(node)) {
+ path = Object.freeze(path.concat(node));
+ const ck = await visitAsync_('key', node.key, visitor, path);
+ if (ck === BREAK)
+ return BREAK;
+ else if (ck === REMOVE)
+ node.key = null;
+ const cv = await visitAsync_('value', node.value, visitor, path);
+ if (cv === BREAK)
+ return BREAK;
+ else if (cv === REMOVE)
+ node.value = null;
+ }
+ }
+ return ctrl;
+}
+function initVisitor(visitor) {
+ if (typeof visitor === 'object' &&
+ (visitor.Collection || visitor.Node || visitor.Value)) {
+ return Object.assign({
+ Alias: visitor.Node,
+ Map: visitor.Node,
+ Scalar: visitor.Node,
+ Seq: visitor.Node
+ }, visitor.Value && {
+ Map: visitor.Value,
+ Scalar: visitor.Value,
+ Seq: visitor.Value
+ }, visitor.Collection && {
+ Map: visitor.Collection,
+ Seq: visitor.Collection
+ }, visitor);
+ }
+ return visitor;
+}
+function callVisitor(key, node, visitor, path) {
+ if (typeof visitor === 'function')
+ return visitor(key, node, path);
+ if (isMap(node))
+ return visitor.Map?.(key, node, path);
+ if (isSeq(node))
+ return visitor.Seq?.(key, node, path);
+ if (isPair(node))
+ return visitor.Pair?.(key, node, path);
+ if (isScalar(node))
+ return visitor.Scalar?.(key, node, path);
+ if (isAlias(node))
+ return visitor.Alias?.(key, node, path);
+ return undefined;
+}
+function replaceNode(key, path, node) {
+ const parent = path[path.length - 1];
+ if (isCollection(parent)) {
+ parent.items[key] = node;
+ }
+ else if (isPair(parent)) {
+ if (key === 'key')
+ parent.key = node;
+ else
+ parent.value = node;
+ }
+ else if (isDocument(parent)) {
+ parent.contents = node;
+ }
+ else {
+ const pt = isAlias(parent) ? 'alias' : 'scalar';
+ throw new Error(`Cannot replace node with ${pt} parent`);
+ }
+}
+
+export { visit, visitAsync };
diff --git a/MistyCore/node_modules/yaml/browser/index.js b/MistyCore/node_modules/yaml/browser/index.js
new file mode 100644
index 0000000..5f73271
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/index.js
@@ -0,0 +1,5 @@
+// `export * as default from ...` fails on Webpack v4
+// https://github.com/eemeli/yaml/issues/228
+import * as YAML from './dist/index.js'
+export default YAML
+export * from './dist/index.js'
diff --git a/MistyCore/node_modules/yaml/browser/package.json b/MistyCore/node_modules/yaml/browser/package.json
new file mode 100644
index 0000000..3dbc1ca
--- /dev/null
+++ b/MistyCore/node_modules/yaml/browser/package.json
@@ -0,0 +1,3 @@
+{
+ "type": "module"
+}
diff --git a/MistyCore/node_modules/yaml/dist/compose/compose-collection.d.ts b/MistyCore/node_modules/yaml/dist/compose/compose-collection.d.ts
new file mode 100644
index 0000000..7ba83ac
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/compose-collection.d.ts
@@ -0,0 +1,5 @@
+import { ParsedNode } from '../nodes/Node.js';
+import type { BlockMap, BlockSequence, FlowCollection, SourceToken } from '../parse/cst.js';
+import type { ComposeContext, ComposeNode } from './compose-node.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function composeCollection(CN: ComposeNode, ctx: ComposeContext, token: BlockMap | BlockSequence | FlowCollection, tagToken: SourceToken | null, onError: ComposeErrorHandler): ParsedNode;
diff --git a/MistyCore/node_modules/yaml/dist/compose/compose-collection.js b/MistyCore/node_modules/yaml/dist/compose/compose-collection.js
new file mode 100644
index 0000000..015eadd
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/compose-collection.js
@@ -0,0 +1,61 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+var Scalar = require('../nodes/Scalar.js');
+var resolveBlockMap = require('./resolve-block-map.js');
+var resolveBlockSeq = require('./resolve-block-seq.js');
+var resolveFlowCollection = require('./resolve-flow-collection.js');
+
+function composeCollection(CN, ctx, token, tagToken, onError) {
+ let coll;
+ switch (token.type) {
+ case 'block-map': {
+ coll = resolveBlockMap.resolveBlockMap(CN, ctx, token, onError);
+ break;
+ }
+ case 'block-seq': {
+ coll = resolveBlockSeq.resolveBlockSeq(CN, ctx, token, onError);
+ break;
+ }
+ case 'flow-collection': {
+ coll = resolveFlowCollection.resolveFlowCollection(CN, ctx, token, onError);
+ break;
+ }
+ }
+ if (!tagToken)
+ return coll;
+ const tagName = ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg));
+ if (!tagName)
+ return coll;
+ // Cast needed due to: https://github.com/Microsoft/TypeScript/issues/3841
+ const Coll = coll.constructor;
+ if (tagName === '!' || tagName === Coll.tagName) {
+ coll.tag = Coll.tagName;
+ return coll;
+ }
+ const expType = Node.isMap(coll) ? 'map' : 'seq';
+ let tag = ctx.schema.tags.find(t => t.collection === expType && t.tag === tagName);
+ if (!tag) {
+ const kt = ctx.schema.knownTags[tagName];
+ if (kt && kt.collection === expType) {
+ ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
+ tag = kt;
+ }
+ else {
+ onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, true);
+ coll.tag = tagName;
+ return coll;
+ }
+ }
+ const res = tag.resolve(coll, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg), ctx.options);
+ const node = Node.isNode(res)
+ ? res
+ : new Scalar.Scalar(res);
+ node.range = coll.range;
+ node.tag = tagName;
+ if (tag?.format)
+ node.format = tag.format;
+ return node;
+}
+
+exports.composeCollection = composeCollection;
diff --git a/MistyCore/node_modules/yaml/dist/compose/compose-doc.d.ts b/MistyCore/node_modules/yaml/dist/compose/compose-doc.d.ts
new file mode 100644
index 0000000..2068f87
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/compose-doc.d.ts
@@ -0,0 +1,6 @@
+import type { Directives } from '../doc/directives.js';
+import { Document } from '../doc/Document.js';
+import type { DocumentOptions, ParseOptions, SchemaOptions } from '../options.js';
+import type * as CST from '../parse/cst.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function composeDoc(options: ParseOptions & DocumentOptions & SchemaOptions, directives: Directives, { offset, start, value, end }: CST.Document, onError: ComposeErrorHandler): Document.Parsed<import("../index.js").ParsedNode>;
diff --git a/MistyCore/node_modules/yaml/dist/compose/compose-doc.js b/MistyCore/node_modules/yaml/dist/compose/compose-doc.js
new file mode 100644
index 0000000..02457bf
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/compose-doc.js
@@ -0,0 +1,42 @@
+'use strict';
+
+var Document = require('../doc/Document.js');
+var composeNode = require('./compose-node.js');
+var resolveEnd = require('./resolve-end.js');
+var resolveProps = require('./resolve-props.js');
+
+function composeDoc(options, directives, { offset, start, value, end }, onError) {
+ const opts = Object.assign({ _directives: directives }, options);
+ const doc = new Document.Document(undefined, opts);
+ const ctx = {
+ atRoot: true,
+ directives: doc.directives,
+ options: doc.options,
+ schema: doc.schema
+ };
+ const props = resolveProps.resolveProps(start, {
+ indicator: 'doc-start',
+ next: value ?? end?.[0],
+ offset,
+ onError,
+ startOnNewline: true
+ });
+ if (props.found) {
+ doc.directives.docStart = true;
+ if (value &&
+ (value.type === 'block-map' || value.type === 'block-seq') &&
+ !props.hasNewline)
+ onError(props.end, 'MISSING_CHAR', 'Block collection cannot start on same line with directives-end marker');
+ }
+ doc.contents = value
+ ? composeNode.composeNode(ctx, value, props, onError)
+ : composeNode.composeEmptyNode(ctx, props.end, start, null, props, onError);
+ const contentEnd = doc.contents.range[2];
+ const re = resolveEnd.resolveEnd(end, contentEnd, false, onError);
+ if (re.comment)
+ doc.comment = re.comment;
+ doc.range = [offset, contentEnd, re.offset];
+ return doc;
+}
+
+exports.composeDoc = composeDoc;
diff --git a/MistyCore/node_modules/yaml/dist/compose/compose-node.d.ts b/MistyCore/node_modules/yaml/dist/compose/compose-node.d.ts
new file mode 100644
index 0000000..c147192
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/compose-node.d.ts
@@ -0,0 +1,27 @@
+import type { Directives } from '../doc/directives.js';
+import type { ParsedNode } from '../nodes/Node.js';
+import type { ParseOptions } from '../options.js';
+import type { SourceToken, Token } from '../parse/cst.js';
+import type { Schema } from '../schema/Schema.js';
+import type { ComposeErrorHandler } from './composer.js';
+export interface ComposeContext {
+ atRoot: boolean;
+ directives: Directives;
+ options: Readonly<Required<Omit<ParseOptions, 'lineCounter'>>>;
+ schema: Readonly<Schema>;
+}
+interface Props {
+ spaceBefore: boolean;
+ comment: string;
+ anchor: SourceToken | null;
+ tag: SourceToken | null;
+ end: number;
+}
+declare const CN: {
+ composeNode: typeof composeNode;
+ composeEmptyNode: typeof composeEmptyNode;
+};
+export declare type ComposeNode = typeof CN;
+export declare function composeNode(ctx: ComposeContext, token: Token, props: Props, onError: ComposeErrorHandler): ParsedNode;
+export declare function composeEmptyNode(ctx: ComposeContext, offset: number, before: Token[] | undefined, pos: number | null, { spaceBefore, comment, anchor, tag, end }: Props, onError: ComposeErrorHandler): import("../index.js").Scalar.Parsed;
+export {};
diff --git a/MistyCore/node_modules/yaml/dist/compose/compose-node.js b/MistyCore/node_modules/yaml/dist/compose/compose-node.js
new file mode 100644
index 0000000..7eb1daf
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/compose-node.js
@@ -0,0 +1,95 @@
+'use strict';
+
+var Alias = require('../nodes/Alias.js');
+var composeCollection = require('./compose-collection.js');
+var composeScalar = require('./compose-scalar.js');
+var resolveEnd = require('./resolve-end.js');
+var utilEmptyScalarPosition = require('./util-empty-scalar-position.js');
+
+const CN = { composeNode, composeEmptyNode };
+function composeNode(ctx, token, props, onError) {
+ const { spaceBefore, comment, anchor, tag } = props;
+ let node;
+ let isSrcToken = true;
+ switch (token.type) {
+ case 'alias':
+ node = composeAlias(ctx, token, onError);
+ if (anchor || tag)
+ onError(token, 'ALIAS_PROPS', 'An alias node must not specify any properties');
+ break;
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ case 'block-scalar':
+ node = composeScalar.composeScalar(ctx, token, tag, onError);
+ if (anchor)
+ node.anchor = anchor.source.substring(1);
+ break;
+ case 'block-map':
+ case 'block-seq':
+ case 'flow-collection':
+ node = composeCollection.composeCollection(CN, ctx, token, tag, onError);
+ if (anchor)
+ node.anchor = anchor.source.substring(1);
+ break;
+ default: {
+ const message = token.type === 'error'
+ ? token.message
+ : `Unsupported token (type: ${token.type})`;
+ onError(token, 'UNEXPECTED_TOKEN', message);
+ node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
+ isSrcToken = false;
+ }
+ }
+ if (anchor && node.anchor === '')
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
+ if (spaceBefore)
+ node.spaceBefore = true;
+ if (comment) {
+ if (token.type === 'scalar' && token.source === '')
+ node.comment = comment;
+ else
+ node.commentBefore = comment;
+ }
+ // @ts-expect-error Type checking misses meaning of isSrcToken
+ if (ctx.options.keepSourceTokens && isSrcToken)
+ node.srcToken = token;
+ return node;
+}
+function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor, tag, end }, onError) {
+ const token = {
+ type: 'scalar',
+ offset: utilEmptyScalarPosition.emptyScalarPosition(offset, before, pos),
+ indent: -1,
+ source: ''
+ };
+ const node = composeScalar.composeScalar(ctx, token, tag, onError);
+ if (anchor) {
+ node.anchor = anchor.source.substring(1);
+ if (node.anchor === '')
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
+ }
+ if (spaceBefore)
+ node.spaceBefore = true;
+ if (comment) {
+ node.comment = comment;
+ node.range[2] = end;
+ }
+ return node;
+}
+function composeAlias({ options }, { offset, source, end }, onError) {
+ const alias = new Alias.Alias(source.substring(1));
+ if (alias.source === '')
+ onError(offset, 'BAD_ALIAS', 'Alias cannot be an empty string');
+ if (alias.source.endsWith(':'))
+ onError(offset + source.length - 1, 'BAD_ALIAS', 'Alias ending in : is ambiguous', true);
+ const valueEnd = offset + source.length;
+ const re = resolveEnd.resolveEnd(end, valueEnd, options.strict, onError);
+ alias.range = [offset, valueEnd, re.offset];
+ if (re.comment)
+ alias.comment = re.comment;
+ return alias;
+}
+
+exports.composeEmptyNode = composeEmptyNode;
+exports.composeNode = composeNode;
diff --git a/MistyCore/node_modules/yaml/dist/compose/compose-scalar.d.ts b/MistyCore/node_modules/yaml/dist/compose/compose-scalar.d.ts
new file mode 100644
index 0000000..d5d0f79
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/compose-scalar.d.ts
@@ -0,0 +1,5 @@
+import { Scalar } from '../nodes/Scalar.js';
+import type { BlockScalar, FlowScalar, SourceToken } from '../parse/cst.js';
+import type { ComposeContext } from './compose-node.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function composeScalar(ctx: ComposeContext, token: FlowScalar | BlockScalar, tagToken: SourceToken | null, onError: ComposeErrorHandler): Scalar.Parsed;
diff --git a/MistyCore/node_modules/yaml/dist/compose/compose-scalar.js b/MistyCore/node_modules/yaml/dist/compose/compose-scalar.js
new file mode 100644
index 0000000..d87bf94
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/compose-scalar.js
@@ -0,0 +1,82 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+var Scalar = require('../nodes/Scalar.js');
+var resolveBlockScalar = require('./resolve-block-scalar.js');
+var resolveFlowScalar = require('./resolve-flow-scalar.js');
+
+function composeScalar(ctx, token, tagToken, onError) {
+ const { value, type, comment, range } = token.type === 'block-scalar'
+ ? resolveBlockScalar.resolveBlockScalar(token, ctx.options.strict, onError)
+ : resolveFlowScalar.resolveFlowScalar(token, ctx.options.strict, onError);
+ const tagName = tagToken
+ ? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg))
+ : null;
+ const tag = tagToken && tagName
+ ? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError)
+ : token.type === 'scalar'
+ ? findScalarTagByTest(ctx, value, token, onError)
+ : ctx.schema[Node.SCALAR];
+ let scalar;
+ try {
+ const res = tag.resolve(value, msg => onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg), ctx.options);
+ scalar = Node.isScalar(res) ? res : new Scalar.Scalar(res);
+ }
+ catch (error) {
+ const msg = error instanceof Error ? error.message : String(error);
+ onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg);
+ scalar = new Scalar.Scalar(value);
+ }
+ scalar.range = range;
+ scalar.source = value;
+ if (type)
+ scalar.type = type;
+ if (tagName)
+ scalar.tag = tagName;
+ if (tag.format)
+ scalar.format = tag.format;
+ if (comment)
+ scalar.comment = comment;
+ return scalar;
+}
+function findScalarTagByName(schema, value, tagName, tagToken, onError) {
+ if (tagName === '!')
+ return schema[Node.SCALAR]; // non-specific tag
+ const matchWithTest = [];
+ for (const tag of schema.tags) {
+ if (!tag.collection && tag.tag === tagName) {
+ if (tag.default && tag.test)
+ matchWithTest.push(tag);
+ else
+ return tag;
+ }
+ }
+ for (const tag of matchWithTest)
+ if (tag.test?.test(value))
+ return tag;
+ const kt = schema.knownTags[tagName];
+ if (kt && !kt.collection) {
+ // Ensure that the known tag is available for stringifying,
+ // but does not get used by default.
+ schema.tags.push(Object.assign({}, kt, { default: false, test: undefined }));
+ return kt;
+ }
+ onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str');
+ return schema[Node.SCALAR];
+}
+function findScalarTagByTest({ directives, schema }, value, token, onError) {
+ const tag = schema.tags.find(tag => tag.default && tag.test?.test(value)) || schema[Node.SCALAR];
+ if (schema.compat) {
+ const compat = schema.compat.find(tag => tag.default && tag.test?.test(value)) ??
+ schema[Node.SCALAR];
+ if (tag.tag !== compat.tag) {
+ const ts = directives.tagString(tag.tag);
+ const cs = directives.tagString(compat.tag);
+ const msg = `Value may be parsed as either ${ts} or ${cs}`;
+ onError(token, 'TAG_RESOLVE_FAILED', msg, true);
+ }
+ }
+ return tag;
+}
+
+exports.composeScalar = composeScalar;
diff --git a/MistyCore/node_modules/yaml/dist/compose/composer.d.ts b/MistyCore/node_modules/yaml/dist/compose/composer.d.ts
new file mode 100644
index 0000000..9db2477
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/composer.d.ts
@@ -0,0 +1,62 @@
+import { Directives } from '../doc/directives.js';
+import { Document } from '../doc/Document.js';
+import { ErrorCode, YAMLParseError, YAMLWarning } from '../errors.js';
+import { Range } from '../nodes/Node.js';
+import type { DocumentOptions, ParseOptions, SchemaOptions } from '../options.js';
+import type { Token } from '../parse/cst.js';
+declare type ErrorSource = number | [number, number] | Range | {
+ offset: number;
+ source?: string;
+};
+export declare type ComposeErrorHandler = (source: ErrorSource, code: ErrorCode, message: string, warning?: boolean) => void;
+/**
+ * Compose a stream of CST nodes into a stream of YAML Documents.
+ *
+ * ```ts
+ * import { Composer, Parser } from 'yaml'
+ *
+ * const src: string = ...
+ * const tokens = new Parser().parse(src)
+ * const docs = new Composer().compose(tokens)
+ * ```
+ */
+export declare class Composer {
+ private directives;
+ private doc;
+ private options;
+ private atDirectives;
+ private prelude;
+ private errors;
+ private warnings;
+ constructor(options?: ParseOptions & DocumentOptions & SchemaOptions);
+ private onError;
+ private decorate;
+ /**
+ * Current stream status information.
+ *
+ * Mostly useful at the end of input for an empty stream.
+ */
+ streamInfo(): {
+ comment: string;
+ directives: Directives;
+ errors: YAMLParseError[];
+ warnings: YAMLWarning[];
+ };
+ /**
+ * Compose tokens into documents.
+ *
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
+ */
+ compose(tokens: Iterable<Token>, forceDoc?: boolean, endOffset?: number): Generator<Document.Parsed<import("../nodes/Node.js").ParsedNode>, void, unknown>;
+ /** Advance the composer by one CST token. */
+ next(token: Token): Generator<Document.Parsed<import("../nodes/Node.js").ParsedNode>, void, unknown>;
+ /**
+ * Call at end of input to yield any remaining document.
+ *
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
+ */
+ end(forceDoc?: boolean, endOffset?: number): Generator<Document.Parsed<import("../nodes/Node.js").ParsedNode>, void, unknown>;
+}
+export {};
diff --git a/MistyCore/node_modules/yaml/dist/compose/composer.js b/MistyCore/node_modules/yaml/dist/compose/composer.js
new file mode 100644
index 0000000..508d896
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/composer.js
@@ -0,0 +1,221 @@
+'use strict';
+
+var directives = require('../doc/directives.js');
+var Document = require('../doc/Document.js');
+var errors = require('../errors.js');
+var Node = require('../nodes/Node.js');
+var composeDoc = require('./compose-doc.js');
+var resolveEnd = require('./resolve-end.js');
+
+function getErrorPos(src) {
+ if (typeof src === 'number')
+ return [src, src + 1];
+ if (Array.isArray(src))
+ return src.length === 2 ? src : [src[0], src[1]];
+ const { offset, source } = src;
+ return [offset, offset + (typeof source === 'string' ? source.length : 1)];
+}
+function parsePrelude(prelude) {
+ let comment = '';
+ let atComment = false;
+ let afterEmptyLine = false;
+ for (let i = 0; i < prelude.length; ++i) {
+ const source = prelude[i];
+ switch (source[0]) {
+ case '#':
+ comment +=
+ (comment === '' ? '' : afterEmptyLine ? '\n\n' : '\n') +
+ (source.substring(1) || ' ');
+ atComment = true;
+ afterEmptyLine = false;
+ break;
+ case '%':
+ if (prelude[i + 1]?.[0] !== '#')
+ i += 1;
+ atComment = false;
+ break;
+ default:
+ // This may be wrong after doc-end, but in that case it doesn't matter
+ if (!atComment)
+ afterEmptyLine = true;
+ atComment = false;
+ }
+ }
+ return { comment, afterEmptyLine };
+}
+/**
+ * Compose a stream of CST nodes into a stream of YAML Documents.
+ *
+ * ```ts
+ * import { Composer, Parser } from 'yaml'
+ *
+ * const src: string = ...
+ * const tokens = new Parser().parse(src)
+ * const docs = new Composer().compose(tokens)
+ * ```
+ */
+class Composer {
+ constructor(options = {}) {
+ this.doc = null;
+ this.atDirectives = false;
+ this.prelude = [];
+ this.errors = [];
+ this.warnings = [];
+ this.onError = (source, code, message, warning) => {
+ const pos = getErrorPos(source);
+ if (warning)
+ this.warnings.push(new errors.YAMLWarning(pos, code, message));
+ else
+ this.errors.push(new errors.YAMLParseError(pos, code, message));
+ };
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ this.directives = new directives.Directives({ version: options.version || '1.2' });
+ this.options = options;
+ }
+ decorate(doc, afterDoc) {
+ const { comment, afterEmptyLine } = parsePrelude(this.prelude);
+ //console.log({ dc: doc.comment, prelude, comment })
+ if (comment) {
+ const dc = doc.contents;
+ if (afterDoc) {
+ doc.comment = doc.comment ? `${doc.comment}\n${comment}` : comment;
+ }
+ else if (afterEmptyLine || doc.directives.docStart || !dc) {
+ doc.commentBefore = comment;
+ }
+ else if (Node.isCollection(dc) && !dc.flow && dc.items.length > 0) {
+ let it = dc.items[0];
+ if (Node.isPair(it))
+ it = it.key;
+ const cb = it.commentBefore;
+ it.commentBefore = cb ? `${comment}\n${cb}` : comment;
+ }
+ else {
+ const cb = dc.commentBefore;
+ dc.commentBefore = cb ? `${comment}\n${cb}` : comment;
+ }
+ }
+ if (afterDoc) {
+ Array.prototype.push.apply(doc.errors, this.errors);
+ Array.prototype.push.apply(doc.warnings, this.warnings);
+ }
+ else {
+ doc.errors = this.errors;
+ doc.warnings = this.warnings;
+ }
+ this.prelude = [];
+ this.errors = [];
+ this.warnings = [];
+ }
+ /**
+ * Current stream status information.
+ *
+ * Mostly useful at the end of input for an empty stream.
+ */
+ streamInfo() {
+ return {
+ comment: parsePrelude(this.prelude).comment,
+ directives: this.directives,
+ errors: this.errors,
+ warnings: this.warnings
+ };
+ }
+ /**
+ * Compose tokens into documents.
+ *
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
+ */
+ *compose(tokens, forceDoc = false, endOffset = -1) {
+ for (const token of tokens)
+ yield* this.next(token);
+ yield* this.end(forceDoc, endOffset);
+ }
+ /** Advance the composer by one CST token. */
+ *next(token) {
+ if (process.env.LOG_STREAM)
+ console.dir(token, { depth: null });
+ switch (token.type) {
+ case 'directive':
+ this.directives.add(token.source, (offset, message, warning) => {
+ const pos = getErrorPos(token);
+ pos[0] += offset;
+ this.onError(pos, 'BAD_DIRECTIVE', message, warning);
+ });
+ this.prelude.push(token.source);
+ this.atDirectives = true;
+ break;
+ case 'document': {
+ const doc = composeDoc.composeDoc(this.options, this.directives, token, this.onError);
+ if (this.atDirectives && !doc.directives.docStart)
+ this.onError(token, 'MISSING_CHAR', 'Missing directives-end/doc-start indicator line');
+ this.decorate(doc, false);
+ if (this.doc)
+ yield this.doc;
+ this.doc = doc;
+ this.atDirectives = false;
+ break;
+ }
+ case 'byte-order-mark':
+ case 'space':
+ break;
+ case 'comment':
+ case 'newline':
+ this.prelude.push(token.source);
+ break;
+ case 'error': {
+ const msg = token.source
+ ? `${token.message}: ${JSON.stringify(token.source)}`
+ : token.message;
+ const error = new errors.YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', msg);
+ if (this.atDirectives || !this.doc)
+ this.errors.push(error);
+ else
+ this.doc.errors.push(error);
+ break;
+ }
+ case 'doc-end': {
+ if (!this.doc) {
+ const msg = 'Unexpected doc-end without preceding document';
+ this.errors.push(new errors.YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', msg));
+ break;
+ }
+ this.doc.directives.docEnd = true;
+ const end = resolveEnd.resolveEnd(token.end, token.offset + token.source.length, this.doc.options.strict, this.onError);
+ this.decorate(this.doc, true);
+ if (end.comment) {
+ const dc = this.doc.comment;
+ this.doc.comment = dc ? `${dc}\n${end.comment}` : end.comment;
+ }
+ this.doc.range[2] = end.offset;
+ break;
+ }
+ default:
+ this.errors.push(new errors.YAMLParseError(getErrorPos(token), 'UNEXPECTED_TOKEN', `Unsupported token ${token.type}`));
+ }
+ }
+ /**
+ * Call at end of input to yield any remaining document.
+ *
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
+ */
+ *end(forceDoc = false, endOffset = -1) {
+ if (this.doc) {
+ this.decorate(this.doc, true);
+ yield this.doc;
+ this.doc = null;
+ }
+ else if (forceDoc) {
+ const opts = Object.assign({ _directives: this.directives }, this.options);
+ const doc = new Document.Document(undefined, opts);
+ if (this.atDirectives)
+ this.onError(endOffset, 'MISSING_CHAR', 'Missing directives-end indicator line');
+ doc.range = [0, endOffset, endOffset];
+ this.decorate(doc, false);
+ yield doc;
+ }
+ }
+}
+
+exports.Composer = Composer;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-block-map.d.ts b/MistyCore/node_modules/yaml/dist/compose/resolve-block-map.d.ts
new file mode 100644
index 0000000..dbcd3fa
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-block-map.d.ts
@@ -0,0 +1,6 @@
+import type { ParsedNode } from '../nodes/Node.js';
+import { YAMLMap } from '../nodes/YAMLMap.js';
+import type { BlockMap } from '../parse/cst.js';
+import type { ComposeContext, ComposeNode } from './compose-node.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function resolveBlockMap({ composeNode, composeEmptyNode }: ComposeNode, ctx: ComposeContext, bm: BlockMap, onError: ComposeErrorHandler): YAMLMap.Parsed<ParsedNode, ParsedNode | null>;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-block-map.js b/MistyCore/node_modules/yaml/dist/compose/resolve-block-map.js
new file mode 100644
index 0000000..006dfae
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-block-map.js
@@ -0,0 +1,112 @@
+'use strict';
+
+var Pair = require('../nodes/Pair.js');
+var YAMLMap = require('../nodes/YAMLMap.js');
+var resolveProps = require('./resolve-props.js');
+var utilContainsNewline = require('./util-contains-newline.js');
+var utilFlowIndentCheck = require('./util-flow-indent-check.js');
+var utilMapIncludes = require('./util-map-includes.js');
+
+const startColMsg = 'All mapping items must start at the same column';
+function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError) {
+ const map = new YAMLMap.YAMLMap(ctx.schema);
+ if (ctx.atRoot)
+ ctx.atRoot = false;
+ let offset = bm.offset;
+ let commentEnd = null;
+ for (const collItem of bm.items) {
+ const { start, key, sep, value } = collItem;
+ // key properties
+ const keyProps = resolveProps.resolveProps(start, {
+ indicator: 'explicit-key-ind',
+ next: key ?? sep?.[0],
+ offset,
+ onError,
+ startOnNewline: true
+ });
+ const implicitKey = !keyProps.found;
+ if (implicitKey) {
+ if (key) {
+ if (key.type === 'block-seq')
+ onError(offset, 'BLOCK_AS_IMPLICIT_KEY', 'A block sequence may not be used as an implicit map key');
+ else if ('indent' in key && key.indent !== bm.indent)
+ onError(offset, 'BAD_INDENT', startColMsg);
+ }
+ if (!keyProps.anchor && !keyProps.tag && !sep) {
+ commentEnd = keyProps.end;
+ if (keyProps.comment) {
+ if (map.comment)
+ map.comment += '\n' + keyProps.comment;
+ else
+ map.comment = keyProps.comment;
+ }
+ continue;
+ }
+ if (keyProps.hasNewlineAfterProp || utilContainsNewline.containsNewline(key)) {
+ onError(key ?? start[start.length - 1], 'MULTILINE_IMPLICIT_KEY', 'Implicit keys need to be on a single line');
+ }
+ }
+ else if (keyProps.found?.indent !== bm.indent) {
+ onError(offset, 'BAD_INDENT', startColMsg);
+ }
+ // key value
+ const keyStart = keyProps.end;
+ const keyNode = key
+ ? composeNode(ctx, key, keyProps, onError)
+ : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
+ if (ctx.schema.compat)
+ utilFlowIndentCheck.flowIndentCheck(bm.indent, key, onError);
+ if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
+ onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');
+ // value properties
+ const valueProps = resolveProps.resolveProps(sep ?? [], {
+ indicator: 'map-value-ind',
+ next: value,
+ offset: keyNode.range[2],
+ onError,
+ startOnNewline: !key || key.type === 'block-scalar'
+ });
+ offset = valueProps.end;
+ if (valueProps.found) {
+ if (implicitKey) {
+ if (value?.type === 'block-map' && !valueProps.hasNewline)
+ onError(offset, 'BLOCK_AS_IMPLICIT_KEY', 'Nested mappings are not allowed in compact mappings');
+ if (ctx.options.strict &&
+ keyProps.start < valueProps.found.offset - 1024)
+ onError(keyNode.range, 'KEY_OVER_1024_CHARS', 'The : indicator must be at most 1024 chars after the start of an implicit block mapping key');
+ }
+ // value value
+ const valueNode = value
+ ? composeNode(ctx, value, valueProps, onError)
+ : composeEmptyNode(ctx, offset, sep, null, valueProps, onError);
+ if (ctx.schema.compat)
+ utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
+ offset = valueNode.range[2];
+ const pair = new Pair.Pair(keyNode, valueNode);
+ if (ctx.options.keepSourceTokens)
+ pair.srcToken = collItem;
+ map.items.push(pair);
+ }
+ else {
+ // key with no value
+ if (implicitKey)
+ onError(keyNode.range, 'MISSING_CHAR', 'Implicit map keys need to be followed by map values');
+ if (valueProps.comment) {
+ if (keyNode.comment)
+ keyNode.comment += '\n' + valueProps.comment;
+ else
+ keyNode.comment = valueProps.comment;
+ }
+ const pair = new Pair.Pair(keyNode);
+ if (ctx.options.keepSourceTokens)
+ pair.srcToken = collItem;
+ map.items.push(pair);
+ }
+ }
+ if (commentEnd && commentEnd < offset)
+ onError(commentEnd, 'IMPOSSIBLE', 'Map comment with trailing content');
+ map.range = [bm.offset, offset, commentEnd ?? offset];
+ return map;
+}
+
+exports.resolveBlockMap = resolveBlockMap;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts b/MistyCore/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts
new file mode 100644
index 0000000..4855b19
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts
@@ -0,0 +1,10 @@
+import { Range } from '../nodes/Node.js';
+import { Scalar } from '../nodes/Scalar.js';
+import type { BlockScalar } from '../parse/cst.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function resolveBlockScalar(scalar: BlockScalar, strict: boolean, onError: ComposeErrorHandler): {
+ value: string;
+ type: Scalar.BLOCK_FOLDED | Scalar.BLOCK_LITERAL | null;
+ comment: string;
+ range: Range;
+};
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-block-scalar.js b/MistyCore/node_modules/yaml/dist/compose/resolve-block-scalar.js
new file mode 100644
index 0000000..ba89f97
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-block-scalar.js
@@ -0,0 +1,196 @@
+'use strict';
+
+var Scalar = require('../nodes/Scalar.js');
+
+function resolveBlockScalar(scalar, strict, onError) {
+ const start = scalar.offset;
+ const header = parseBlockScalarHeader(scalar, strict, onError);
+ if (!header)
+ return { value: '', type: null, comment: '', range: [start, start, start] };
+ const type = header.mode === '>' ? Scalar.Scalar.BLOCK_FOLDED : Scalar.Scalar.BLOCK_LITERAL;
+ const lines = scalar.source ? splitLines(scalar.source) : [];
+ // determine the end of content & start of chomping
+ let chompStart = lines.length;
+ for (let i = lines.length - 1; i >= 0; --i) {
+ const content = lines[i][1];
+ if (content === '' || content === '\r')
+ chompStart = i;
+ else
+ break;
+ }
+ // shortcut for empty contents
+ if (chompStart === 0) {
+ const value = header.chomp === '+' && lines.length > 0
+ ? '\n'.repeat(Math.max(1, lines.length - 1))
+ : '';
+ let end = start + header.length;
+ if (scalar.source)
+ end += scalar.source.length;
+ return { value, type, comment: header.comment, range: [start, end, end] };
+ }
+ // find the indentation level to trim from start
+ let trimIndent = scalar.indent + header.indent;
+ let offset = scalar.offset + header.length;
+ let contentStart = 0;
+ for (let i = 0; i < chompStart; ++i) {
+ const [indent, content] = lines[i];
+ if (content === '' || content === '\r') {
+ if (header.indent === 0 && indent.length > trimIndent)
+ trimIndent = indent.length;
+ }
+ else {
+ if (indent.length < trimIndent) {
+ const message = 'Block scalars with more-indented leading empty lines must use an explicit indentation indicator';
+ onError(offset + indent.length, 'MISSING_CHAR', message);
+ }
+ if (header.indent === 0)
+ trimIndent = indent.length;
+ contentStart = i;
+ break;
+ }
+ offset += indent.length + content.length + 1;
+ }
+ // include trailing more-indented empty lines in content
+ for (let i = lines.length - 1; i >= chompStart; --i) {
+ if (lines[i][0].length > trimIndent)
+ chompStart = i + 1;
+ }
+ let value = '';
+ let sep = '';
+ let prevMoreIndented = false;
+ // leading whitespace is kept intact
+ for (let i = 0; i < contentStart; ++i)
+ value += lines[i][0].slice(trimIndent) + '\n';
+ for (let i = contentStart; i < chompStart; ++i) {
+ let [indent, content] = lines[i];
+ offset += indent.length + content.length + 1;
+ const crlf = content[content.length - 1] === '\r';
+ if (crlf)
+ content = content.slice(0, -1);
+ /* istanbul ignore if already caught in lexer */
+ if (content && indent.length < trimIndent) {
+ const src = header.indent
+ ? 'explicit indentation indicator'
+ : 'first line';
+ const message = `Block scalar lines must not be less indented than their ${src}`;
+ onError(offset - content.length - (crlf ? 2 : 1), 'BAD_INDENT', message);
+ indent = '';
+ }
+ if (type === Scalar.Scalar.BLOCK_LITERAL) {
+ value += sep + indent.slice(trimIndent) + content;
+ sep = '\n';
+ }
+ else if (indent.length > trimIndent || content[0] === '\t') {
+ // more-indented content within a folded block
+ if (sep === ' ')
+ sep = '\n';
+ else if (!prevMoreIndented && sep === '\n')
+ sep = '\n\n';
+ value += sep + indent.slice(trimIndent) + content;
+ sep = '\n';
+ prevMoreIndented = true;
+ }
+ else if (content === '') {
+ // empty line
+ if (sep === '\n')
+ value += '\n';
+ else
+ sep = '\n';
+ }
+ else {
+ value += sep + content;
+ sep = ' ';
+ prevMoreIndented = false;
+ }
+ }
+ switch (header.chomp) {
+ case '-':
+ break;
+ case '+':
+ for (let i = chompStart; i < lines.length; ++i)
+ value += '\n' + lines[i][0].slice(trimIndent);
+ if (value[value.length - 1] !== '\n')
+ value += '\n';
+ break;
+ default:
+ value += '\n';
+ }
+ const end = start + header.length + scalar.source.length;
+ return { value, type, comment: header.comment, range: [start, end, end] };
+}
+function parseBlockScalarHeader({ offset, props }, strict, onError) {
+ /* istanbul ignore if should not happen */
+ if (props[0].type !== 'block-scalar-header') {
+ onError(props[0], 'IMPOSSIBLE', 'Block scalar header not found');
+ return null;
+ }
+ const { source } = props[0];
+ const mode = source[0];
+ let indent = 0;
+ let chomp = '';
+ let error = -1;
+ for (let i = 1; i < source.length; ++i) {
+ const ch = source[i];
+ if (!chomp && (ch === '-' || ch === '+'))
+ chomp = ch;
+ else {
+ const n = Number(ch);
+ if (!indent && n)
+ indent = n;
+ else if (error === -1)
+ error = offset + i;
+ }
+ }
+ if (error !== -1)
+ onError(error, 'UNEXPECTED_TOKEN', `Block scalar header includes extra characters: ${source}`);
+ let hasSpace = false;
+ let comment = '';
+ let length = source.length;
+ for (let i = 1; i < props.length; ++i) {
+ const token = props[i];
+ switch (token.type) {
+ case 'space':
+ hasSpace = true;
+ // fallthrough
+ case 'newline':
+ length += token.source.length;
+ break;
+ case 'comment':
+ if (strict && !hasSpace) {
+ const message = 'Comments must be separated from other tokens by white space characters';
+ onError(token, 'MISSING_CHAR', message);
+ }
+ length += token.source.length;
+ comment = token.source.substring(1);
+ break;
+ case 'error':
+ onError(token, 'UNEXPECTED_TOKEN', token.message);
+ length += token.source.length;
+ break;
+ /* istanbul ignore next should not happen */
+ default: {
+ const message = `Unexpected token in block scalar header: ${token.type}`;
+ onError(token, 'UNEXPECTED_TOKEN', message);
+ const ts = token.source;
+ if (ts && typeof ts === 'string')
+ length += ts.length;
+ }
+ }
+ }
+ return { mode, indent, chomp, comment, length };
+}
+/** @returns Array of lines split up as `[indent, content]` */
+function splitLines(source) {
+ const split = source.split(/\n( *)/);
+ const first = split[0];
+ const m = first.match(/^( *)/);
+ const line0 = m?.[1]
+ ? [m[1], first.slice(m[1].length)]
+ : ['', first];
+ const lines = [line0];
+ for (let i = 1; i < split.length; i += 2)
+ lines.push([split[i], split[i + 1]]);
+ return lines;
+}
+
+exports.resolveBlockScalar = resolveBlockScalar;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-block-seq.d.ts b/MistyCore/node_modules/yaml/dist/compose/resolve-block-seq.d.ts
new file mode 100644
index 0000000..25ed558
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-block-seq.d.ts
@@ -0,0 +1,5 @@
+import { YAMLSeq } from '../nodes/YAMLSeq.js';
+import type { BlockSequence } from '../parse/cst.js';
+import type { ComposeContext, ComposeNode } from './compose-node.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function resolveBlockSeq({ composeNode, composeEmptyNode }: ComposeNode, ctx: ComposeContext, bs: BlockSequence, onError: ComposeErrorHandler): YAMLSeq.Parsed<import("../index.js").ParsedNode>;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-block-seq.js b/MistyCore/node_modules/yaml/dist/compose/resolve-block-seq.js
new file mode 100644
index 0000000..a6cabc4
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-block-seq.js
@@ -0,0 +1,47 @@
+'use strict';
+
+var YAMLSeq = require('../nodes/YAMLSeq.js');
+var resolveProps = require('./resolve-props.js');
+var utilFlowIndentCheck = require('./util-flow-indent-check.js');
+
+function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError) {
+ const seq = new YAMLSeq.YAMLSeq(ctx.schema);
+ if (ctx.atRoot)
+ ctx.atRoot = false;
+ let offset = bs.offset;
+ let commentEnd = null;
+ for (const { start, value } of bs.items) {
+ const props = resolveProps.resolveProps(start, {
+ indicator: 'seq-item-ind',
+ next: value,
+ offset,
+ onError,
+ startOnNewline: true
+ });
+ if (!props.found) {
+ if (props.anchor || props.tag || value) {
+ if (value && value.type === 'block-seq')
+ onError(props.end, 'BAD_INDENT', 'All sequence items must start at the same column');
+ else
+ onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator');
+ }
+ else {
+ commentEnd = props.end;
+ if (props.comment)
+ seq.comment = props.comment;
+ continue;
+ }
+ }
+ const node = value
+ ? composeNode(ctx, value, props, onError)
+ : composeEmptyNode(ctx, props.end, start, null, props, onError);
+ if (ctx.schema.compat)
+ utilFlowIndentCheck.flowIndentCheck(bs.indent, value, onError);
+ offset = node.range[2];
+ seq.items.push(node);
+ }
+ seq.range = [bs.offset, offset, commentEnd ?? offset];
+ return seq;
+}
+
+exports.resolveBlockSeq = resolveBlockSeq;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-end.d.ts b/MistyCore/node_modules/yaml/dist/compose/resolve-end.d.ts
new file mode 100644
index 0000000..bb2d0b8
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-end.d.ts
@@ -0,0 +1,6 @@
+import type { SourceToken } from '../parse/cst.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function resolveEnd(end: SourceToken[] | undefined, offset: number, reqSpace: boolean, onError: ComposeErrorHandler): {
+ comment: string;
+ offset: number;
+};
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-end.js b/MistyCore/node_modules/yaml/dist/compose/resolve-end.js
new file mode 100644
index 0000000..3a58347
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-end.js
@@ -0,0 +1,39 @@
+'use strict';
+
+function resolveEnd(end, offset, reqSpace, onError) {
+ let comment = '';
+ if (end) {
+ let hasSpace = false;
+ let sep = '';
+ for (const token of end) {
+ const { source, type } = token;
+ switch (type) {
+ case 'space':
+ hasSpace = true;
+ break;
+ case 'comment': {
+ if (reqSpace && !hasSpace)
+ onError(token, 'MISSING_CHAR', 'Comments must be separated from other tokens by white space characters');
+ const cb = source.substring(1) || ' ';
+ if (!comment)
+ comment = cb;
+ else
+ comment += sep + cb;
+ sep = '';
+ break;
+ }
+ case 'newline':
+ if (comment)
+ sep += source;
+ hasSpace = true;
+ break;
+ default:
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${type} at node end`);
+ }
+ offset += source.length;
+ }
+ }
+ return { comment, offset };
+}
+
+exports.resolveEnd = resolveEnd;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts b/MistyCore/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts
new file mode 100644
index 0000000..06d32f5
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts
@@ -0,0 +1,6 @@
+import { YAMLMap } from '../nodes/YAMLMap.js';
+import { YAMLSeq } from '../nodes/YAMLSeq.js';
+import type { FlowCollection } from '../parse/cst.js';
+import type { ComposeContext, ComposeNode } from './compose-node.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function resolveFlowCollection({ composeNode, composeEmptyNode }: ComposeNode, ctx: ComposeContext, fc: FlowCollection, onError: ComposeErrorHandler): YAMLMap.Parsed<import("../nodes/Node.js").ParsedNode, import("../nodes/Node.js").ParsedNode | null> | YAMLSeq.Parsed<import("../nodes/Node.js").ParsedNode>;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-flow-collection.js b/MistyCore/node_modules/yaml/dist/compose/resolve-flow-collection.js
new file mode 100644
index 0000000..54eb2a5
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-flow-collection.js
@@ -0,0 +1,202 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+var Pair = require('../nodes/Pair.js');
+var YAMLMap = require('../nodes/YAMLMap.js');
+var YAMLSeq = require('../nodes/YAMLSeq.js');
+var resolveEnd = require('./resolve-end.js');
+var resolveProps = require('./resolve-props.js');
+var utilContainsNewline = require('./util-contains-newline.js');
+var utilMapIncludes = require('./util-map-includes.js');
+
+const blockMsg = 'Block collections are not allowed within flow collections';
+const isBlock = (token) => token && (token.type === 'block-map' || token.type === 'block-seq');
+function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError) {
+ const isMap = fc.start.source === '{';
+ const fcName = isMap ? 'flow map' : 'flow sequence';
+ const coll = isMap
+ ? new YAMLMap.YAMLMap(ctx.schema)
+ : new YAMLSeq.YAMLSeq(ctx.schema);
+ coll.flow = true;
+ const atRoot = ctx.atRoot;
+ if (atRoot)
+ ctx.atRoot = false;
+ let offset = fc.offset + fc.start.source.length;
+ for (let i = 0; i < fc.items.length; ++i) {
+ const collItem = fc.items[i];
+ const { start, key, sep, value } = collItem;
+ const props = resolveProps.resolveProps(start, {
+ flow: fcName,
+ indicator: 'explicit-key-ind',
+ next: key ?? sep?.[0],
+ offset,
+ onError,
+ startOnNewline: false
+ });
+ if (!props.found) {
+ if (!props.anchor && !props.tag && !sep && !value) {
+ if (i === 0 && props.comma)
+ onError(props.comma, 'UNEXPECTED_TOKEN', `Unexpected , in ${fcName}`);
+ else if (i < fc.items.length - 1)
+ onError(props.start, 'UNEXPECTED_TOKEN', `Unexpected empty item in ${fcName}`);
+ if (props.comment) {
+ if (coll.comment)
+ coll.comment += '\n' + props.comment;
+ else
+ coll.comment = props.comment;
+ }
+ offset = props.end;
+ continue;
+ }
+ if (!isMap && ctx.options.strict && utilContainsNewline.containsNewline(key))
+ onError(key, // checked by containsNewline()
+ 'MULTILINE_IMPLICIT_KEY', 'Implicit keys of flow sequence pairs need to be on a single line');
+ }
+ if (i === 0) {
+ if (props.comma)
+ onError(props.comma, 'UNEXPECTED_TOKEN', `Unexpected , in ${fcName}`);
+ }
+ else {
+ if (!props.comma)
+ onError(props.start, 'MISSING_CHAR', `Missing , between ${fcName} items`);
+ if (props.comment) {
+ let prevItemComment = '';
+ loop: for (const st of start) {
+ switch (st.type) {
+ case 'comma':
+ case 'space':
+ break;
+ case 'comment':
+ prevItemComment = st.source.substring(1);
+ break loop;
+ default:
+ break loop;
+ }
+ }
+ if (prevItemComment) {
+ let prev = coll.items[coll.items.length - 1];
+ if (Node.isPair(prev))
+ prev = prev.value ?? prev.key;
+ if (prev.comment)
+ prev.comment += '\n' + prevItemComment;
+ else
+ prev.comment = prevItemComment;
+ props.comment = props.comment.substring(prevItemComment.length + 1);
+ }
+ }
+ }
+ if (!isMap && !sep && !props.found) {
+ // item is a value in a seq
+ // → key & sep are empty, start does not include ? or :
+ const valueNode = value
+ ? composeNode(ctx, value, props, onError)
+ : composeEmptyNode(ctx, props.end, sep, null, props, onError);
+ coll.items.push(valueNode);
+ offset = valueNode.range[2];
+ if (isBlock(value))
+ onError(valueNode.range, 'BLOCK_IN_FLOW', blockMsg);
+ }
+ else {
+ // item is a key+value pair
+ // key value
+ const keyStart = props.end;
+ const keyNode = key
+ ? composeNode(ctx, key, props, onError)
+ : composeEmptyNode(ctx, keyStart, start, null, props, onError);
+ if (isBlock(key))
+ onError(keyNode.range, 'BLOCK_IN_FLOW', blockMsg);
+ // value properties
+ const valueProps = resolveProps.resolveProps(sep ?? [], {
+ flow: fcName,
+ indicator: 'map-value-ind',
+ next: value,
+ offset: keyNode.range[2],
+ onError,
+ startOnNewline: false
+ });
+ if (valueProps.found) {
+ if (!isMap && !props.found && ctx.options.strict) {
+ if (sep)
+ for (const st of sep) {
+ if (st === valueProps.found)
+ break;
+ if (st.type === 'newline') {
+ onError(st, 'MULTILINE_IMPLICIT_KEY', 'Implicit keys of flow sequence pairs need to be on a single line');
+ break;
+ }
+ }
+ if (props.start < valueProps.found.offset - 1024)
+ onError(valueProps.found, 'KEY_OVER_1024_CHARS', 'The : indicator must be at most 1024 chars after the start of an implicit flow sequence key');
+ }
+ }
+ else if (value) {
+ if ('source' in value && value.source && value.source[0] === ':')
+ onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
+ else
+ onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
+ }
+ // value value
+ const valueNode = value
+ ? composeNode(ctx, value, valueProps, onError)
+ : valueProps.found
+ ? composeEmptyNode(ctx, valueProps.end, sep, null, valueProps, onError)
+ : null;
+ if (valueNode) {
+ if (isBlock(value))
+ onError(valueNode.range, 'BLOCK_IN_FLOW', blockMsg);
+ }
+ else if (valueProps.comment) {
+ if (keyNode.comment)
+ keyNode.comment += '\n' + valueProps.comment;
+ else
+ keyNode.comment = valueProps.comment;
+ }
+ const pair = new Pair.Pair(keyNode, valueNode);
+ if (ctx.options.keepSourceTokens)
+ pair.srcToken = collItem;
+ if (isMap) {
+ const map = coll;
+ if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
+ onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');
+ map.items.push(pair);
+ }
+ else {
+ const map = new YAMLMap.YAMLMap(ctx.schema);
+ map.flow = true;
+ map.items.push(pair);
+ coll.items.push(map);
+ }
+ offset = valueNode ? valueNode.range[2] : valueProps.end;
+ }
+ }
+ const expectedEnd = isMap ? '}' : ']';
+ const [ce, ...ee] = fc.end;
+ let cePos = offset;
+ if (ce && ce.source === expectedEnd)
+ cePos = ce.offset + ce.source.length;
+ else {
+ const name = fcName[0].toUpperCase() + fcName.substring(1);
+ const msg = atRoot
+ ? `${name} must end with a ${expectedEnd}`
+ : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
+ onError(offset, atRoot ? 'MISSING_CHAR' : 'BAD_INDENT', msg);
+ if (ce && ce.source.length !== 1)
+ ee.unshift(ce);
+ }
+ if (ee.length > 0) {
+ const end = resolveEnd.resolveEnd(ee, cePos, ctx.options.strict, onError);
+ if (end.comment) {
+ if (coll.comment)
+ coll.comment += '\n' + end.comment;
+ else
+ coll.comment = end.comment;
+ }
+ coll.range = [fc.offset, cePos, end.offset];
+ }
+ else {
+ coll.range = [fc.offset, cePos, cePos];
+ }
+ return coll;
+}
+
+exports.resolveFlowCollection = resolveFlowCollection;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts b/MistyCore/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts
new file mode 100644
index 0000000..0c9204d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts
@@ -0,0 +1,10 @@
+import { Range } from '../nodes/Node.js';
+import { Scalar } from '../nodes/Scalar.js';
+import type { FlowScalar } from '../parse/cst.js';
+import type { ComposeErrorHandler } from './composer.js';
+export declare function resolveFlowScalar(scalar: FlowScalar, strict: boolean, onError: ComposeErrorHandler): {
+ value: string;
+ type: Scalar.PLAIN | Scalar.QUOTE_DOUBLE | Scalar.QUOTE_SINGLE | null;
+ comment: string;
+ range: Range;
+};
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-flow-scalar.js b/MistyCore/node_modules/yaml/dist/compose/resolve-flow-scalar.js
new file mode 100644
index 0000000..cf6257c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-flow-scalar.js
@@ -0,0 +1,225 @@
+'use strict';
+
+var Scalar = require('../nodes/Scalar.js');
+var resolveEnd = require('./resolve-end.js');
+
+function resolveFlowScalar(scalar, strict, onError) {
+ const { offset, type, source, end } = scalar;
+ let _type;
+ let value;
+ const _onError = (rel, code, msg) => onError(offset + rel, code, msg);
+ switch (type) {
+ case 'scalar':
+ _type = Scalar.Scalar.PLAIN;
+ value = plainValue(source, _onError);
+ break;
+ case 'single-quoted-scalar':
+ _type = Scalar.Scalar.QUOTE_SINGLE;
+ value = singleQuotedValue(source, _onError);
+ break;
+ case 'double-quoted-scalar':
+ _type = Scalar.Scalar.QUOTE_DOUBLE;
+ value = doubleQuotedValue(source, _onError);
+ break;
+ /* istanbul ignore next should not happen */
+ default:
+ onError(scalar, 'UNEXPECTED_TOKEN', `Expected a flow scalar value, but found: ${type}`);
+ return {
+ value: '',
+ type: null,
+ comment: '',
+ range: [offset, offset + source.length, offset + source.length]
+ };
+ }
+ const valueEnd = offset + source.length;
+ const re = resolveEnd.resolveEnd(end, valueEnd, strict, onError);
+ return {
+ value,
+ type: _type,
+ comment: re.comment,
+ range: [offset, valueEnd, re.offset]
+ };
+}
+function plainValue(source, onError) {
+ let badChar = '';
+ switch (source[0]) {
+ /* istanbul ignore next should not happen */
+ case '\t':
+ badChar = 'a tab character';
+ break;
+ case ',':
+ badChar = 'flow indicator character ,';
+ break;
+ case '%':
+ badChar = 'directive indicator character %';
+ break;
+ case '|':
+ case '>': {
+ badChar = `block scalar indicator ${source[0]}`;
+ break;
+ }
+ case '@':
+ case '`': {
+ badChar = `reserved character ${source[0]}`;
+ break;
+ }
+ }
+ if (badChar)
+ onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
+ return foldLines(source);
+}
+function singleQuotedValue(source, onError) {
+ if (source[source.length - 1] !== "'" || source.length === 1)
+ onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
+ return foldLines(source.slice(1, -1)).replace(/''/g, "'");
+}
+function foldLines(source) {
+ /**
+ * The negative lookbehind here and in the `re` RegExp is to
+ * prevent causing a polynomial search time in certain cases.
+ *
+ * The try-catch is for Safari, which doesn't support this yet:
+ * https://caniuse.com/js-regexp-lookbehind
+ */
+ let first, line;
+ try {
+ first = new RegExp('(.*?)(?<![ \t])[ \t]*\r?\n', 'sy');
+ line = new RegExp('[ \t]*(.*?)(?:(?<![ \t])[ \t]*)?\r?\n', 'sy');
+ }
+ catch (_) {
+ first = /(.*?)[ \t]*\r?\n/sy;
+ line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
+ }
+ let match = first.exec(source);
+ if (!match)
+ return source;
+ let res = match[1];
+ let sep = ' ';
+ let pos = first.lastIndex;
+ line.lastIndex = pos;
+ while ((match = line.exec(source))) {
+ if (match[1] === '') {
+ if (sep === '\n')
+ res += sep;
+ else
+ sep = '\n';
+ }
+ else {
+ res += sep + match[1];
+ sep = ' ';
+ }
+ pos = line.lastIndex;
+ }
+ const last = /[ \t]*(.*)/sy;
+ last.lastIndex = pos;
+ match = last.exec(source);
+ return res + sep + (match?.[1] ?? '');
+}
+function doubleQuotedValue(source, onError) {
+ let res = '';
+ for (let i = 1; i < source.length - 1; ++i) {
+ const ch = source[i];
+ if (ch === '\r' && source[i + 1] === '\n')
+ continue;
+ if (ch === '\n') {
+ const { fold, offset } = foldNewline(source, i);
+ res += fold;
+ i = offset;
+ }
+ else if (ch === '\\') {
+ let next = source[++i];
+ const cc = escapeCodes[next];
+ if (cc)
+ res += cc;
+ else if (next === '\n') {
+ // skip escaped newlines, but still trim the following line
+ next = source[i + 1];
+ while (next === ' ' || next === '\t')
+ next = source[++i + 1];
+ }
+ else if (next === '\r' && source[i + 1] === '\n') {
+ // skip escaped CRLF newlines, but still trim the following line
+ next = source[++i + 1];
+ while (next === ' ' || next === '\t')
+ next = source[++i + 1];
+ }
+ else if (next === 'x' || next === 'u' || next === 'U') {
+ const length = { x: 2, u: 4, U: 8 }[next];
+ res += parseCharCode(source, i + 1, length, onError);
+ i += length;
+ }
+ else {
+ const raw = source.substr(i - 1, 2);
+ onError(i - 1, 'BAD_DQ_ESCAPE', `Invalid escape sequence ${raw}`);
+ res += raw;
+ }
+ }
+ else if (ch === ' ' || ch === '\t') {
+ // trim trailing whitespace
+ const wsStart = i;
+ let next = source[i + 1];
+ while (next === ' ' || next === '\t')
+ next = source[++i + 1];
+ if (next !== '\n' && !(next === '\r' && source[i + 2] === '\n'))
+ res += i > wsStart ? source.slice(wsStart, i + 1) : ch;
+ }
+ else {
+ res += ch;
+ }
+ }
+ if (source[source.length - 1] !== '"' || source.length === 1)
+ onError(source.length, 'MISSING_CHAR', 'Missing closing "quote');
+ return res;
+}
+/**
+ * Fold a single newline into a space, multiple newlines to N - 1 newlines.
+ * Presumes `source[offset] === '\n'`
+ */
+function foldNewline(source, offset) {
+ let fold = '';
+ let ch = source[offset + 1];
+ while (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r') {
+ if (ch === '\r' && source[offset + 2] !== '\n')
+ break;
+ if (ch === '\n')
+ fold += '\n';
+ offset += 1;
+ ch = source[offset + 1];
+ }
+ if (!fold)
+ fold = ' ';
+ return { fold, offset };
+}
+const escapeCodes = {
+ '0': '\0',
+ a: '\x07',
+ b: '\b',
+ e: '\x1b',
+ f: '\f',
+ n: '\n',
+ r: '\r',
+ t: '\t',
+ v: '\v',
+ N: '\u0085',
+ _: '\u00a0',
+ L: '\u2028',
+ P: '\u2029',
+ ' ': ' ',
+ '"': '"',
+ '/': '/',
+ '\\': '\\',
+ '\t': '\t'
+};
+function parseCharCode(source, offset, length, onError) {
+ const cc = source.substr(offset, length);
+ const ok = cc.length === length && /^[0-9a-fA-F]+$/.test(cc);
+ const code = ok ? parseInt(cc, 16) : NaN;
+ if (isNaN(code)) {
+ const raw = source.substr(offset - 2, length + 2);
+ onError(offset - 2, 'BAD_DQ_ESCAPE', `Invalid escape sequence ${raw}`);
+ return raw;
+ }
+ return String.fromCodePoint(code);
+}
+
+exports.resolveFlowScalar = resolveFlowScalar;
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-props.d.ts b/MistyCore/node_modules/yaml/dist/compose/resolve-props.d.ts
new file mode 100644
index 0000000..fba44cf
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-props.d.ts
@@ -0,0 +1,22 @@
+import type { SourceToken, Token } from '../parse/cst.js';
+import type { ComposeErrorHandler } from './composer.js';
+export interface ResolvePropsArg {
+ flow?: 'flow map' | 'flow sequence';
+ indicator: 'doc-start' | 'explicit-key-ind' | 'map-value-ind' | 'seq-item-ind';
+ next: Token | null | undefined;
+ offset: number;
+ onError: ComposeErrorHandler;
+ startOnNewline: boolean;
+}
+export declare function resolveProps(tokens: SourceToken[], { flow, indicator, next, offset, onError, startOnNewline }: ResolvePropsArg): {
+ comma: SourceToken | null;
+ found: SourceToken | null;
+ spaceBefore: boolean;
+ comment: string;
+ hasNewline: boolean;
+ hasNewlineAfterProp: boolean;
+ anchor: SourceToken | null;
+ tag: SourceToken | null;
+ end: number;
+ start: number;
+};
diff --git a/MistyCore/node_modules/yaml/dist/compose/resolve-props.js b/MistyCore/node_modules/yaml/dist/compose/resolve-props.js
new file mode 100644
index 0000000..bc2ef22
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/resolve-props.js
@@ -0,0 +1,136 @@
+'use strict';
+
+function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnNewline }) {
+ let spaceBefore = false;
+ let atNewline = startOnNewline;
+ let hasSpace = startOnNewline;
+ let comment = '';
+ let commentSep = '';
+ let hasNewline = false;
+ let hasNewlineAfterProp = false;
+ let reqSpace = false;
+ let anchor = null;
+ let tag = null;
+ let comma = null;
+ let found = null;
+ let start = null;
+ for (const token of tokens) {
+ if (reqSpace) {
+ if (token.type !== 'space' &&
+ token.type !== 'newline' &&
+ token.type !== 'comma')
+ onError(token.offset, 'MISSING_CHAR', 'Tags and anchors must be separated from the next token by white space');
+ reqSpace = false;
+ }
+ switch (token.type) {
+ case 'space':
+ // At the doc level, tabs at line start may be parsed
+ // as leading white space rather than indentation.
+ // In a flow collection, only the parser handles indent.
+ if (!flow &&
+ atNewline &&
+ indicator !== 'doc-start' &&
+ token.source[0] === '\t')
+ onError(token, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation');
+ hasSpace = true;
+ break;
+ case 'comment': {
+ if (!hasSpace)
+ onError(token, 'MISSING_CHAR', 'Comments must be separated from other tokens by white space characters');
+ const cb = token.source.substring(1) || ' ';
+ if (!comment)
+ comment = cb;
+ else
+ comment += commentSep + cb;
+ commentSep = '';
+ atNewline = false;
+ break;
+ }
+ case 'newline':
+ if (atNewline) {
+ if (comment)
+ comment += token.source;
+ else
+ spaceBefore = true;
+ }
+ else
+ commentSep += token.source;
+ atNewline = true;
+ hasNewline = true;
+ if (anchor || tag)
+ hasNewlineAfterProp = true;
+ hasSpace = true;
+ break;
+ case 'anchor':
+ if (anchor)
+ onError(token, 'MULTIPLE_ANCHORS', 'A node can have at most one anchor');
+ if (token.source.endsWith(':'))
+ onError(token.offset + token.source.length - 1, 'BAD_ALIAS', 'Anchor ending in : is ambiguous', true);
+ anchor = token;
+ if (start === null)
+ start = token.offset;
+ atNewline = false;
+ hasSpace = false;
+ reqSpace = true;
+ break;
+ case 'tag': {
+ if (tag)
+ onError(token, 'MULTIPLE_TAGS', 'A node can have at most one tag');
+ tag = token;
+ if (start === null)
+ start = token.offset;
+ atNewline = false;
+ hasSpace = false;
+ reqSpace = true;
+ break;
+ }
+ case indicator:
+ // Could here handle preceding comments differently
+ if (anchor || tag)
+ onError(token, 'BAD_PROP_ORDER', `Anchors and tags must be after the ${token.source} indicator`);
+ if (found)
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.source} in ${flow ?? 'collection'}`);
+ found = token;
+ atNewline = false;
+ hasSpace = false;
+ break;
+ case 'comma':
+ if (flow) {
+ if (comma)
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected , in ${flow}`);
+ comma = token;
+ atNewline = false;
+ hasSpace = false;
+ break;
+ }
+ // else fallthrough
+ default:
+ onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.type} token`);
+ atNewline = false;
+ hasSpace = false;
+ }
+ }
+ const last = tokens[tokens.length - 1];
+ const end = last ? last.offset + last.source.length : offset;
+ if (reqSpace &&
+ next &&
+ next.type !== 'space' &&
+ next.type !== 'newline' &&
+ next.type !== 'comma' &&
+ (next.type !== 'scalar' || next.source !== ''))
+ onError(next.offset, 'MISSING_CHAR', 'Tags and anchors must be separated from the next token by white space');
+ return {
+ comma,
+ found,
+ spaceBefore,
+ comment,
+ hasNewline,
+ hasNewlineAfterProp,
+ anchor,
+ tag,
+ end,
+ start: start ?? end
+ };
+}
+
+exports.resolveProps = resolveProps;
diff --git a/MistyCore/node_modules/yaml/dist/compose/util-contains-newline.d.ts b/MistyCore/node_modules/yaml/dist/compose/util-contains-newline.d.ts
new file mode 100644
index 0000000..8155be0
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/util-contains-newline.d.ts
@@ -0,0 +1,2 @@
+import type { Token } from '../parse/cst.js';
+export declare function containsNewline(key: Token | null | undefined): boolean | null;
diff --git a/MistyCore/node_modules/yaml/dist/compose/util-contains-newline.js b/MistyCore/node_modules/yaml/dist/compose/util-contains-newline.js
new file mode 100644
index 0000000..e7aa82d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/util-contains-newline.js
@@ -0,0 +1,36 @@
+'use strict';
+
+function containsNewline(key) {
+ if (!key)
+ return null;
+ switch (key.type) {
+ case 'alias':
+ case 'scalar':
+ case 'double-quoted-scalar':
+ case 'single-quoted-scalar':
+ if (key.source.includes('\n'))
+ return true;
+ if (key.end)
+ for (const st of key.end)
+ if (st.type === 'newline')
+ return true;
+ return false;
+ case 'flow-collection':
+ for (const it of key.items) {
+ for (const st of it.start)
+ if (st.type === 'newline')
+ return true;
+ if (it.sep)
+ for (const st of it.sep)
+ if (st.type === 'newline')
+ return true;
+ if (containsNewline(it.key) || containsNewline(it.value))
+ return true;
+ }
+ return false;
+ default:
+ return true;
+ }
+}
+
+exports.containsNewline = containsNewline;
diff --git a/MistyCore/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts b/MistyCore/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts
new file mode 100644
index 0000000..90499b8
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts
@@ -0,0 +1,2 @@
+import type { Token } from '../parse/cst.js';
+export declare function emptyScalarPosition(offset: number, before: Token[] | undefined, pos: number | null): number;
diff --git a/MistyCore/node_modules/yaml/dist/compose/util-empty-scalar-position.js b/MistyCore/node_modules/yaml/dist/compose/util-empty-scalar-position.js
new file mode 100644
index 0000000..b2cd849
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/util-empty-scalar-position.js
@@ -0,0 +1,29 @@
+'use strict';
+
+function emptyScalarPosition(offset, before, pos) {
+ if (before) {
+ if (pos === null)
+ pos = before.length;
+ for (let i = pos - 1; i >= 0; --i) {
+ let st = before[i];
+ switch (st.type) {
+ case 'space':
+ case 'comment':
+ case 'newline':
+ offset -= st.source.length;
+ continue;
+ }
+ // Technically, an empty scalar is immediately after the last non-empty
+ // node, but it's more useful to place it after any whitespace.
+ st = before[++i];
+ while (st?.type === 'space') {
+ offset += st.source.length;
+ st = before[++i];
+ }
+ break;
+ }
+ }
+ return offset;
+}
+
+exports.emptyScalarPosition = emptyScalarPosition;
diff --git a/MistyCore/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts b/MistyCore/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts
new file mode 100644
index 0000000..64ed1fc
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts
@@ -0,0 +1,3 @@
+import { Token } from '../parse/cst';
+import { ComposeErrorHandler } from './composer';
+export declare function flowIndentCheck(indent: number, fc: Token | null | undefined, onError: ComposeErrorHandler): void;
diff --git a/MistyCore/node_modules/yaml/dist/compose/util-flow-indent-check.js b/MistyCore/node_modules/yaml/dist/compose/util-flow-indent-check.js
new file mode 100644
index 0000000..1e6b06f
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/util-flow-indent-check.js
@@ -0,0 +1,17 @@
+'use strict';
+
+var utilContainsNewline = require('./util-contains-newline.js');
+
+function flowIndentCheck(indent, fc, onError) {
+ if (fc?.type === 'flow-collection') {
+ const end = fc.end[0];
+ if (end.indent === indent &&
+ (end.source === ']' || end.source === '}') &&
+ utilContainsNewline.containsNewline(fc)) {
+ const msg = 'Flow end indicator should be more indented than parent';
+ onError(end, 'BAD_INDENT', msg, true);
+ }
+ }
+}
+
+exports.flowIndentCheck = flowIndentCheck;
diff --git a/MistyCore/node_modules/yaml/dist/compose/util-map-includes.d.ts b/MistyCore/node_modules/yaml/dist/compose/util-map-includes.d.ts
new file mode 100644
index 0000000..5d2c4b3
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/util-map-includes.d.ts
@@ -0,0 +1,4 @@
+import { ParsedNode } from '../nodes/Node';
+import { Pair } from '../nodes/Pair';
+import { ComposeContext } from './compose-node';
+export declare function mapIncludes(ctx: ComposeContext, items: Pair<ParsedNode>[], search: ParsedNode): boolean;
diff --git a/MistyCore/node_modules/yaml/dist/compose/util-map-includes.js b/MistyCore/node_modules/yaml/dist/compose/util-map-includes.js
new file mode 100644
index 0000000..ab03be1
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/compose/util-map-includes.js
@@ -0,0 +1,19 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+
+function mapIncludes(ctx, items, search) {
+ const { uniqueKeys } = ctx.options;
+ if (uniqueKeys === false)
+ return false;
+ const isEqual = typeof uniqueKeys === 'function'
+ ? uniqueKeys
+ : (a, b) => a === b ||
+ (Node.isScalar(a) &&
+ Node.isScalar(b) &&
+ a.value === b.value &&
+ !(a.value === '<<' && ctx.schema.merge));
+ return items.some(pair => isEqual(pair.key, search));
+}
+
+exports.mapIncludes = mapIncludes;
diff --git a/MistyCore/node_modules/yaml/dist/doc/Document.d.ts b/MistyCore/node_modules/yaml/dist/doc/Document.d.ts
new file mode 100644
index 0000000..d525543
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/Document.d.ts
@@ -0,0 +1,139 @@
+import type { YAMLError, YAMLWarning } from '../errors.js';
+import { Alias } from '../nodes/Alias.js';
+import { Node, NodeType, NODE_TYPE, ParsedNode, Range } from '../nodes/Node.js';
+import { Pair } from '../nodes/Pair.js';
+import type { Scalar } from '../nodes/Scalar.js';
+import type { YAMLMap } from '../nodes/YAMLMap.js';
+import type { YAMLSeq } from '../nodes/YAMLSeq.js';
+import type { CreateNodeOptions, DocumentOptions, ParseOptions, SchemaOptions, ToJSOptions, ToStringOptions } from '../options.js';
+import { Schema } from '../schema/Schema.js';
+import { Directives } from './directives.js';
+export declare type Replacer = any[] | ((key: any, value: any) => unknown);
+export declare namespace Document {
+ interface Parsed<T extends ParsedNode = ParsedNode> extends Document<T> {
+ directives: Directives;
+ range: Range;
+ }
+}
+export declare class Document<T extends Node = Node> {
+ readonly [NODE_TYPE]: symbol;
+ /** A comment before this Document */
+ commentBefore: string | null;
+ /** A comment immediately after this Document */
+ comment: string | null;
+ /** The document contents. */
+ contents: T | null;
+ directives?: Directives;
+ /** Errors encountered during parsing. */
+ errors: YAMLError[];
+ options: Required<Omit<ParseOptions & DocumentOptions, '_directives' | 'lineCounter' | 'version'>>;
+ /**
+ * The `[start, value-end, node-end]` character offsets for the part of the
+ * source parsed into this document (undefined if not parsed). The `value-end`
+ * and `node-end` positions are themselves not included in their respective
+ * ranges.
+ */
+ range?: Range;
+ /** The schema used with the document. Use `setSchema()` to change. */
+ schema: Schema;
+ /** Warnings encountered during parsing. */
+ warnings: YAMLWarning[];
+ /**
+ * @param value - The initial value for the document, which will be wrapped
+ * in a Node container.
+ */
+ constructor(value?: any, options?: DocumentOptions & SchemaOptions & ParseOptions & CreateNodeOptions);
+ constructor(value: any, replacer: null | Replacer, options?: DocumentOptions & SchemaOptions & ParseOptions & CreateNodeOptions);
+ /**
+ * Create a deep copy of this Document and its contents.
+ *
+ * Custom Node values that inherit from `Object` still refer to their original instances.
+ */
+ clone(): Document<T>;
+ /** Adds a value to the document. */
+ add(value: any): void;
+ /** Adds a value to the document. */
+ addIn(path: Iterable<unknown>, value: unknown): void;
+ /**
+ * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
+ *
+ * If `node` already has an anchor, `name` is ignored.
+ * Otherwise, the `node.anchor` value will be set to `name`,
+ * or if an anchor with that name is already present in the document,
+ * `name` will be used as a prefix for a new unique anchor.
+ * If `name` is undefined, the generated anchor will use 'a' as a prefix.
+ */
+ createAlias(node: Scalar | YAMLMap | YAMLSeq, name?: string): Alias;
+ /**
+ * Convert any value into a `Node` using the current schema, recursively
+ * turning objects into collections.
+ */
+ createNode<T = unknown>(value: T, options?: CreateNodeOptions): NodeType<T>;
+ createNode<T = unknown>(value: T, replacer: Replacer | CreateNodeOptions | null, options?: CreateNodeOptions): NodeType<T>;
+ /**
+ * Convert a key and a value into a `Pair` using the current schema,
+ * recursively wrapping all values as `Scalar` or `Collection` nodes.
+ */
+ createPair<K extends Node = Node, V extends Node = Node>(key: unknown, value: unknown, options?: CreateNodeOptions): Pair<K, V>;
+ /**
+ * Removes a value from the document.
+ * @returns `true` if the item was found and removed.
+ */
+ delete(key: unknown): boolean;
+ /**
+ * Removes a value from the document.
+ * @returns `true` if the item was found and removed.
+ */
+ deleteIn(path: Iterable<unknown> | null): boolean;
+ /**
+ * Returns item at `key`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ get(key: unknown, keepScalar?: boolean): unknown;
+ /**
+ * Returns item at `path`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ getIn(path: Iterable<unknown> | null, keepScalar?: boolean): unknown;
+ /**
+ * Checks if the document includes a value with the key `key`.
+ */
+ has(key: unknown): boolean;
+ /**
+ * Checks if the document includes a value at `path`.
+ */
+ hasIn(path: Iterable<unknown> | null): boolean;
+ /**
+ * Sets a value in this document. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ set(key: any, value: unknown): void;
+ /**
+ * Sets a value in this document. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ setIn(path: Iterable<unknown> | null, value: unknown): void;
+ /**
+ * Change the YAML version and schema used by the document.
+ * A `null` version disables support for directives, explicit tags, anchors, and aliases.
+ * It also requires the `schema` option to be given as a `Schema` instance value.
+ *
+ * Overrides all previously set schema options.
+ */
+ setSchema(version: '1.1' | '1.2' | 'next' | null, options?: SchemaOptions): void;
+ /** A plain JavaScript representation of the document `contents`. */
+ toJS(opt?: ToJSOptions & {
+ [ignored: string]: unknown;
+ }): any;
+ /**
+ * A JSON representation of the document `contents`.
+ *
+ * @param jsonArg Used by `JSON.stringify` to indicate the array index or
+ * property name.
+ */
+ toJSON(jsonArg?: string | null, onAnchor?: ToJSOptions['onAnchor']): any;
+ /** A YAML representation of the document. */
+ toString(options?: ToStringOptions): string;
+}
diff --git a/MistyCore/node_modules/yaml/dist/doc/Document.js b/MistyCore/node_modules/yaml/dist/doc/Document.js
new file mode 100644
index 0000000..3df7bb4
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/Document.js
@@ -0,0 +1,334 @@
+'use strict';
+
+var Alias = require('../nodes/Alias.js');
+var Collection = require('../nodes/Collection.js');
+var Node = require('../nodes/Node.js');
+var Pair = require('../nodes/Pair.js');
+var toJS = require('../nodes/toJS.js');
+var Schema = require('../schema/Schema.js');
+var stringify = require('../stringify/stringify.js');
+var stringifyDocument = require('../stringify/stringifyDocument.js');
+var anchors = require('./anchors.js');
+var applyReviver = require('./applyReviver.js');
+var createNode = require('./createNode.js');
+var directives = require('./directives.js');
+
+class Document {
+ constructor(value, replacer, options) {
+ /** A comment before this Document */
+ this.commentBefore = null;
+ /** A comment immediately after this Document */
+ this.comment = null;
+ /** Errors encountered during parsing. */
+ this.errors = [];
+ /** Warnings encountered during parsing. */
+ this.warnings = [];
+ Object.defineProperty(this, Node.NODE_TYPE, { value: Node.DOC });
+ let _replacer = null;
+ if (typeof replacer === 'function' || Array.isArray(replacer)) {
+ _replacer = replacer;
+ }
+ else if (options === undefined && replacer) {
+ options = replacer;
+ replacer = undefined;
+ }
+ const opt = Object.assign({
+ intAsBigInt: false,
+ keepSourceTokens: false,
+ logLevel: 'warn',
+ prettyErrors: true,
+ strict: true,
+ uniqueKeys: true,
+ version: '1.2'
+ }, options);
+ this.options = opt;
+ let { version } = opt;
+ if (options?._directives) {
+ this.directives = options._directives.atDocument();
+ if (this.directives.yaml.explicit)
+ version = this.directives.yaml.version;
+ }
+ else
+ this.directives = new directives.Directives({ version });
+ this.setSchema(version, options);
+ if (value === undefined)
+ this.contents = null;
+ else {
+ this.contents = this.createNode(value, _replacer, options);
+ }
+ }
+ /**
+ * Create a deep copy of this Document and its contents.
+ *
+ * Custom Node values that inherit from `Object` still refer to their original instances.
+ */
+ clone() {
+ const copy = Object.create(Document.prototype, {
+ [Node.NODE_TYPE]: { value: Node.DOC }
+ });
+ copy.commentBefore = this.commentBefore;
+ copy.comment = this.comment;
+ copy.errors = this.errors.slice();
+ copy.warnings = this.warnings.slice();
+ copy.options = Object.assign({}, this.options);
+ if (this.directives)
+ copy.directives = this.directives.clone();
+ copy.schema = this.schema.clone();
+ copy.contents = Node.isNode(this.contents)
+ ? this.contents.clone(copy.schema)
+ : this.contents;
+ if (this.range)
+ copy.range = this.range.slice();
+ return copy;
+ }
+ /** Adds a value to the document. */
+ add(value) {
+ if (assertCollection(this.contents))
+ this.contents.add(value);
+ }
+ /** Adds a value to the document. */
+ addIn(path, value) {
+ if (assertCollection(this.contents))
+ this.contents.addIn(path, value);
+ }
+ /**
+ * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
+ *
+ * If `node` already has an anchor, `name` is ignored.
+ * Otherwise, the `node.anchor` value will be set to `name`,
+ * or if an anchor with that name is already present in the document,
+ * `name` will be used as a prefix for a new unique anchor.
+ * If `name` is undefined, the generated anchor will use 'a' as a prefix.
+ */
+ createAlias(node, name) {
+ if (!node.anchor) {
+ const prev = anchors.anchorNames(this);
+ node.anchor =
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ !name || prev.has(name) ? anchors.findNewAnchor(name || 'a', prev) : name;
+ }
+ return new Alias.Alias(node.anchor);
+ }
+ createNode(value, replacer, options) {
+ let _replacer = undefined;
+ if (typeof replacer === 'function') {
+ value = replacer.call({ '': value }, '', value);
+ _replacer = replacer;
+ }
+ else if (Array.isArray(replacer)) {
+ const keyToStr = (v) => typeof v === 'number' || v instanceof String || v instanceof Number;
+ const asStr = replacer.filter(keyToStr).map(String);
+ if (asStr.length > 0)
+ replacer = replacer.concat(asStr);
+ _replacer = replacer;
+ }
+ else if (options === undefined && replacer) {
+ options = replacer;
+ replacer = undefined;
+ }
+ const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options ?? {};
+ const { onAnchor, setAnchors, sourceObjects } = anchors.createNodeAnchors(this,
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ anchorPrefix || 'a');
+ const ctx = {
+ aliasDuplicateObjects: aliasDuplicateObjects ?? true,
+ keepUndefined: keepUndefined ?? false,
+ onAnchor,
+ onTagObj,
+ replacer: _replacer,
+ schema: this.schema,
+ sourceObjects
+ };
+ const node = createNode.createNode(value, tag, ctx);
+ if (flow && Node.isCollection(node))
+ node.flow = true;
+ setAnchors();
+ return node;
+ }
+ /**
+ * Convert a key and a value into a `Pair` using the current schema,
+ * recursively wrapping all values as `Scalar` or `Collection` nodes.
+ */
+ createPair(key, value, options = {}) {
+ const k = this.createNode(key, null, options);
+ const v = this.createNode(value, null, options);
+ return new Pair.Pair(k, v);
+ }
+ /**
+ * Removes a value from the document.
+ * @returns `true` if the item was found and removed.
+ */
+ delete(key) {
+ return assertCollection(this.contents) ? this.contents.delete(key) : false;
+ }
+ /**
+ * Removes a value from the document.
+ * @returns `true` if the item was found and removed.
+ */
+ deleteIn(path) {
+ if (Collection.isEmptyPath(path)) {
+ if (this.contents == null)
+ return false;
+ this.contents = null;
+ return true;
+ }
+ return assertCollection(this.contents)
+ ? this.contents.deleteIn(path)
+ : false;
+ }
+ /**
+ * Returns item at `key`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ get(key, keepScalar) {
+ return Node.isCollection(this.contents)
+ ? this.contents.get(key, keepScalar)
+ : undefined;
+ }
+ /**
+ * Returns item at `path`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ getIn(path, keepScalar) {
+ if (Collection.isEmptyPath(path))
+ return !keepScalar && Node.isScalar(this.contents)
+ ? this.contents.value
+ : this.contents;
+ return Node.isCollection(this.contents)
+ ? this.contents.getIn(path, keepScalar)
+ : undefined;
+ }
+ /**
+ * Checks if the document includes a value with the key `key`.
+ */
+ has(key) {
+ return Node.isCollection(this.contents) ? this.contents.has(key) : false;
+ }
+ /**
+ * Checks if the document includes a value at `path`.
+ */
+ hasIn(path) {
+ if (Collection.isEmptyPath(path))
+ return this.contents !== undefined;
+ return Node.isCollection(this.contents) ? this.contents.hasIn(path) : false;
+ }
+ /**
+ * Sets a value in this document. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ set(key, value) {
+ if (this.contents == null) {
+ this.contents = Collection.collectionFromPath(this.schema, [key], value);
+ }
+ else if (assertCollection(this.contents)) {
+ this.contents.set(key, value);
+ }
+ }
+ /**
+ * Sets a value in this document. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ setIn(path, value) {
+ if (Collection.isEmptyPath(path))
+ this.contents = value;
+ else if (this.contents == null) {
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path), value);
+ }
+ else if (assertCollection(this.contents)) {
+ this.contents.setIn(path, value);
+ }
+ }
+ /**
+ * Change the YAML version and schema used by the document.
+ * A `null` version disables support for directives, explicit tags, anchors, and aliases.
+ * It also requires the `schema` option to be given as a `Schema` instance value.
+ *
+ * Overrides all previously set schema options.
+ */
+ setSchema(version, options = {}) {
+ if (typeof version === 'number')
+ version = String(version);
+ let opt;
+ switch (version) {
+ case '1.1':
+ if (this.directives)
+ this.directives.yaml.version = '1.1';
+ else
+ this.directives = new directives.Directives({ version: '1.1' });
+ opt = { merge: true, resolveKnownTags: false, schema: 'yaml-1.1' };
+ break;
+ case '1.2':
+ case 'next':
+ if (this.directives)
+ this.directives.yaml.version = version;
+ else
+ this.directives = new directives.Directives({ version });
+ opt = { merge: false, resolveKnownTags: true, schema: 'core' };
+ break;
+ case null:
+ if (this.directives)
+ delete this.directives;
+ opt = null;
+ break;
+ default: {
+ const sv = JSON.stringify(version);
+ throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
+ }
+ }
+ // Not using `instanceof Schema` to allow for duck typing
+ if (options.schema instanceof Object)
+ this.schema = options.schema;
+ else if (opt)
+ this.schema = new Schema.Schema(Object.assign(opt, options));
+ else
+ throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
+ }
+ // json & jsonArg are only used from toJSON()
+ toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
+ const ctx = {
+ anchors: new Map(),
+ doc: this,
+ keep: !json,
+ mapAsMap: mapAsMap === true,
+ mapKeyWarned: false,
+ maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100,
+ stringify: stringify.stringify
+ };
+ const res = toJS.toJS(this.contents, jsonArg ?? '', ctx);
+ if (typeof onAnchor === 'function')
+ for (const { count, res } of ctx.anchors.values())
+ onAnchor(res, count);
+ return typeof reviver === 'function'
+ ? applyReviver.applyReviver(reviver, { '': res }, '', res)
+ : res;
+ }
+ /**
+ * A JSON representation of the document `contents`.
+ *
+ * @param jsonArg Used by `JSON.stringify` to indicate the array index or
+ * property name.
+ */
+ toJSON(jsonArg, onAnchor) {
+ return this.toJS({ json: true, jsonArg, mapAsMap: false, onAnchor });
+ }
+ /** A YAML representation of the document. */
+ toString(options = {}) {
+ if (this.errors.length > 0)
+ throw new Error('Document with errors cannot be stringified');
+ if ('indent' in options &&
+ (!Number.isInteger(options.indent) || Number(options.indent) <= 0)) {
+ const s = JSON.stringify(options.indent);
+ throw new Error(`"indent" option must be a positive integer, not ${s}`);
+ }
+ return stringifyDocument.stringifyDocument(this, options);
+ }
+}
+function assertCollection(contents) {
+ if (Node.isCollection(contents))
+ return true;
+ throw new Error('Expected a YAML collection as document contents');
+}
+
+exports.Document = Document;
diff --git a/MistyCore/node_modules/yaml/dist/doc/anchors.d.ts b/MistyCore/node_modules/yaml/dist/doc/anchors.d.ts
new file mode 100644
index 0000000..fac66be
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/anchors.d.ts
@@ -0,0 +1,24 @@
+import { Node } from '../nodes/Node.js';
+import type { Document } from './Document.js';
+/**
+ * Verify that the input string is a valid anchor.
+ *
+ * Will throw on errors.
+ */
+export declare function anchorIsValid(anchor: string): true;
+export declare function anchorNames(root: Document | Node): Set<string>;
+/** Find a new anchor name with the given `prefix` and a one-indexed suffix. */
+export declare function findNewAnchor(prefix: string, exclude: Set<string>): string;
+export declare function createNodeAnchors(doc: Document, prefix: string): {
+ onAnchor: (source: unknown) => string;
+ /**
+ * With circular references, the source node is only resolved after all
+ * of its child nodes are. This is why anchors are set only after all of
+ * the nodes have been created.
+ */
+ setAnchors: () => void;
+ sourceObjects: Map<unknown, {
+ anchor: string | null;
+ node: Node<unknown> | null;
+ }>;
+};
diff --git a/MistyCore/node_modules/yaml/dist/doc/anchors.js b/MistyCore/node_modules/yaml/dist/doc/anchors.js
new file mode 100644
index 0000000..5c51bdb
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/anchors.js
@@ -0,0 +1,77 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+var visit = require('../visit.js');
+
+/**
+ * Verify that the input string is a valid anchor.
+ *
+ * Will throw on errors.
+ */
+function anchorIsValid(anchor) {
+ if (/[\x00-\x19\s,[\]{}]/.test(anchor)) {
+ const sa = JSON.stringify(anchor);
+ const msg = `Anchor must not contain whitespace or control characters: ${sa}`;
+ throw new Error(msg);
+ }
+ return true;
+}
+function anchorNames(root) {
+ const anchors = new Set();
+ visit.visit(root, {
+ Value(_key, node) {
+ if (node.anchor)
+ anchors.add(node.anchor);
+ }
+ });
+ return anchors;
+}
+/** Find a new anchor name with the given `prefix` and a one-indexed suffix. */
+function findNewAnchor(prefix, exclude) {
+ for (let i = 1; true; ++i) {
+ const name = `${prefix}${i}`;
+ if (!exclude.has(name))
+ return name;
+ }
+}
+function createNodeAnchors(doc, prefix) {
+ const aliasObjects = [];
+ const sourceObjects = new Map();
+ let prevAnchors = null;
+ return {
+ onAnchor: (source) => {
+ aliasObjects.push(source);
+ if (!prevAnchors)
+ prevAnchors = anchorNames(doc);
+ const anchor = findNewAnchor(prefix, prevAnchors);
+ prevAnchors.add(anchor);
+ return anchor;
+ },
+ /**
+ * With circular references, the source node is only resolved after all
+ * of its child nodes are. This is why anchors are set only after all of
+ * the nodes have been created.
+ */
+ setAnchors: () => {
+ for (const source of aliasObjects) {
+ const ref = sourceObjects.get(source);
+ if (typeof ref === 'object' &&
+ ref.anchor &&
+ (Node.isScalar(ref.node) || Node.isCollection(ref.node))) {
+ ref.node.anchor = ref.anchor;
+ }
+ else {
+ const error = new Error('Failed to resolve repeated object (this should not happen)');
+ error.source = source;
+ throw error;
+ }
+ }
+ },
+ sourceObjects
+ };
+}
+
+exports.anchorIsValid = anchorIsValid;
+exports.anchorNames = anchorNames;
+exports.createNodeAnchors = createNodeAnchors;
+exports.findNewAnchor = findNewAnchor;
diff --git a/MistyCore/node_modules/yaml/dist/doc/applyReviver.d.ts b/MistyCore/node_modules/yaml/dist/doc/applyReviver.d.ts
new file mode 100644
index 0000000..ac28f2c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/applyReviver.d.ts
@@ -0,0 +1,9 @@
+export declare type Reviver = (key: unknown, value: unknown) => unknown;
+/**
+ * Applies the JSON.parse reviver algorithm as defined in the ECMA-262 spec,
+ * in section 24.5.1.1 "Runtime Semantics: InternalizeJSONProperty" of the
+ * 2021 edition: https://tc39.es/ecma262/#sec-json.parse
+ *
+ * Includes extensions for handling Map and Set objects.
+ */
+export declare function applyReviver(reviver: Reviver, obj: unknown, key: unknown, val: any): unknown;
diff --git a/MistyCore/node_modules/yaml/dist/doc/applyReviver.js b/MistyCore/node_modules/yaml/dist/doc/applyReviver.js
new file mode 100644
index 0000000..8734579
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/applyReviver.js
@@ -0,0 +1,56 @@
+'use strict';
+
+/**
+ * Applies the JSON.parse reviver algorithm as defined in the ECMA-262 spec,
+ * in section 24.5.1.1 "Runtime Semantics: InternalizeJSONProperty" of the
+ * 2021 edition: https://tc39.es/ecma262/#sec-json.parse
+ *
+ * Includes extensions for handling Map and Set objects.
+ */
+function applyReviver(reviver, obj, key, val) {
+ if (val && typeof val === 'object') {
+ if (Array.isArray(val)) {
+ for (let i = 0, len = val.length; i < len; ++i) {
+ const v0 = val[i];
+ const v1 = applyReviver(reviver, val, String(i), v0);
+ if (v1 === undefined)
+ delete val[i];
+ else if (v1 !== v0)
+ val[i] = v1;
+ }
+ }
+ else if (val instanceof Map) {
+ for (const k of Array.from(val.keys())) {
+ const v0 = val.get(k);
+ const v1 = applyReviver(reviver, val, k, v0);
+ if (v1 === undefined)
+ val.delete(k);
+ else if (v1 !== v0)
+ val.set(k, v1);
+ }
+ }
+ else if (val instanceof Set) {
+ for (const v0 of Array.from(val)) {
+ const v1 = applyReviver(reviver, val, v0, v0);
+ if (v1 === undefined)
+ val.delete(v0);
+ else if (v1 !== v0) {
+ val.delete(v0);
+ val.add(v1);
+ }
+ }
+ }
+ else {
+ for (const [k, v0] of Object.entries(val)) {
+ const v1 = applyReviver(reviver, val, k, v0);
+ if (v1 === undefined)
+ delete val[k];
+ else if (v1 !== v0)
+ val[k] = v1;
+ }
+ }
+ }
+ return reviver.call(obj, key, val);
+}
+
+exports.applyReviver = applyReviver;
diff --git a/MistyCore/node_modules/yaml/dist/doc/createNode.d.ts b/MistyCore/node_modules/yaml/dist/doc/createNode.d.ts
new file mode 100644
index 0000000..cfbd35c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/createNode.d.ts
@@ -0,0 +1,17 @@
+import { Node } from '../nodes/Node.js';
+import type { Schema } from '../schema/Schema.js';
+import type { CollectionTag, ScalarTag } from '../schema/types.js';
+import type { Replacer } from './Document.js';
+export interface CreateNodeContext {
+ aliasDuplicateObjects: boolean;
+ keepUndefined: boolean;
+ onAnchor: (source: unknown) => string;
+ onTagObj?: (tagObj: ScalarTag | CollectionTag) => void;
+ sourceObjects: Map<unknown, {
+ anchor: string | null;
+ node: Node | null;
+ }>;
+ replacer?: Replacer;
+ schema: Schema;
+}
+export declare function createNode(value: unknown, tagName: string | undefined, ctx: CreateNodeContext): Node;
diff --git a/MistyCore/node_modules/yaml/dist/doc/createNode.js b/MistyCore/node_modules/yaml/dist/doc/createNode.js
new file mode 100644
index 0000000..0b1bc3f
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/createNode.js
@@ -0,0 +1,87 @@
+'use strict';
+
+var Alias = require('../nodes/Alias.js');
+var Node = require('../nodes/Node.js');
+var Scalar = require('../nodes/Scalar.js');
+
+const defaultTagPrefix = 'tag:yaml.org,2002:';
+function findTagObject(value, tagName, tags) {
+ if (tagName) {
+ const match = tags.filter(t => t.tag === tagName);
+ const tagObj = match.find(t => !t.format) ?? match[0];
+ if (!tagObj)
+ throw new Error(`Tag ${tagName} not found`);
+ return tagObj;
+ }
+ return tags.find(t => t.identify?.(value) && !t.format);
+}
+function createNode(value, tagName, ctx) {
+ if (Node.isDocument(value))
+ value = value.contents;
+ if (Node.isNode(value))
+ return value;
+ if (Node.isPair(value)) {
+ const map = ctx.schema[Node.MAP].createNode?.(ctx.schema, null, ctx);
+ map.items.push(value);
+ return map;
+ }
+ if (value instanceof String ||
+ value instanceof Number ||
+ value instanceof Boolean ||
+ (typeof BigInt !== 'undefined' && value instanceof BigInt) // not supported everywhere
+ ) {
+ // https://tc39.es/ecma262/#sec-serializejsonproperty
+ value = value.valueOf();
+ }
+ const { aliasDuplicateObjects, onAnchor, onTagObj, schema, sourceObjects } = ctx;
+ // Detect duplicate references to the same object & use Alias nodes for all
+ // after first. The `ref` wrapper allows for circular references to resolve.
+ let ref = undefined;
+ if (aliasDuplicateObjects && value && typeof value === 'object') {
+ ref = sourceObjects.get(value);
+ if (ref) {
+ if (!ref.anchor)
+ ref.anchor = onAnchor(value);
+ return new Alias.Alias(ref.anchor);
+ }
+ else {
+ ref = { anchor: null, node: null };
+ sourceObjects.set(value, ref);
+ }
+ }
+ if (tagName?.startsWith('!!'))
+ tagName = defaultTagPrefix + tagName.slice(2);
+ let tagObj = findTagObject(value, tagName, schema.tags);
+ if (!tagObj) {
+ if (value && typeof value.toJSON === 'function') {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+ value = value.toJSON();
+ }
+ if (!value || typeof value !== 'object') {
+ const node = new Scalar.Scalar(value);
+ if (ref)
+ ref.node = node;
+ return node;
+ }
+ tagObj =
+ value instanceof Map
+ ? schema[Node.MAP]
+ : Symbol.iterator in Object(value)
+ ? schema[Node.SEQ]
+ : schema[Node.MAP];
+ }
+ if (onTagObj) {
+ onTagObj(tagObj);
+ delete ctx.onTagObj;
+ }
+ const node = tagObj?.createNode
+ ? tagObj.createNode(ctx.schema, value, ctx)
+ : new Scalar.Scalar(value);
+ if (tagName)
+ node.tag = tagName;
+ if (ref)
+ ref.node = node;
+ return node;
+}
+
+exports.createNode = createNode;
diff --git a/MistyCore/node_modules/yaml/dist/doc/directives.d.ts b/MistyCore/node_modules/yaml/dist/doc/directives.d.ts
new file mode 100644
index 0000000..ff8a2cb
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/directives.d.ts
@@ -0,0 +1,49 @@
+import type { Document } from './Document.js';
+export declare class Directives {
+ static defaultYaml: Directives['yaml'];
+ static defaultTags: Directives['tags'];
+ yaml: {
+ version: '1.1' | '1.2' | 'next';
+ explicit?: boolean;
+ };
+ tags: Record<string, string>;
+ /**
+ * The directives-end/doc-start marker `---`. If `null`, a marker may still be
+ * included in the document's stringified representation.
+ */
+ docStart: true | null;
+ /** The doc-end marker `...`. */
+ docEnd: boolean;
+ /**
+ * Used when parsing YAML 1.1, where:
+ * > If the document specifies no directives, it is parsed using the same
+ * > settings as the previous document. If the document does specify any
+ * > directives, all directives of previous documents, if any, are ignored.
+ */
+ private atNextDocument?;
+ constructor(yaml?: Directives['yaml'], tags?: Directives['tags']);
+ clone(): Directives;
+ /**
+ * During parsing, get a Directives instance for the current document and
+ * update the stream state according to the current version's spec.
+ */
+ atDocument(): Directives;
+ /**
+ * @param onError - May be called even if the action was successful
+ * @returns `true` on success
+ */
+ add(line: string, onError: (offset: number, message: string, warning?: boolean) => void): boolean;
+ /**
+ * Resolves a tag, matching handles to those defined in %TAG directives.
+ *
+ * @returns Resolved tag, which may also be the non-specific tag `'!'` or a
+ * `'!local'` tag, or `null` if unresolvable.
+ */
+ tagName(source: string, onError: (message: string) => void): string | null;
+ /**
+ * Given a fully resolved tag, returns its printable string form,
+ * taking into account current tag prefixes and defaults.
+ */
+ tagString(tag: string): string;
+ toString(doc?: Document): string;
+}
diff --git a/MistyCore/node_modules/yaml/dist/doc/directives.js b/MistyCore/node_modules/yaml/dist/doc/directives.js
new file mode 100644
index 0000000..0fa911c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/doc/directives.js
@@ -0,0 +1,171 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+var visit = require('../visit.js');
+
+const escapeChars = {
+ '!': '%21',
+ ',': '%2C',
+ '[': '%5B',
+ ']': '%5D',
+ '{': '%7B',
+ '}': '%7D'
+};
+const escapeTagName = (tn) => tn.replace(/[!,[\]{}]/g, ch => escapeChars[ch]);
+class Directives {
+ constructor(yaml, tags) {
+ /**
+ * The directives-end/doc-start marker `---`. If `null`, a marker may still be
+ * included in the document's stringified representation.
+ */
+ this.docStart = null;
+ /** The doc-end marker `...`. */
+ this.docEnd = false;
+ this.yaml = Object.assign({}, Directives.defaultYaml, yaml);
+ this.tags = Object.assign({}, Directives.defaultTags, tags);
+ }
+ clone() {
+ const copy = new Directives(this.yaml, this.tags);
+ copy.docStart = this.docStart;
+ return copy;
+ }
+ /**
+ * During parsing, get a Directives instance for the current document and
+ * update the stream state according to the current version's spec.
+ */
+ atDocument() {
+ const res = new Directives(this.yaml, this.tags);
+ switch (this.yaml.version) {
+ case '1.1':
+ this.atNextDocument = true;
+ break;
+ case '1.2':
+ this.atNextDocument = false;
+ this.yaml = {
+ explicit: Directives.defaultYaml.explicit,
+ version: '1.2'
+ };
+ this.tags = Object.assign({}, Directives.defaultTags);
+ break;
+ }
+ return res;
+ }
+ /**
+ * @param onError - May be called even if the action was successful
+ * @returns `true` on success
+ */
+ add(line, onError) {
+ if (this.atNextDocument) {
+ this.yaml = { explicit: Directives.defaultYaml.explicit, version: '1.1' };
+ this.tags = Object.assign({}, Directives.defaultTags);
+ this.atNextDocument = false;
+ }
+ const parts = line.trim().split(/[ \t]+/);
+ const name = parts.shift();
+ switch (name) {
+ case '%TAG': {
+ if (parts.length !== 2) {
+ onError(0, '%TAG directive should contain exactly two parts');
+ if (parts.length < 2)
+ return false;
+ }
+ const [handle, prefix] = parts;
+ this.tags[handle] = prefix;
+ return true;
+ }
+ case '%YAML': {
+ this.yaml.explicit = true;
+ if (parts.length !== 1) {
+ onError(0, '%YAML directive should contain exactly one part');
+ return false;
+ }
+ const [version] = parts;
+ if (version === '1.1' || version === '1.2') {
+ this.yaml.version = version;
+ return true;
+ }
+ else {
+ const isValid = /^\d+\.\d+$/.test(version);
+ onError(6, `Unsupported YAML version ${version}`, isValid);
+ return false;
+ }
+ }
+ default:
+ onError(0, `Unknown directive ${name}`, true);
+ return false;
+ }
+ }
+ /**
+ * Resolves a tag, matching handles to those defined in %TAG directives.
+ *
+ * @returns Resolved tag, which may also be the non-specific tag `'!'` or a
+ * `'!local'` tag, or `null` if unresolvable.
+ */
+ tagName(source, onError) {
+ if (source === '!')
+ return '!'; // non-specific tag
+ if (source[0] !== '!') {
+ onError(`Not a valid tag: ${source}`);
+ return null;
+ }
+ if (source[1] === '<') {
+ const verbatim = source.slice(2, -1);
+ if (verbatim === '!' || verbatim === '!!') {
+ onError(`Verbatim tags aren't resolved, so ${source} is invalid.`);
+ return null;
+ }
+ if (source[source.length - 1] !== '>')
+ onError('Verbatim tags must end with a >');
+ return verbatim;
+ }
+ const [, handle, suffix] = source.match(/^(.*!)([^!]*)$/);
+ if (!suffix)
+ onError(`The ${source} tag has no suffix`);
+ const prefix = this.tags[handle];
+ if (prefix)
+ return prefix + decodeURIComponent(suffix);
+ if (handle === '!')
+ return source; // local tag
+ onError(`Could not resolve tag: ${source}`);
+ return null;
+ }
+ /**
+ * Given a fully resolved tag, returns its printable string form,
+ * taking into account current tag prefixes and defaults.
+ */
+ tagString(tag) {
+ for (const [handle, prefix] of Object.entries(this.tags)) {
+ if (tag.startsWith(prefix))
+ return handle + escapeTagName(tag.substring(prefix.length));
+ }
+ return tag[0] === '!' ? tag : `!<${tag}>`;
+ }
+ toString(doc) {
+ const lines = this.yaml.explicit
+ ? [`%YAML ${this.yaml.version || '1.2'}`]
+ : [];
+ const tagEntries = Object.entries(this.tags);
+ let tagNames;
+ if (doc && tagEntries.length > 0 && Node.isNode(doc.contents)) {
+ const tags = {};
+ visit.visit(doc.contents, (_key, node) => {
+ if (Node.isNode(node) && node.tag)
+ tags[node.tag] = true;
+ });
+ tagNames = Object.keys(tags);
+ }
+ else
+ tagNames = [];
+ for (const [handle, prefix] of tagEntries) {
+ if (handle === '!!' && prefix === 'tag:yaml.org,2002:')
+ continue;
+ if (!doc || tagNames.some(tn => tn.startsWith(prefix)))
+ lines.push(`%TAG ${handle} ${prefix}`);
+ }
+ return lines.join('\n');
+ }
+}
+Directives.defaultYaml = { explicit: false, version: '1.2' };
+Directives.defaultTags = { '!!': 'tag:yaml.org,2002:' };
+
+exports.Directives = Directives;
diff --git a/MistyCore/node_modules/yaml/dist/errors.d.ts b/MistyCore/node_modules/yaml/dist/errors.d.ts
new file mode 100644
index 0000000..1ea1797
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/errors.d.ts
@@ -0,0 +1,21 @@
+import type { LineCounter } from './parse/line-counter';
+export declare type ErrorCode = 'ALIAS_PROPS' | 'BAD_ALIAS' | 'BAD_DIRECTIVE' | 'BAD_DQ_ESCAPE' | 'BAD_INDENT' | 'BAD_PROP_ORDER' | 'BAD_SCALAR_START' | 'BLOCK_AS_IMPLICIT_KEY' | 'BLOCK_IN_FLOW' | 'DUPLICATE_KEY' | 'IMPOSSIBLE' | 'KEY_OVER_1024_CHARS' | 'MISSING_CHAR' | 'MULTILINE_IMPLICIT_KEY' | 'MULTIPLE_ANCHORS' | 'MULTIPLE_DOCS' | 'MULTIPLE_TAGS' | 'TAB_AS_INDENT' | 'TAG_RESOLVE_FAILED' | 'UNEXPECTED_TOKEN';
+export declare type LinePos = {
+ line: number;
+ col: number;
+};
+export declare class YAMLError extends Error {
+ name: 'YAMLParseError' | 'YAMLWarning';
+ code: ErrorCode;
+ message: string;
+ pos: [number, number];
+ linePos?: [LinePos] | [LinePos, LinePos];
+ constructor(name: YAMLError['name'], pos: [number, number], code: ErrorCode, message: string);
+}
+export declare class YAMLParseError extends YAMLError {
+ constructor(pos: [number, number], code: ErrorCode, message: string);
+}
+export declare class YAMLWarning extends YAMLError {
+ constructor(pos: [number, number], code: ErrorCode, message: string);
+}
+export declare const prettifyError: (src: string, lc: LineCounter) => (error: YAMLError) => void;
diff --git a/MistyCore/node_modules/yaml/dist/errors.js b/MistyCore/node_modules/yaml/dist/errors.js
new file mode 100644
index 0000000..39f49fa
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/errors.js
@@ -0,0 +1,62 @@
+'use strict';
+
+class YAMLError extends Error {
+ constructor(name, pos, code, message) {
+ super();
+ this.name = name;
+ this.code = code;
+ this.message = message;
+ this.pos = pos;
+ }
+}
+class YAMLParseError extends YAMLError {
+ constructor(pos, code, message) {
+ super('YAMLParseError', pos, code, message);
+ }
+}
+class YAMLWarning extends YAMLError {
+ constructor(pos, code, message) {
+ super('YAMLWarning', pos, code, message);
+ }
+}
+const prettifyError = (src, lc) => (error) => {
+ if (error.pos[0] === -1)
+ return;
+ error.linePos = error.pos.map(pos => lc.linePos(pos));
+ const { line, col } = error.linePos[0];
+ error.message += ` at line ${line}, column ${col}`;
+ let ci = col - 1;
+ let lineStr = src
+ .substring(lc.lineStarts[line - 1], lc.lineStarts[line])
+ .replace(/[\n\r]+$/, '');
+ // Trim to max 80 chars, keeping col position near the middle
+ if (ci >= 60 && lineStr.length > 80) {
+ const trimStart = Math.min(ci - 39, lineStr.length - 79);
+ lineStr = '…' + lineStr.substring(trimStart);
+ ci -= trimStart - 1;
+ }
+ if (lineStr.length > 80)
+ lineStr = lineStr.substring(0, 79) + '…';
+ // Include previous line in context if pointing at line start
+ if (line > 1 && /^ *$/.test(lineStr.substring(0, ci))) {
+ // Regexp won't match if start is trimmed
+ let prev = src.substring(lc.lineStarts[line - 2], lc.lineStarts[line - 1]);
+ if (prev.length > 80)
+ prev = prev.substring(0, 79) + '…\n';
+ lineStr = prev + lineStr;
+ }
+ if (/[^ ]/.test(lineStr)) {
+ let count = 1;
+ const end = error.linePos[1];
+ if (end && end.line === line && end.col > col) {
+ count = Math.min(end.col - col, 80 - ci);
+ }
+ const pointer = ' '.repeat(ci) + '^'.repeat(count);
+ error.message += `:\n\n${lineStr}\n${pointer}\n`;
+ }
+};
+
+exports.YAMLError = YAMLError;
+exports.YAMLParseError = YAMLParseError;
+exports.YAMLWarning = YAMLWarning;
+exports.prettifyError = prettifyError;
diff --git a/MistyCore/node_modules/yaml/dist/index.d.ts b/MistyCore/node_modules/yaml/dist/index.d.ts
new file mode 100644
index 0000000..0c6ca6e
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/index.d.ts
@@ -0,0 +1,21 @@
+export { Composer } from './compose/composer.js';
+export { Document } from './doc/Document.js';
+export { Schema } from './schema/Schema.js';
+export { ErrorCode, YAMLError, YAMLParseError, YAMLWarning } from './errors.js';
+export { Alias } from './nodes/Alias.js';
+export { isAlias, isCollection, isDocument, isMap, isNode, isPair, isScalar, isSeq, Node, ParsedNode, Range } from './nodes/Node.js';
+export { Pair } from './nodes/Pair.js';
+export { Scalar } from './nodes/Scalar.js';
+export { YAMLMap } from './nodes/YAMLMap.js';
+export { YAMLSeq } from './nodes/YAMLSeq.js';
+export type { CreateNodeOptions, DocumentOptions, ParseOptions, SchemaOptions, ToJSOptions, ToStringOptions } from './options.js';
+export * as CST from './parse/cst.js';
+export { Lexer } from './parse/lexer.js';
+export { LineCounter } from './parse/line-counter.js';
+export { Parser } from './parse/parser.js';
+export { EmptyStream, parse, parseAllDocuments, parseDocument, stringify } from './public-api.js';
+export type { TagId, Tags } from './schema/tags';
+export type { CollectionTag, ScalarTag } from './schema/types';
+export type { YAMLOMap } from './schema/yaml-1.1/omap';
+export type { YAMLSet } from './schema/yaml-1.1/set';
+export { asyncVisitor, asyncVisitorFn, visit, visitAsync, visitor, visitorFn } from './visit.js';
diff --git a/MistyCore/node_modules/yaml/dist/index.js b/MistyCore/node_modules/yaml/dist/index.js
new file mode 100644
index 0000000..b013fae
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/index.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var composer = require('./compose/composer.js');
+var Document = require('./doc/Document.js');
+var Schema = require('./schema/Schema.js');
+var errors = require('./errors.js');
+var Alias = require('./nodes/Alias.js');
+var Node = require('./nodes/Node.js');
+var Pair = require('./nodes/Pair.js');
+var Scalar = require('./nodes/Scalar.js');
+var YAMLMap = require('./nodes/YAMLMap.js');
+var YAMLSeq = require('./nodes/YAMLSeq.js');
+var cst = require('./parse/cst.js');
+var lexer = require('./parse/lexer.js');
+var lineCounter = require('./parse/line-counter.js');
+var parser = require('./parse/parser.js');
+var publicApi = require('./public-api.js');
+var visit = require('./visit.js');
+
+
+
+exports.Composer = composer.Composer;
+exports.Document = Document.Document;
+exports.Schema = Schema.Schema;
+exports.YAMLError = errors.YAMLError;
+exports.YAMLParseError = errors.YAMLParseError;
+exports.YAMLWarning = errors.YAMLWarning;
+exports.Alias = Alias.Alias;
+exports.isAlias = Node.isAlias;
+exports.isCollection = Node.isCollection;
+exports.isDocument = Node.isDocument;
+exports.isMap = Node.isMap;
+exports.isNode = Node.isNode;
+exports.isPair = Node.isPair;
+exports.isScalar = Node.isScalar;
+exports.isSeq = Node.isSeq;
+exports.Pair = Pair.Pair;
+exports.Scalar = Scalar.Scalar;
+exports.YAMLMap = YAMLMap.YAMLMap;
+exports.YAMLSeq = YAMLSeq.YAMLSeq;
+exports.CST = cst;
+exports.Lexer = lexer.Lexer;
+exports.LineCounter = lineCounter.LineCounter;
+exports.Parser = parser.Parser;
+exports.parse = publicApi.parse;
+exports.parseAllDocuments = publicApi.parseAllDocuments;
+exports.parseDocument = publicApi.parseDocument;
+exports.stringify = publicApi.stringify;
+exports.visit = visit.visit;
+exports.visitAsync = visit.visitAsync;
diff --git a/MistyCore/node_modules/yaml/dist/log.d.ts b/MistyCore/node_modules/yaml/dist/log.d.ts
new file mode 100644
index 0000000..d5f4e07
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/log.d.ts
@@ -0,0 +1,3 @@
+export declare type LogLevelId = 'silent' | 'error' | 'warn' | 'debug';
+export declare function debug(logLevel: LogLevelId, ...messages: any[]): void;
+export declare function warn(logLevel: LogLevelId, warning: string | Error): void;
diff --git a/MistyCore/node_modules/yaml/dist/log.js b/MistyCore/node_modules/yaml/dist/log.js
new file mode 100644
index 0000000..fac7d5a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/log.js
@@ -0,0 +1,17 @@
+'use strict';
+
+function debug(logLevel, ...messages) {
+ if (logLevel === 'debug')
+ console.log(...messages);
+}
+function warn(logLevel, warning) {
+ if (logLevel === 'debug' || logLevel === 'warn') {
+ if (typeof process !== 'undefined' && process.emitWarning)
+ process.emitWarning(warning);
+ else
+ console.warn(warning);
+ }
+}
+
+exports.debug = debug;
+exports.warn = warn;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Alias.d.ts b/MistyCore/node_modules/yaml/dist/nodes/Alias.d.ts
new file mode 100644
index 0000000..4d05aec
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Alias.d.ts
@@ -0,0 +1,28 @@
+import type { Document } from '../doc/Document.js';
+import type { FlowScalar } from '../parse/cst.js';
+import type { StringifyContext } from '../stringify/stringify.js';
+import { NodeBase, Range } from './Node.js';
+import type { Scalar } from './Scalar';
+import type { ToJSContext } from './toJS.js';
+import type { YAMLMap } from './YAMLMap.js';
+import type { YAMLSeq } from './YAMLSeq.js';
+export declare namespace Alias {
+ interface Parsed extends Alias {
+ range: Range;
+ srcToken?: FlowScalar & {
+ type: 'alias';
+ };
+ }
+}
+export declare class Alias extends NodeBase {
+ source: string;
+ anchor?: never;
+ constructor(source: string);
+ /**
+ * Resolve the value of this alias within `doc`, finding the last
+ * instance of the `source` anchor before this node.
+ */
+ resolve(doc: Document): Scalar | YAMLMap | YAMLSeq | undefined;
+ toJSON(_arg?: unknown, ctx?: ToJSContext): {} | null;
+ toString(ctx?: StringifyContext, _onComment?: () => void, _onChompKeep?: () => void): string;
+}
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Alias.js b/MistyCore/node_modules/yaml/dist/nodes/Alias.js
new file mode 100644
index 0000000..75853cf
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Alias.js
@@ -0,0 +1,96 @@
+'use strict';
+
+var anchors = require('../doc/anchors.js');
+var visit = require('../visit.js');
+var Node = require('./Node.js');
+
+class Alias extends Node.NodeBase {
+ constructor(source) {
+ super(Node.ALIAS);
+ this.source = source;
+ Object.defineProperty(this, 'tag', {
+ set() {
+ throw new Error('Alias nodes cannot have tags');
+ }
+ });
+ }
+ /**
+ * Resolve the value of this alias within `doc`, finding the last
+ * instance of the `source` anchor before this node.
+ */
+ resolve(doc) {
+ let found = undefined;
+ visit.visit(doc, {
+ Node: (_key, node) => {
+ if (node === this)
+ return visit.visit.BREAK;
+ if (node.anchor === this.source)
+ found = node;
+ }
+ });
+ return found;
+ }
+ toJSON(_arg, ctx) {
+ if (!ctx)
+ return { source: this.source };
+ const { anchors, doc, maxAliasCount } = ctx;
+ const source = this.resolve(doc);
+ if (!source) {
+ const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
+ throw new ReferenceError(msg);
+ }
+ const data = anchors.get(source);
+ /* istanbul ignore if */
+ if (!data || data.res === undefined) {
+ const msg = 'This should not happen: Alias anchor was not resolved?';
+ throw new ReferenceError(msg);
+ }
+ if (maxAliasCount >= 0) {
+ data.count += 1;
+ if (data.aliasCount === 0)
+ data.aliasCount = getAliasCount(doc, source, anchors);
+ if (data.count * data.aliasCount > maxAliasCount) {
+ const msg = 'Excessive alias count indicates a resource exhaustion attack';
+ throw new ReferenceError(msg);
+ }
+ }
+ return data.res;
+ }
+ toString(ctx, _onComment, _onChompKeep) {
+ const src = `*${this.source}`;
+ if (ctx) {
+ anchors.anchorIsValid(this.source);
+ if (ctx.options.verifyAliasOrder && !ctx.anchors.has(this.source)) {
+ const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
+ throw new Error(msg);
+ }
+ if (ctx.implicitKey)
+ return `${src} `;
+ }
+ return src;
+ }
+}
+function getAliasCount(doc, node, anchors) {
+ if (Node.isAlias(node)) {
+ const source = node.resolve(doc);
+ const anchor = anchors && source && anchors.get(source);
+ return anchor ? anchor.count * anchor.aliasCount : 0;
+ }
+ else if (Node.isCollection(node)) {
+ let count = 0;
+ for (const item of node.items) {
+ const c = getAliasCount(doc, item, anchors);
+ if (c > count)
+ count = c;
+ }
+ return count;
+ }
+ else if (Node.isPair(node)) {
+ const kc = getAliasCount(doc, node.key, anchors);
+ const vc = getAliasCount(doc, node.value, anchors);
+ return Math.max(kc, vc);
+ }
+ return 1;
+}
+
+exports.Alias = Alias;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Collection.d.ts b/MistyCore/node_modules/yaml/dist/nodes/Collection.d.ts
new file mode 100644
index 0000000..0ac6568
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Collection.d.ts
@@ -0,0 +1,73 @@
+import type { Schema } from '../schema/Schema.js';
+import { NodeBase, NODE_TYPE } from './Node.js';
+export declare function collectionFromPath(schema: Schema, path: unknown[], value: unknown): import("./Node.js").Node<unknown>;
+export declare const isEmptyPath: (path: Iterable<unknown> | null | undefined) => path is null | undefined;
+export declare abstract class Collection extends NodeBase {
+ static maxFlowStringSingleLineLength: number;
+ schema: Schema | undefined;
+ [NODE_TYPE]: symbol;
+ items: unknown[];
+ /** An optional anchor on this node. Used by alias nodes. */
+ anchor?: string;
+ /**
+ * If true, stringify this and all child nodes using flow rather than
+ * block styles.
+ */
+ flow?: boolean;
+ constructor(type: symbol, schema?: Schema);
+ /**
+ * Create a copy of this collection.
+ *
+ * @param schema - If defined, overwrites the original's schema
+ */
+ clone(schema?: Schema): Collection;
+ /** Adds a value to the collection. */
+ abstract add(value: unknown): void;
+ /**
+ * Removes a value from the collection.
+ * @returns `true` if the item was found and removed.
+ */
+ abstract delete(key: unknown): boolean;
+ /**
+ * Returns item at `key`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ abstract get(key: unknown, keepScalar?: boolean): unknown;
+ /**
+ * Checks if the collection includes a value with the key `key`.
+ */
+ abstract has(key: unknown): boolean;
+ /**
+ * Sets a value in this collection. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ abstract set(key: unknown, value: unknown): void;
+ /**
+ * Adds a value to the collection. For `!!map` and `!!omap` the value must
+ * be a Pair instance or a `{ key, value }` object, which may not have a key
+ * that already exists in the map.
+ */
+ addIn(path: Iterable<unknown>, value: unknown): void;
+ /**
+ * Removes a value from the collection.
+ * @returns `true` if the item was found and removed.
+ */
+ deleteIn(path: Iterable<unknown>): boolean;
+ /**
+ * Returns item at `key`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ getIn(path: Iterable<unknown>, keepScalar?: boolean): unknown;
+ hasAllNullValues(allowScalar?: boolean): boolean;
+ /**
+ * Checks if the collection includes a value with the key `key`.
+ */
+ hasIn(path: Iterable<unknown>): boolean;
+ /**
+ * Sets a value in this collection. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ setIn(path: Iterable<unknown>, value: unknown): void;
+}
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Collection.js b/MistyCore/node_modules/yaml/dist/nodes/Collection.js
new file mode 100644
index 0000000..f9d2571
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Collection.js
@@ -0,0 +1,151 @@
+'use strict';
+
+var createNode = require('../doc/createNode.js');
+var Node = require('./Node.js');
+
+function collectionFromPath(schema, path, value) {
+ let v = value;
+ for (let i = path.length - 1; i >= 0; --i) {
+ const k = path[i];
+ if (typeof k === 'number' && Number.isInteger(k) && k >= 0) {
+ const a = [];
+ a[k] = v;
+ v = a;
+ }
+ else {
+ v = new Map([[k, v]]);
+ }
+ }
+ return createNode.createNode(v, undefined, {
+ aliasDuplicateObjects: false,
+ keepUndefined: false,
+ onAnchor: () => {
+ throw new Error('This should not happen, please report a bug.');
+ },
+ schema,
+ sourceObjects: new Map()
+ });
+}
+// Type guard is intentionally a little wrong so as to be more useful,
+// as it does not cover untypable empty non-string iterables (e.g. []).
+const isEmptyPath = (path) => path == null ||
+ (typeof path === 'object' && !!path[Symbol.iterator]().next().done);
+class Collection extends Node.NodeBase {
+ constructor(type, schema) {
+ super(type);
+ Object.defineProperty(this, 'schema', {
+ value: schema,
+ configurable: true,
+ enumerable: false,
+ writable: true
+ });
+ }
+ /**
+ * Create a copy of this collection.
+ *
+ * @param schema - If defined, overwrites the original's schema
+ */
+ clone(schema) {
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
+ if (schema)
+ copy.schema = schema;
+ copy.items = copy.items.map(it => Node.isNode(it) || Node.isPair(it) ? it.clone(schema) : it);
+ if (this.range)
+ copy.range = this.range.slice();
+ return copy;
+ }
+ /**
+ * Adds a value to the collection. For `!!map` and `!!omap` the value must
+ * be a Pair instance or a `{ key, value }` object, which may not have a key
+ * that already exists in the map.
+ */
+ addIn(path, value) {
+ if (isEmptyPath(path))
+ this.add(value);
+ else {
+ const [key, ...rest] = path;
+ const node = this.get(key, true);
+ if (Node.isCollection(node))
+ node.addIn(rest, value);
+ else if (node === undefined && this.schema)
+ this.set(key, collectionFromPath(this.schema, rest, value));
+ else
+ throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
+ }
+ }
+ /**
+ * Removes a value from the collection.
+ * @returns `true` if the item was found and removed.
+ */
+ deleteIn(path) {
+ const [key, ...rest] = path;
+ if (rest.length === 0)
+ return this.delete(key);
+ const node = this.get(key, true);
+ if (Node.isCollection(node))
+ return node.deleteIn(rest);
+ else
+ throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
+ }
+ /**
+ * Returns item at `key`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ */
+ getIn(path, keepScalar) {
+ const [key, ...rest] = path;
+ const node = this.get(key, true);
+ if (rest.length === 0)
+ return !keepScalar && Node.isScalar(node) ? node.value : node;
+ else
+ return Node.isCollection(node) ? node.getIn(rest, keepScalar) : undefined;
+ }
+ hasAllNullValues(allowScalar) {
+ return this.items.every(node => {
+ if (!Node.isPair(node))
+ return false;
+ const n = node.value;
+ return (n == null ||
+ (allowScalar &&
+ Node.isScalar(n) &&
+ n.value == null &&
+ !n.commentBefore &&
+ !n.comment &&
+ !n.tag));
+ });
+ }
+ /**
+ * Checks if the collection includes a value with the key `key`.
+ */
+ hasIn(path) {
+ const [key, ...rest] = path;
+ if (rest.length === 0)
+ return this.has(key);
+ const node = this.get(key, true);
+ return Node.isCollection(node) ? node.hasIn(rest) : false;
+ }
+ /**
+ * Sets a value in this collection. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ */
+ setIn(path, value) {
+ const [key, ...rest] = path;
+ if (rest.length === 0) {
+ this.set(key, value);
+ }
+ else {
+ const node = this.get(key, true);
+ if (Node.isCollection(node))
+ node.setIn(rest, value);
+ else if (node === undefined && this.schema)
+ this.set(key, collectionFromPath(this.schema, rest, value));
+ else
+ throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
+ }
+ }
+}
+Collection.maxFlowStringSingleLineLength = 60;
+
+exports.Collection = Collection;
+exports.collectionFromPath = collectionFromPath;
+exports.isEmptyPath = isEmptyPath;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Node.d.ts b/MistyCore/node_modules/yaml/dist/nodes/Node.d.ts
new file mode 100644
index 0000000..0514e69
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Node.d.ts
@@ -0,0 +1,59 @@
+import type { Document } from '../doc/Document.js';
+import { Token } from '../parse/cst.js';
+import type { StringifyContext } from '../stringify/stringify.js';
+import type { Alias } from './Alias.js';
+import type { Pair } from './Pair.js';
+import type { Scalar } from './Scalar.js';
+import type { YAMLMap } from './YAMLMap.js';
+import type { YAMLSeq } from './YAMLSeq.js';
+export declare type Node<T = unknown> = Alias | Scalar<T> | YAMLMap<unknown, T> | YAMLSeq<T>;
+/** Utility type mapper */
+export declare type NodeType<T> = T extends string | number | bigint | boolean | null ? Scalar<T> : T extends Array<any> ? YAMLSeq<NodeType<T[number]>> : T extends {
+ [key: string]: any;
+} ? YAMLMap<NodeType<keyof T>, NodeType<T[keyof T]>> : T extends {
+ [key: number]: any;
+} ? YAMLMap<NodeType<keyof T>, NodeType<T[keyof T]>> : Node;
+export declare type ParsedNode = Alias.Parsed | Scalar.Parsed | YAMLMap.Parsed | YAMLSeq.Parsed;
+export declare type Range = [number, number, number];
+export declare const ALIAS: unique symbol;
+export declare const DOC: unique symbol;
+export declare const MAP: unique symbol;
+export declare const PAIR: unique symbol;
+export declare const SCALAR: unique symbol;
+export declare const SEQ: unique symbol;
+export declare const NODE_TYPE: unique symbol;
+export declare const isAlias: (node: any) => node is Alias;
+export declare const isDocument: <T extends Node<unknown> = Node<unknown>>(node: any) => node is Document<T>;
+export declare const isMap: <K = unknown, V = unknown>(node: any) => node is YAMLMap<K, V>;
+export declare const isPair: <K = unknown, V = unknown>(node: any) => node is Pair<K, V>;
+export declare const isScalar: <T = unknown>(node: any) => node is Scalar<T>;
+export declare const isSeq: <T = unknown>(node: any) => node is YAMLSeq<T>;
+export declare function isCollection<K = unknown, V = unknown>(node: any): node is YAMLMap<K, V> | YAMLSeq<V>;
+export declare function isNode<T = unknown>(node: any): node is Node<T>;
+export declare const hasAnchor: <K = unknown, V = unknown>(node: unknown) => node is Scalar<V> | YAMLMap<K, V> | YAMLSeq<V>;
+export declare abstract class NodeBase {
+ readonly [NODE_TYPE]: symbol;
+ /** A comment on or immediately after this */
+ comment?: string | null;
+ /** A comment before this */
+ commentBefore?: string | null;
+ /**
+ * The `[start, value-end, node-end]` character offsets for the part of the
+ * source parsed into this node (undefined if not parsed). The `value-end`
+ * and `node-end` positions are themselves not included in their respective
+ * ranges.
+ */
+ range?: Range | null;
+ /** A blank line before this node and its commentBefore */
+ spaceBefore?: boolean;
+ /** The CST token that was composed into this node. */
+ srcToken?: Token;
+ /** A fully qualified tag, if required */
+ tag?: string;
+ /** A plain JS representation of this node */
+ abstract toJSON(): any;
+ abstract toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
+ constructor(type: symbol);
+ /** Create a copy of this node. */
+ clone(): NodeBase;
+}
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Node.js b/MistyCore/node_modules/yaml/dist/nodes/Node.js
new file mode 100644
index 0000000..4ddff6a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Node.js
@@ -0,0 +1,66 @@
+'use strict';
+
+const ALIAS = Symbol.for('yaml.alias');
+const DOC = Symbol.for('yaml.document');
+const MAP = Symbol.for('yaml.map');
+const PAIR = Symbol.for('yaml.pair');
+const SCALAR = Symbol.for('yaml.scalar');
+const SEQ = Symbol.for('yaml.seq');
+const NODE_TYPE = Symbol.for('yaml.node.type');
+const isAlias = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === ALIAS;
+const isDocument = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === DOC;
+const isMap = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === MAP;
+const isPair = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === PAIR;
+const isScalar = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SCALAR;
+const isSeq = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SEQ;
+function isCollection(node) {
+ if (node && typeof node === 'object')
+ switch (node[NODE_TYPE]) {
+ case MAP:
+ case SEQ:
+ return true;
+ }
+ return false;
+}
+function isNode(node) {
+ if (node && typeof node === 'object')
+ switch (node[NODE_TYPE]) {
+ case ALIAS:
+ case MAP:
+ case SCALAR:
+ case SEQ:
+ return true;
+ }
+ return false;
+}
+const hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor;
+class NodeBase {
+ constructor(type) {
+ Object.defineProperty(this, NODE_TYPE, { value: type });
+ }
+ /** Create a copy of this node. */
+ clone() {
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
+ if (this.range)
+ copy.range = this.range.slice();
+ return copy;
+ }
+}
+
+exports.ALIAS = ALIAS;
+exports.DOC = DOC;
+exports.MAP = MAP;
+exports.NODE_TYPE = NODE_TYPE;
+exports.NodeBase = NodeBase;
+exports.PAIR = PAIR;
+exports.SCALAR = SCALAR;
+exports.SEQ = SEQ;
+exports.hasAnchor = hasAnchor;
+exports.isAlias = isAlias;
+exports.isCollection = isCollection;
+exports.isDocument = isDocument;
+exports.isMap = isMap;
+exports.isNode = isNode;
+exports.isPair = isPair;
+exports.isScalar = isScalar;
+exports.isSeq = isSeq;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Pair.d.ts b/MistyCore/node_modules/yaml/dist/nodes/Pair.d.ts
new file mode 100644
index 0000000..f7bef97
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Pair.d.ts
@@ -0,0 +1,21 @@
+import { CreateNodeContext } from '../doc/createNode.js';
+import type { CollectionItem } from '../parse/cst.js';
+import type { Schema } from '../schema/Schema.js';
+import type { StringifyContext } from '../stringify/stringify.js';
+import { addPairToJSMap } from './addPairToJSMap.js';
+import { NODE_TYPE } from './Node.js';
+import type { ToJSContext } from './toJS.js';
+export declare function createPair(key: unknown, value: unknown, ctx: CreateNodeContext): Pair<import("./Node.js").Node<unknown>, import("./Alias.js").Alias | import("./Scalar.js").Scalar<unknown> | import("./YAMLMap.js").YAMLMap<unknown, unknown> | import("./YAMLSeq.js").YAMLSeq<unknown>>;
+export declare class Pair<K = unknown, V = unknown> {
+ readonly [NODE_TYPE]: symbol;
+ /** Always Node or null when parsed, but can be set to anything. */
+ key: K;
+ /** Always Node or null when parsed, but can be set to anything. */
+ value: V | null;
+ /** The CST token that was composed into this pair. */
+ srcToken?: CollectionItem;
+ constructor(key: K, value?: V | null);
+ clone(schema?: Schema): Pair<K, V>;
+ toJSON(_?: unknown, ctx?: ToJSContext): ReturnType<typeof addPairToJSMap>;
+ toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
+}
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Pair.js b/MistyCore/node_modules/yaml/dist/nodes/Pair.js
new file mode 100644
index 0000000..815ced2
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Pair.js
@@ -0,0 +1,39 @@
+'use strict';
+
+var createNode = require('../doc/createNode.js');
+var stringifyPair = require('../stringify/stringifyPair.js');
+var addPairToJSMap = require('./addPairToJSMap.js');
+var Node = require('./Node.js');
+
+function createPair(key, value, ctx) {
+ const k = createNode.createNode(key, undefined, ctx);
+ const v = createNode.createNode(value, undefined, ctx);
+ return new Pair(k, v);
+}
+class Pair {
+ constructor(key, value = null) {
+ Object.defineProperty(this, Node.NODE_TYPE, { value: Node.PAIR });
+ this.key = key;
+ this.value = value;
+ }
+ clone(schema) {
+ let { key, value } = this;
+ if (Node.isNode(key))
+ key = key.clone(schema);
+ if (Node.isNode(value))
+ value = value.clone(schema);
+ return new Pair(key, value);
+ }
+ toJSON(_, ctx) {
+ const pair = ctx?.mapAsMap ? new Map() : {};
+ return addPairToJSMap.addPairToJSMap(ctx, pair, this);
+ }
+ toString(ctx, onComment, onChompKeep) {
+ return ctx?.doc
+ ? stringifyPair.stringifyPair(this, ctx, onComment, onChompKeep)
+ : JSON.stringify(this);
+ }
+}
+
+exports.Pair = Pair;
+exports.createPair = createPair;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Scalar.d.ts b/MistyCore/node_modules/yaml/dist/nodes/Scalar.d.ts
new file mode 100644
index 0000000..dd330b2
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Scalar.d.ts
@@ -0,0 +1,42 @@
+import type { BlockScalar, FlowScalar } from '../parse/cst.js';
+import { NodeBase, Range } from './Node.js';
+import { ToJSContext } from './toJS.js';
+export declare const isScalarValue: (value: unknown) => boolean;
+export declare namespace Scalar {
+ interface Parsed extends Scalar {
+ range: Range;
+ source: string;
+ srcToken?: FlowScalar | BlockScalar;
+ }
+ type BLOCK_FOLDED = 'BLOCK_FOLDED';
+ type BLOCK_LITERAL = 'BLOCK_LITERAL';
+ type PLAIN = 'PLAIN';
+ type QUOTE_DOUBLE = 'QUOTE_DOUBLE';
+ type QUOTE_SINGLE = 'QUOTE_SINGLE';
+ type Type = BLOCK_FOLDED | BLOCK_LITERAL | PLAIN | QUOTE_DOUBLE | QUOTE_SINGLE;
+}
+export declare class Scalar<T = unknown> extends NodeBase {
+ static readonly BLOCK_FOLDED = "BLOCK_FOLDED";
+ static readonly BLOCK_LITERAL = "BLOCK_LITERAL";
+ static readonly PLAIN = "PLAIN";
+ static readonly QUOTE_DOUBLE = "QUOTE_DOUBLE";
+ static readonly QUOTE_SINGLE = "QUOTE_SINGLE";
+ value: T;
+ /** An optional anchor on this node. Used by alias nodes. */
+ anchor?: string;
+ /**
+ * By default (undefined), numbers use decimal notation.
+ * The YAML 1.2 core schema only supports 'HEX' and 'OCT'.
+ * The YAML 1.1 schema also supports 'BIN' and 'TIME'
+ */
+ format?: string;
+ /** If `value` is a number, use this value when stringifying this node. */
+ minFractionDigits?: number;
+ /** Set during parsing to the source string value */
+ source?: string;
+ /** The scalar style used for the node's string representation */
+ type?: Scalar.Type;
+ constructor(value: T);
+ toJSON(arg?: any, ctx?: ToJSContext): any;
+ toString(): string;
+}
diff --git a/MistyCore/node_modules/yaml/dist/nodes/Scalar.js b/MistyCore/node_modules/yaml/dist/nodes/Scalar.js
new file mode 100644
index 0000000..2552913
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/Scalar.js
@@ -0,0 +1,26 @@
+'use strict';
+
+var Node = require('./Node.js');
+var toJS = require('./toJS.js');
+
+const isScalarValue = (value) => !value || (typeof value !== 'function' && typeof value !== 'object');
+class Scalar extends Node.NodeBase {
+ constructor(value) {
+ super(Node.SCALAR);
+ this.value = value;
+ }
+ toJSON(arg, ctx) {
+ return ctx?.keep ? this.value : toJS.toJS(this.value, arg, ctx);
+ }
+ toString() {
+ return String(this.value);
+ }
+}
+Scalar.BLOCK_FOLDED = 'BLOCK_FOLDED';
+Scalar.BLOCK_LITERAL = 'BLOCK_LITERAL';
+Scalar.PLAIN = 'PLAIN';
+Scalar.QUOTE_DOUBLE = 'QUOTE_DOUBLE';
+Scalar.QUOTE_SINGLE = 'QUOTE_SINGLE';
+
+exports.Scalar = Scalar;
+exports.isScalarValue = isScalarValue;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/YAMLMap.d.ts b/MistyCore/node_modules/yaml/dist/nodes/YAMLMap.d.ts
new file mode 100644
index 0000000..574f271
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/YAMLMap.d.ts
@@ -0,0 +1,47 @@
+import type { BlockMap, FlowCollection } from '../parse/cst.js';
+import type { Schema } from '../schema/Schema.js';
+import type { StringifyContext } from '../stringify/stringify.js';
+import { Collection } from './Collection.js';
+import { ParsedNode, Range } from './Node.js';
+import { Pair } from './Pair.js';
+import { Scalar } from './Scalar.js';
+import type { ToJSContext } from './toJS.js';
+export declare type MapLike = Map<unknown, unknown> | Set<unknown> | Record<string | number | symbol, unknown>;
+export declare function findPair<K = unknown, V = unknown>(items: Iterable<Pair<K, V>>, key: unknown): Pair<K, V> | undefined;
+export declare namespace YAMLMap {
+ interface Parsed<K extends ParsedNode = ParsedNode, V extends ParsedNode | null = ParsedNode | null> extends YAMLMap<K, V> {
+ items: Pair<K, V>[];
+ range: Range;
+ srcToken?: BlockMap | FlowCollection;
+ }
+}
+export declare class YAMLMap<K = unknown, V = unknown> extends Collection {
+ static get tagName(): 'tag:yaml.org,2002:map';
+ items: Pair<K, V>[];
+ constructor(schema?: Schema);
+ /**
+ * Adds a value to the collection.
+ *
+ * @param overwrite - If not set `true`, using a key that is already in the
+ * collection will throw. Otherwise, overwrites the previous value.
+ */
+ add(pair: Pair<K, V> | {
+ key: K;
+ value: V;
+ }, overwrite?: boolean): void;
+ delete(key: unknown): boolean;
+ get(key: unknown, keepScalar: true): Scalar<V> | undefined;
+ get(key: unknown, keepScalar?: false): V | undefined;
+ get(key: unknown, keepScalar?: boolean): V | Scalar<V> | undefined;
+ has(key: unknown): boolean;
+ set(key: K, value: V): void;
+ /**
+ * @param ctx - Conversion context, originally set in Document#toJS()
+ * @param {Class} Type - If set, forces the returned collection type
+ * @returns Instance of Type, Map, or Object
+ */
+ toJSON<T extends MapLike = Map<unknown, unknown>>(_?: unknown, ctx?: ToJSContext, Type?: {
+ new (): T;
+ }): any;
+ toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
+}
diff --git a/MistyCore/node_modules/yaml/dist/nodes/YAMLMap.js b/MistyCore/node_modules/yaml/dist/nodes/YAMLMap.js
new file mode 100644
index 0000000..122274c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/YAMLMap.js
@@ -0,0 +1,119 @@
+'use strict';
+
+var stringifyCollection = require('../stringify/stringifyCollection.js');
+var addPairToJSMap = require('./addPairToJSMap.js');
+var Collection = require('./Collection.js');
+var Node = require('./Node.js');
+var Pair = require('./Pair.js');
+var Scalar = require('./Scalar.js');
+
+function findPair(items, key) {
+ const k = Node.isScalar(key) ? key.value : key;
+ for (const it of items) {
+ if (Node.isPair(it)) {
+ if (it.key === key || it.key === k)
+ return it;
+ if (Node.isScalar(it.key) && it.key.value === k)
+ return it;
+ }
+ }
+ return undefined;
+}
+class YAMLMap extends Collection.Collection {
+ constructor(schema) {
+ super(Node.MAP, schema);
+ this.items = [];
+ }
+ static get tagName() {
+ return 'tag:yaml.org,2002:map';
+ }
+ /**
+ * Adds a value to the collection.
+ *
+ * @param overwrite - If not set `true`, using a key that is already in the
+ * collection will throw. Otherwise, overwrites the previous value.
+ */
+ add(pair, overwrite) {
+ let _pair;
+ if (Node.isPair(pair))
+ _pair = pair;
+ else if (!pair || typeof pair !== 'object' || !('key' in pair)) {
+ // In TypeScript, this never happens.
+ _pair = new Pair.Pair(pair, pair?.value);
+ }
+ else
+ _pair = new Pair.Pair(pair.key, pair.value);
+ const prev = findPair(this.items, _pair.key);
+ const sortEntries = this.schema?.sortMapEntries;
+ if (prev) {
+ if (!overwrite)
+ throw new Error(`Key ${_pair.key} already set`);
+ // For scalars, keep the old node & its comments and anchors
+ if (Node.isScalar(prev.value) && Scalar.isScalarValue(_pair.value))
+ prev.value.value = _pair.value;
+ else
+ prev.value = _pair.value;
+ }
+ else if (sortEntries) {
+ const i = this.items.findIndex(item => sortEntries(_pair, item) < 0);
+ if (i === -1)
+ this.items.push(_pair);
+ else
+ this.items.splice(i, 0, _pair);
+ }
+ else {
+ this.items.push(_pair);
+ }
+ }
+ delete(key) {
+ const it = findPair(this.items, key);
+ if (!it)
+ return false;
+ const del = this.items.splice(this.items.indexOf(it), 1);
+ return del.length > 0;
+ }
+ get(key, keepScalar) {
+ const it = findPair(this.items, key);
+ const node = it?.value;
+ return (!keepScalar && Node.isScalar(node) ? node.value : node) ?? undefined;
+ }
+ has(key) {
+ return !!findPair(this.items, key);
+ }
+ set(key, value) {
+ this.add(new Pair.Pair(key, value), true);
+ }
+ /**
+ * @param ctx - Conversion context, originally set in Document#toJS()
+ * @param {Class} Type - If set, forces the returned collection type
+ * @returns Instance of Type, Map, or Object
+ */
+ toJSON(_, ctx, Type) {
+ const map = Type ? new Type() : ctx?.mapAsMap ? new Map() : {};
+ if (ctx?.onCreate)
+ ctx.onCreate(map);
+ for (const item of this.items)
+ addPairToJSMap.addPairToJSMap(ctx, map, item);
+ return map;
+ }
+ toString(ctx, onComment, onChompKeep) {
+ if (!ctx)
+ return JSON.stringify(this);
+ for (const item of this.items) {
+ if (!Node.isPair(item))
+ throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`);
+ }
+ if (!ctx.allNullValues && this.hasAllNullValues(false))
+ ctx = Object.assign({}, ctx, { allNullValues: true });
+ return stringifyCollection.stringifyCollection(this, ctx, {
+ blockItemPrefix: '',
+ flowChars: { start: '{', end: '}' },
+ itemIndent: ctx.indent || '',
+ onChompKeep,
+ onComment
+ });
+ }
+}
+
+exports.YAMLMap = YAMLMap;
+exports.findPair = findPair;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/YAMLSeq.d.ts b/MistyCore/node_modules/yaml/dist/nodes/YAMLSeq.d.ts
new file mode 100644
index 0000000..df50233
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/YAMLSeq.d.ts
@@ -0,0 +1,58 @@
+import type { BlockSequence, FlowCollection } from '../parse/cst.js';
+import type { Schema } from '../schema/Schema.js';
+import type { StringifyContext } from '../stringify/stringify.js';
+import { Collection } from './Collection.js';
+import { ParsedNode, Range } from './Node.js';
+import type { Pair } from './Pair.js';
+import { Scalar } from './Scalar.js';
+import { ToJSContext } from './toJS.js';
+export declare namespace YAMLSeq {
+ interface Parsed<T extends ParsedNode | Pair<ParsedNode, ParsedNode | null> = ParsedNode> extends YAMLSeq<T> {
+ items: T[];
+ range: Range;
+ srcToken?: BlockSequence | FlowCollection;
+ }
+}
+export declare class YAMLSeq<T = unknown> extends Collection {
+ static get tagName(): 'tag:yaml.org,2002:seq';
+ items: T[];
+ constructor(schema?: Schema);
+ add(value: T): void;
+ /**
+ * Removes a value from the collection.
+ *
+ * `key` must contain a representation of an integer for this to succeed.
+ * It may be wrapped in a `Scalar`.
+ *
+ * @returns `true` if the item was found and removed.
+ */
+ delete(key: unknown): boolean;
+ /**
+ * Returns item at `key`, or `undefined` if not found. By default unwraps
+ * scalar values from their surrounding node; to disable set `keepScalar` to
+ * `true` (collections are always returned intact).
+ *
+ * `key` must contain a representation of an integer for this to succeed.
+ * It may be wrapped in a `Scalar`.
+ */
+ get(key: unknown, keepScalar: true): Scalar<T> | undefined;
+ get(key: unknown, keepScalar?: false): T | undefined;
+ get(key: unknown, keepScalar?: boolean): T | Scalar<T> | undefined;
+ /**
+ * Checks if the collection includes a value with the key `key`.
+ *
+ * `key` must contain a representation of an integer for this to succeed.
+ * It may be wrapped in a `Scalar`.
+ */
+ has(key: unknown): boolean;
+ /**
+ * Sets a value in this collection. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ *
+ * If `key` does not contain a representation of an integer, this will throw.
+ * It may be wrapped in a `Scalar`.
+ */
+ set(key: unknown, value: T): void;
+ toJSON(_?: unknown, ctx?: ToJSContext): unknown[];
+ toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
+}
diff --git a/MistyCore/node_modules/yaml/dist/nodes/YAMLSeq.js b/MistyCore/node_modules/yaml/dist/nodes/YAMLSeq.js
new file mode 100644
index 0000000..6b446c6
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/YAMLSeq.js
@@ -0,0 +1,99 @@
+'use strict';
+
+var stringifyCollection = require('../stringify/stringifyCollection.js');
+var Collection = require('./Collection.js');
+var Node = require('./Node.js');
+var Scalar = require('./Scalar.js');
+var toJS = require('./toJS.js');
+
+class YAMLSeq extends Collection.Collection {
+ constructor(schema) {
+ super(Node.SEQ, schema);
+ this.items = [];
+ }
+ static get tagName() {
+ return 'tag:yaml.org,2002:seq';
+ }
+ add(value) {
+ this.items.push(value);
+ }
+ /**
+ * Removes a value from the collection.
+ *
+ * `key` must contain a representation of an integer for this to succeed.
+ * It may be wrapped in a `Scalar`.
+ *
+ * @returns `true` if the item was found and removed.
+ */
+ delete(key) {
+ const idx = asItemIndex(key);
+ if (typeof idx !== 'number')
+ return false;
+ const del = this.items.splice(idx, 1);
+ return del.length > 0;
+ }
+ get(key, keepScalar) {
+ const idx = asItemIndex(key);
+ if (typeof idx !== 'number')
+ return undefined;
+ const it = this.items[idx];
+ return !keepScalar && Node.isScalar(it) ? it.value : it;
+ }
+ /**
+ * Checks if the collection includes a value with the key `key`.
+ *
+ * `key` must contain a representation of an integer for this to succeed.
+ * It may be wrapped in a `Scalar`.
+ */
+ has(key) {
+ const idx = asItemIndex(key);
+ return typeof idx === 'number' && idx < this.items.length;
+ }
+ /**
+ * Sets a value in this collection. For `!!set`, `value` needs to be a
+ * boolean to add/remove the item from the set.
+ *
+ * If `key` does not contain a representation of an integer, this will throw.
+ * It may be wrapped in a `Scalar`.
+ */
+ set(key, value) {
+ const idx = asItemIndex(key);
+ if (typeof idx !== 'number')
+ throw new Error(`Expected a valid index, not ${key}.`);
+ const prev = this.items[idx];
+ if (Node.isScalar(prev) && Scalar.isScalarValue(value))
+ prev.value = value;
+ else
+ this.items[idx] = value;
+ }
+ toJSON(_, ctx) {
+ const seq = [];
+ if (ctx?.onCreate)
+ ctx.onCreate(seq);
+ let i = 0;
+ for (const item of this.items)
+ seq.push(toJS.toJS(item, String(i++), ctx));
+ return seq;
+ }
+ toString(ctx, onComment, onChompKeep) {
+ if (!ctx)
+ return JSON.stringify(this);
+ return stringifyCollection.stringifyCollection(this, ctx, {
+ blockItemPrefix: '- ',
+ flowChars: { start: '[', end: ']' },
+ itemIndent: (ctx.indent || '') + ' ',
+ onChompKeep,
+ onComment
+ });
+ }
+}
+function asItemIndex(key) {
+ let idx = Node.isScalar(key) ? key.value : key;
+ if (idx && typeof idx === 'string')
+ idx = Number(idx);
+ return typeof idx === 'number' && Number.isInteger(idx) && idx >= 0
+ ? idx
+ : null;
+}
+
+exports.YAMLSeq = YAMLSeq;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts b/MistyCore/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts
new file mode 100644
index 0000000..70d9e62
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts
@@ -0,0 +1,4 @@
+import type { Pair } from './Pair.js';
+import { ToJSContext } from './toJS.js';
+import type { MapLike } from './YAMLMap.js';
+export declare function addPairToJSMap(ctx: ToJSContext | undefined, map: MapLike, { key, value }: Pair): MapLike;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/addPairToJSMap.js b/MistyCore/node_modules/yaml/dist/nodes/addPairToJSMap.js
new file mode 100644
index 0000000..2d3ab5c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/addPairToJSMap.js
@@ -0,0 +1,106 @@
+'use strict';
+
+var log = require('../log.js');
+var stringify = require('../stringify/stringify.js');
+var Node = require('./Node.js');
+var Scalar = require('./Scalar.js');
+var toJS = require('./toJS.js');
+
+const MERGE_KEY = '<<';
+function addPairToJSMap(ctx, map, { key, value }) {
+ if (ctx?.doc.schema.merge && isMergeKey(key)) {
+ value = Node.isAlias(value) ? value.resolve(ctx.doc) : value;
+ if (Node.isSeq(value))
+ for (const it of value.items)
+ mergeToJSMap(ctx, map, it);
+ else if (Array.isArray(value))
+ for (const it of value)
+ mergeToJSMap(ctx, map, it);
+ else
+ mergeToJSMap(ctx, map, value);
+ }
+ else {
+ const jsKey = toJS.toJS(key, '', ctx);
+ if (map instanceof Map) {
+ map.set(jsKey, toJS.toJS(value, jsKey, ctx));
+ }
+ else if (map instanceof Set) {
+ map.add(jsKey);
+ }
+ else {
+ const stringKey = stringifyKey(key, jsKey, ctx);
+ const jsValue = toJS.toJS(value, stringKey, ctx);
+ if (stringKey in map)
+ Object.defineProperty(map, stringKey, {
+ value: jsValue,
+ writable: true,
+ enumerable: true,
+ configurable: true
+ });
+ else
+ map[stringKey] = jsValue;
+ }
+ }
+ return map;
+}
+const isMergeKey = (key) => key === MERGE_KEY ||
+ (Node.isScalar(key) &&
+ key.value === MERGE_KEY &&
+ (!key.type || key.type === Scalar.Scalar.PLAIN));
+// If the value associated with a merge key is a single mapping node, each of
+// its key/value pairs is inserted into the current mapping, unless the key
+// already exists in it. If the value associated with the merge key is a
+// sequence, then this sequence is expected to contain mapping nodes and each
+// of these nodes is merged in turn according to its order in the sequence.
+// Keys in mapping nodes earlier in the sequence override keys specified in
+// later mapping nodes. -- http://yaml.org/type/merge.html
+function mergeToJSMap(ctx, map, value) {
+ const source = ctx && Node.isAlias(value) ? value.resolve(ctx.doc) : value;
+ if (!Node.isMap(source))
+ throw new Error('Merge sources must be maps or map aliases');
+ const srcMap = source.toJSON(null, ctx, Map);
+ for (const [key, value] of srcMap) {
+ if (map instanceof Map) {
+ if (!map.has(key))
+ map.set(key, value);
+ }
+ else if (map instanceof Set) {
+ map.add(key);
+ }
+ else if (!Object.prototype.hasOwnProperty.call(map, key)) {
+ Object.defineProperty(map, key, {
+ value,
+ writable: true,
+ enumerable: true,
+ configurable: true
+ });
+ }
+ }
+ return map;
+}
+function stringifyKey(key, jsKey, ctx) {
+ if (jsKey === null)
+ return '';
+ if (typeof jsKey !== 'object')
+ return String(jsKey);
+ if (Node.isNode(key) && ctx && ctx.doc) {
+ const strCtx = stringify.createStringifyContext(ctx.doc, {});
+ strCtx.anchors = new Set();
+ for (const node of ctx.anchors.keys())
+ strCtx.anchors.add(node.anchor);
+ strCtx.inFlow = true;
+ strCtx.inStringifyKey = true;
+ const strKey = key.toString(strCtx);
+ if (!ctx.mapKeyWarned) {
+ let jsonStr = JSON.stringify(strKey);
+ if (jsonStr.length > 40)
+ jsonStr = jsonStr.substring(0, 36) + '..."';
+ log.warn(ctx.doc.options.logLevel, `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use object keys.`);
+ ctx.mapKeyWarned = true;
+ }
+ return strKey;
+ }
+ return JSON.stringify(jsKey);
+}
+
+exports.addPairToJSMap = addPairToJSMap;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/toJS.d.ts b/MistyCore/node_modules/yaml/dist/nodes/toJS.d.ts
new file mode 100644
index 0000000..85d794d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/toJS.d.ts
@@ -0,0 +1,30 @@
+import type { Document } from '../doc/Document.js';
+import type { stringify } from '../stringify/stringify.js';
+import { Node } from './Node.js';
+export interface AnchorData {
+ aliasCount: number;
+ count: number;
+ res: unknown;
+}
+export interface ToJSContext {
+ anchors: Map<Node, AnchorData>;
+ doc: Document;
+ keep: boolean;
+ mapAsMap: boolean;
+ mapKeyWarned: boolean;
+ maxAliasCount: number;
+ onCreate?: (res: unknown) => void;
+ /** Requiring this directly in Pair would create circular dependencies */
+ stringify: typeof stringify;
+}
+/**
+ * Recursively convert any node or its contents to native JavaScript
+ *
+ * @param value - The input value
+ * @param arg - If `value` defines a `toJSON()` method, use this
+ * as its first argument
+ * @param ctx - Conversion context, originally set in Document#toJS(). If
+ * `{ keep: true }` is not set, output should be suitable for JSON
+ * stringification.
+ */
+export declare function toJS(value: any, arg: string | null, ctx?: ToJSContext): any;
diff --git a/MistyCore/node_modules/yaml/dist/nodes/toJS.js b/MistyCore/node_modules/yaml/dist/nodes/toJS.js
new file mode 100644
index 0000000..e7404d5
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/nodes/toJS.js
@@ -0,0 +1,39 @@
+'use strict';
+
+var Node = require('./Node.js');
+
+/**
+ * Recursively convert any node or its contents to native JavaScript
+ *
+ * @param value - The input value
+ * @param arg - If `value` defines a `toJSON()` method, use this
+ * as its first argument
+ * @param ctx - Conversion context, originally set in Document#toJS(). If
+ * `{ keep: true }` is not set, output should be suitable for JSON
+ * stringification.
+ */
+function toJS(value, arg, ctx) {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ if (Array.isArray(value))
+ return value.map((v, i) => toJS(v, String(i), ctx));
+ if (value && typeof value.toJSON === 'function') {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+ if (!ctx || !Node.hasAnchor(value))
+ return value.toJSON(arg, ctx);
+ const data = { aliasCount: 0, count: 1, res: undefined };
+ ctx.anchors.set(value, data);
+ ctx.onCreate = res => {
+ data.res = res;
+ delete ctx.onCreate;
+ };
+ const res = value.toJSON(arg, ctx);
+ if (ctx.onCreate)
+ ctx.onCreate(res);
+ return res;
+ }
+ if (typeof value === 'bigint' && !ctx?.keep)
+ return Number(value);
+ return value;
+}
+
+exports.toJS = toJS;
diff --git a/MistyCore/node_modules/yaml/dist/options.d.ts b/MistyCore/node_modules/yaml/dist/options.d.ts
new file mode 100644
index 0000000..06e1b6d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/options.d.ts
@@ -0,0 +1,331 @@
+import type { Reviver } from './doc/applyReviver.js';
+import type { Directives } from './doc/directives.js';
+import type { LogLevelId } from './log.js';
+import type { ParsedNode } from './nodes/Node.js';
+import type { Pair } from './nodes/Pair.js';
+import type { Scalar } from './nodes/Scalar.js';
+import type { LineCounter } from './parse/line-counter.js';
+import type { Schema } from './schema/Schema.js';
+import type { Tags } from './schema/tags.js';
+import type { CollectionTag, ScalarTag } from './schema/types.js';
+export declare type ParseOptions = {
+ /**
+ * Whether integers should be parsed into BigInt rather than number values.
+ *
+ * Default: `false`
+ *
+ * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/BigInt
+ */
+ intAsBigInt?: boolean;
+ /**
+ * Include a `srcToken` value on each parsed `Node`, containing the CST token
+ * that was composed into this node.
+ *
+ * Default: `false`
+ */
+ keepSourceTokens?: boolean;
+ /**
+ * If set, newlines will be tracked, to allow for `lineCounter.linePos(offset)`
+ * to provide the `{ line, col }` positions within the input.
+ */
+ lineCounter?: LineCounter;
+ /**
+ * Include line/col position & node type directly in parse errors.
+ *
+ * Default: `true`
+ */
+ prettyErrors?: boolean;
+ /**
+ * Detect and report errors that are required by the YAML 1.2 spec,
+ * but are caused by unambiguous content.
+ *
+ * Default: `true`
+ */
+ strict?: boolean;
+ /**
+ * YAML requires map keys to be unique. By default, this is checked by
+ * comparing scalar values with `===`; deep equality is not checked for
+ * aliases or collections. If merge keys are enabled by the schema,
+ * multiple `<<` keys are allowed.
+ *
+ * Set `false` to disable, or provide your own comparator function to
+ * customise. The comparator will be passed two `ParsedNode` values, and
+ * is expected to return a `boolean` indicating their equality.
+ *
+ * Default: `true`
+ */
+ uniqueKeys?: boolean | ((a: ParsedNode, b: ParsedNode) => boolean);
+};
+export declare type DocumentOptions = {
+ /**
+ * @internal
+ * Used internally by Composer. If set and includes an explicit version,
+ * that overrides the `version` option.
+ */
+ _directives?: Directives;
+ /**
+ * Control the logging level during parsing
+ *
+ * Default: `'warn'`
+ */
+ logLevel?: LogLevelId;
+ /**
+ * The YAML version used by documents without a `%YAML` directive.
+ *
+ * Default: `"1.2"`
+ */
+ version?: '1.1' | '1.2' | 'next';
+};
+export declare type SchemaOptions = {
+ /**
+ * When parsing, warn about compatibility issues with the given schema.
+ * When stringifying, use scalar styles that are parsed correctly
+ * by the `compat` schema as well as the actual schema.
+ *
+ * Default: `null`
+ */
+ compat?: string | Tags | null;
+ /**
+ * Array of additional tags to include in the schema, or a function that may
+ * modify the schema's base tag array.
+ */
+ customTags?: Tags | ((tags: Tags) => Tags) | null;
+ /**
+ * Enable support for `<<` merge keys.
+ *
+ * Default: `false` for YAML 1.2, `true` for earlier versions
+ */
+ merge?: boolean;
+ /**
+ * When using the `'core'` schema, support parsing values with these
+ * explicit YAML 1.1 tags:
+ *
+ * `!!binary`, `!!omap`, `!!pairs`, `!!set`, `!!timestamp`.
+ *
+ * Default `true`
+ */
+ resolveKnownTags?: boolean;
+ /**
+ * The base schema to use.
+ *
+ * The core library has built-in support for the following:
+ * - `'failsafe'`: A minimal schema that parses all scalars as strings
+ * - `'core'`: The YAML 1.2 core schema
+ * - `'json'`: The YAML 1.2 JSON schema, with minimal rules for JSON compatibility
+ * - `'yaml-1.1'`: The YAML 1.1 schema
+ *
+ * If using another (custom) schema, the `customTags` array needs to
+ * fully define the schema's tags.
+ *
+ * Default: `'core'` for YAML 1.2, `'yaml-1.1'` for earlier versions
+ */
+ schema?: string | Schema;
+ /**
+ * When adding to or stringifying a map, sort the entries.
+ * If `true`, sort by comparing key values with `<`.
+ * Does not affect item order when parsing.
+ *
+ * Default: `false`
+ */
+ sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
+ /**
+ * Override default values for `toString()` options.
+ */
+ toStringDefaults?: ToStringOptions;
+};
+export declare type CreateNodeOptions = {
+ /**
+ * During node construction, use anchors and aliases to keep strictly equal
+ * non-null objects as equivalent in YAML.
+ *
+ * Default: `true`
+ */
+ aliasDuplicateObjects?: boolean;
+ /**
+ * Default prefix for anchors.
+ *
+ * Default: `'a'`, resulting in anchors `a1`, `a2`, etc.
+ */
+ anchorPrefix?: string;
+ /** Force the top-level collection node to use flow style. */
+ flow?: boolean;
+ /**
+ * Keep `undefined` object values when creating mappings, rather than
+ * discarding them.
+ *
+ * Default: `false`
+ */
+ keepUndefined?: boolean | null;
+ onTagObj?: (tagObj: ScalarTag | CollectionTag) => void;
+ /**
+ * Specify the top-level collection type, e.g. `"!!omap"`. Note that this
+ * requires the corresponding tag to be available in this document's schema.
+ */
+ tag?: string;
+};
+export declare type ToJSOptions = {
+ /**
+ * Use Map rather than Object to represent mappings.
+ *
+ * Default: `false`
+ */
+ mapAsMap?: boolean;
+ /**
+ * Prevent exponential entity expansion attacks by limiting data aliasing count;
+ * set to `-1` to disable checks; `0` disallows all alias nodes.
+ *
+ * Default: `100`
+ */
+ maxAliasCount?: number;
+ /**
+ * If defined, called with the resolved `value` and reference `count` for
+ * each anchor in the document.
+ */
+ onAnchor?: (value: unknown, count: number) => void;
+ /**
+ * Optional function that may filter or modify the output JS value
+ *
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#using_the_reviver_parameter
+ */
+ reviver?: Reviver;
+};
+export declare type ToStringOptions = {
+ /**
+ * Use block quote styles for scalar values where applicable.
+ * Set to `false` to disable block quotes completely.
+ *
+ * Default: `true`
+ */
+ blockQuote?: boolean | 'folded' | 'literal';
+ /**
+ * Enforce `'block'` or `'flow'` style on maps and sequences.
+ * Empty collections will always be stringified as `{}` or `[]`.
+ *
+ * Default: `'any'`, allowing each node to set its style separately
+ * with its `flow: boolean` (default `false`) property.
+ */
+ collectionStyle?: 'any' | 'block' | 'flow';
+ /**
+ * Comment stringifier.
+ * Output should be valid for the current schema.
+ *
+ * By default, empty comment lines are left empty,
+ * lines consisting of a single space are replaced by `#`,
+ * and all other lines are prefixed with a `#`.
+ */
+ commentString?: (comment: string) => string;
+ /**
+ * The default type of string literal used to stringify implicit key values.
+ * Output may use other types if required to fully represent the value.
+ *
+ * If `null`, the value of `defaultStringType` is used.
+ *
+ * Default: `null`
+ */
+ defaultKeyType?: Scalar.Type | null;
+ /**
+ * The default type of string literal used to stringify values in general.
+ * Output may use other types if required to fully represent the value.
+ *
+ * Default: `'PLAIN'`
+ */
+ defaultStringType?: Scalar.Type;
+ /**
+ * Include directives in the output.
+ *
+ * - If `true`, at least the document-start marker `---` is always included.
+ * This does not force the `%YAML` directive to be included. To do that,
+ * set `doc.directives.yaml.explicit = true`.
+ * - If `false`, no directives or marker is ever included. If using the `%TAG`
+ * directive, you are expected to include it manually in the stream before
+ * its use.
+ * - If `null`, directives and marker may be included if required.
+ *
+ * Default: `null`
+ */
+ directives?: boolean | null;
+ /**
+ * Restrict double-quoted strings to use JSON-compatible syntax.
+ *
+ * Default: `false`
+ */
+ doubleQuotedAsJSON?: boolean;
+ /**
+ * Minimum length for double-quoted strings to use multiple lines to
+ * represent the value. Ignored if `doubleQuotedAsJSON` is set.
+ *
+ * Default: `40`
+ */
+ doubleQuotedMinMultiLineLength?: number;
+ /**
+ * String representation for `false`.
+ * With the core schema, use `'false'`, `'False'`, or `'FALSE'`.
+ *
+ * Default: `'false'`
+ */
+ falseStr?: string;
+ /**
+ * The number of spaces to use when indenting code.
+ *
+ * Default: `2`
+ */
+ indent?: number;
+ /**
+ * Whether block sequences should be indented.
+ *
+ * Default: `true`
+ */
+ indentSeq?: boolean;
+ /**
+ * Maximum line width (set to `0` to disable folding).
+ *
+ * This is a soft limit, as only double-quoted semantics allow for inserting
+ * a line break in the middle of a word, as well as being influenced by the
+ * `minContentWidth` option.
+ *
+ * Default: `80`
+ */
+ lineWidth?: number;
+ /**
+ * Minimum line width for highly-indented content (set to `0` to disable).
+ *
+ * Default: `20`
+ */
+ minContentWidth?: number;
+ /**
+ * String representation for `null`.
+ * With the core schema, use `'null'`, `'Null'`, `'NULL'`, `'~'`, or an empty
+ * string `''`.
+ *
+ * Default: `'null'`
+ */
+ nullStr?: string;
+ /**
+ * Require keys to be scalars and to use implicit rather than explicit notation.
+ *
+ * Default: `false`
+ */
+ simpleKeys?: boolean;
+ /**
+ * Use 'single quote' rather than "double quote" where applicable.
+ * Set to `false` to disable single quotes completely.
+ *
+ * Default: `null`
+ */
+ singleQuote?: boolean | null;
+ /**
+ * String representation for `true`.
+ * With the core schema, use `'true'`, `'True'`, or `'TRUE'`.
+ *
+ * Default: `'true'`
+ */
+ trueStr?: string;
+ /**
+ * The anchor used by an alias must be defined before the alias node. As it's
+ * possible for the document to be modified manually, the order may be
+ * verified during stringification.
+ *
+ * Default: `'true'`
+ */
+ verifyAliasOrder?: boolean;
+};
diff --git a/MistyCore/node_modules/yaml/dist/parse/cst-scalar.d.ts b/MistyCore/node_modules/yaml/dist/parse/cst-scalar.d.ts
new file mode 100644
index 0000000..a7bd1d6
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/cst-scalar.d.ts
@@ -0,0 +1,64 @@
+import { ErrorCode } from '../errors.js';
+import { Range } from '../nodes/Node.js';
+import type { Scalar } from '../nodes/Scalar.js';
+import type { BlockScalar, FlowScalar, SourceToken, Token } from './cst.js';
+/**
+ * If `token` is a CST flow or block scalar, determine its string value and a few other attributes.
+ * Otherwise, return `null`.
+ */
+export declare function resolveAsScalar(token: FlowScalar | BlockScalar, strict?: boolean, onError?: (offset: number, code: ErrorCode, message: string) => void): {
+ value: string;
+ type: Scalar.Type | null;
+ comment: string;
+ range: Range;
+};
+export declare function resolveAsScalar(token: Token | null | undefined, strict?: boolean, onError?: (offset: number, code: ErrorCode, message: string) => void): {
+ value: string;
+ type: Scalar.Type | null;
+ comment: string;
+ range: Range;
+} | null;
+/**
+ * Create a new scalar token with `value`
+ *
+ * Values that represent an actual string but may be parsed as a different type should use a `type` other than `'PLAIN'`,
+ * as this function does not support any schema operations and won't check for such conflicts.
+ *
+ * @param value The string representation of the value, which will have its content properly indented.
+ * @param context.end Comments and whitespace after the end of the value, or after the block scalar header. If undefined, a newline will be added.
+ * @param context.implicitKey Being within an implicit key may affect the resolved type of the token's value.
+ * @param context.indent The indent level of the token.
+ * @param context.inFlow Is this scalar within a flow collection? This may affect the resolved type of the token's value.
+ * @param context.offset The offset position of the token.
+ * @param context.type The preferred type of the scalar token. If undefined, the previous type of the `token` will be used, defaulting to `'PLAIN'`.
+ */
+export declare function createScalarToken(value: string, context: {
+ end?: SourceToken[];
+ implicitKey?: boolean;
+ indent: number;
+ inFlow?: boolean;
+ offset?: number;
+ type?: Scalar.Type;
+}): BlockScalar | FlowScalar;
+/**
+ * Set the value of `token` to the given string `value`, overwriting any previous contents and type that it may have.
+ *
+ * Best efforts are made to retain any comments previously associated with the `token`,
+ * though all contents within a collection's `items` will be overwritten.
+ *
+ * Values that represent an actual string but may be parsed as a different type should use a `type` other than `'PLAIN'`,
+ * as this function does not support any schema operations and won't check for such conflicts.
+ *
+ * @param token Any token. If it does not include an `indent` value, the value will be stringified as if it were an implicit key.
+ * @param value The string representation of the value, which will have its content properly indented.
+ * @param context.afterKey In most cases, values after a key should have an additional level of indentation.
+ * @param context.implicitKey Being within an implicit key may affect the resolved type of the token's value.
+ * @param context.inFlow Being within a flow collection may affect the resolved type of the token's value.
+ * @param context.type The preferred type of the scalar token. If undefined, the previous type of the `token` will be used, defaulting to `'PLAIN'`.
+ */
+export declare function setScalarValue(token: Token, value: string, context?: {
+ afterKey?: boolean;
+ implicitKey?: boolean;
+ inFlow?: boolean;
+ type?: Scalar.Type;
+}): void;
diff --git a/MistyCore/node_modules/yaml/dist/parse/cst-scalar.js b/MistyCore/node_modules/yaml/dist/parse/cst-scalar.js
new file mode 100644
index 0000000..11c5fcc
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/cst-scalar.js
@@ -0,0 +1,218 @@
+'use strict';
+
+var resolveBlockScalar = require('../compose/resolve-block-scalar.js');
+var resolveFlowScalar = require('../compose/resolve-flow-scalar.js');
+var errors = require('../errors.js');
+var stringifyString = require('../stringify/stringifyString.js');
+
+function resolveAsScalar(token, strict = true, onError) {
+ if (token) {
+ const _onError = (pos, code, message) => {
+ const offset = typeof pos === 'number' ? pos : Array.isArray(pos) ? pos[0] : pos.offset;
+ if (onError)
+ onError(offset, code, message);
+ else
+ throw new errors.YAMLParseError([offset, offset + 1], code, message);
+ };
+ switch (token.type) {
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ return resolveFlowScalar.resolveFlowScalar(token, strict, _onError);
+ case 'block-scalar':
+ return resolveBlockScalar.resolveBlockScalar(token, strict, _onError);
+ }
+ }
+ return null;
+}
+/**
+ * Create a new scalar token with `value`
+ *
+ * Values that represent an actual string but may be parsed as a different type should use a `type` other than `'PLAIN'`,
+ * as this function does not support any schema operations and won't check for such conflicts.
+ *
+ * @param value The string representation of the value, which will have its content properly indented.
+ * @param context.end Comments and whitespace after the end of the value, or after the block scalar header. If undefined, a newline will be added.
+ * @param context.implicitKey Being within an implicit key may affect the resolved type of the token's value.
+ * @param context.indent The indent level of the token.
+ * @param context.inFlow Is this scalar within a flow collection? This may affect the resolved type of the token's value.
+ * @param context.offset The offset position of the token.
+ * @param context.type The preferred type of the scalar token. If undefined, the previous type of the `token` will be used, defaulting to `'PLAIN'`.
+ */
+function createScalarToken(value, context) {
+ const { implicitKey = false, indent, inFlow = false, offset = -1, type = 'PLAIN' } = context;
+ const source = stringifyString.stringifyString({ type, value }, {
+ implicitKey,
+ indent: indent > 0 ? ' '.repeat(indent) : '',
+ inFlow,
+ options: { blockQuote: true, lineWidth: -1 }
+ });
+ const end = context.end ?? [
+ { type: 'newline', offset: -1, indent, source: '\n' }
+ ];
+ switch (source[0]) {
+ case '|':
+ case '>': {
+ const he = source.indexOf('\n');
+ const head = source.substring(0, he);
+ const body = source.substring(he + 1) + '\n';
+ const props = [
+ { type: 'block-scalar-header', offset, indent, source: head }
+ ];
+ if (!addEndtoBlockProps(props, end))
+ props.push({ type: 'newline', offset: -1, indent, source: '\n' });
+ return { type: 'block-scalar', offset, indent, props, source: body };
+ }
+ case '"':
+ return { type: 'double-quoted-scalar', offset, indent, source, end };
+ case "'":
+ return { type: 'single-quoted-scalar', offset, indent, source, end };
+ default:
+ return { type: 'scalar', offset, indent, source, end };
+ }
+}
+/**
+ * Set the value of `token` to the given string `value`, overwriting any previous contents and type that it may have.
+ *
+ * Best efforts are made to retain any comments previously associated with the `token`,
+ * though all contents within a collection's `items` will be overwritten.
+ *
+ * Values that represent an actual string but may be parsed as a different type should use a `type` other than `'PLAIN'`,
+ * as this function does not support any schema operations and won't check for such conflicts.
+ *
+ * @param token Any token. If it does not include an `indent` value, the value will be stringified as if it were an implicit key.
+ * @param value The string representation of the value, which will have its content properly indented.
+ * @param context.afterKey In most cases, values after a key should have an additional level of indentation.
+ * @param context.implicitKey Being within an implicit key may affect the resolved type of the token's value.
+ * @param context.inFlow Being within a flow collection may affect the resolved type of the token's value.
+ * @param context.type The preferred type of the scalar token. If undefined, the previous type of the `token` will be used, defaulting to `'PLAIN'`.
+ */
+function setScalarValue(token, value, context = {}) {
+ let { afterKey = false, implicitKey = false, inFlow = false, type } = context;
+ let indent = 'indent' in token ? token.indent : null;
+ if (afterKey && typeof indent === 'number')
+ indent += 2;
+ if (!type)
+ switch (token.type) {
+ case 'single-quoted-scalar':
+ type = 'QUOTE_SINGLE';
+ break;
+ case 'double-quoted-scalar':
+ type = 'QUOTE_DOUBLE';
+ break;
+ case 'block-scalar': {
+ const header = token.props[0];
+ if (header.type !== 'block-scalar-header')
+ throw new Error('Invalid block scalar header');
+ type = header.source[0] === '>' ? 'BLOCK_FOLDED' : 'BLOCK_LITERAL';
+ break;
+ }
+ default:
+ type = 'PLAIN';
+ }
+ const source = stringifyString.stringifyString({ type, value }, {
+ implicitKey: implicitKey || indent === null,
+ indent: indent !== null && indent > 0 ? ' '.repeat(indent) : '',
+ inFlow,
+ options: { blockQuote: true, lineWidth: -1 }
+ });
+ switch (source[0]) {
+ case '|':
+ case '>':
+ setBlockScalarValue(token, source);
+ break;
+ case '"':
+ setFlowScalarValue(token, source, 'double-quoted-scalar');
+ break;
+ case "'":
+ setFlowScalarValue(token, source, 'single-quoted-scalar');
+ break;
+ default:
+ setFlowScalarValue(token, source, 'scalar');
+ }
+}
+function setBlockScalarValue(token, source) {
+ const he = source.indexOf('\n');
+ const head = source.substring(0, he);
+ const body = source.substring(he + 1) + '\n';
+ if (token.type === 'block-scalar') {
+ const header = token.props[0];
+ if (header.type !== 'block-scalar-header')
+ throw new Error('Invalid block scalar header');
+ header.source = head;
+ token.source = body;
+ }
+ else {
+ const { offset } = token;
+ const indent = 'indent' in token ? token.indent : -1;
+ const props = [
+ { type: 'block-scalar-header', offset, indent, source: head }
+ ];
+ if (!addEndtoBlockProps(props, 'end' in token ? token.end : undefined))
+ props.push({ type: 'newline', offset: -1, indent, source: '\n' });
+ for (const key of Object.keys(token))
+ if (key !== 'type' && key !== 'offset')
+ delete token[key];
+ Object.assign(token, { type: 'block-scalar', indent, props, source: body });
+ }
+}
+/** @returns `true` if last token is a newline */
+function addEndtoBlockProps(props, end) {
+ if (end)
+ for (const st of end)
+ switch (st.type) {
+ case 'space':
+ case 'comment':
+ props.push(st);
+ break;
+ case 'newline':
+ props.push(st);
+ return true;
+ }
+ return false;
+}
+function setFlowScalarValue(token, source, type) {
+ switch (token.type) {
+ case 'scalar':
+ case 'double-quoted-scalar':
+ case 'single-quoted-scalar':
+ token.type = type;
+ token.source = source;
+ break;
+ case 'block-scalar': {
+ const end = token.props.slice(1);
+ let oa = source.length;
+ if (token.props[0].type === 'block-scalar-header')
+ oa -= token.props[0].source.length;
+ for (const tok of end)
+ tok.offset += oa;
+ delete token.props;
+ Object.assign(token, { type, source, end });
+ break;
+ }
+ case 'block-map':
+ case 'block-seq': {
+ const offset = token.offset + source.length;
+ const nl = { type: 'newline', offset, indent: token.indent, source: '\n' };
+ delete token.items;
+ Object.assign(token, { type, source, end: [nl] });
+ break;
+ }
+ default: {
+ const indent = 'indent' in token ? token.indent : -1;
+ const end = 'end' in token && Array.isArray(token.end)
+ ? token.end.filter(st => st.type === 'space' ||
+ st.type === 'comment' ||
+ st.type === 'newline')
+ : [];
+ for (const key of Object.keys(token))
+ if (key !== 'type' && key !== 'offset')
+ delete token[key];
+ Object.assign(token, { type, indent, source, end });
+ }
+ }
+}
+
+exports.createScalarToken = createScalarToken;
+exports.resolveAsScalar = resolveAsScalar;
+exports.setScalarValue = setScalarValue;
diff --git a/MistyCore/node_modules/yaml/dist/parse/cst-stringify.d.ts b/MistyCore/node_modules/yaml/dist/parse/cst-stringify.d.ts
new file mode 100644
index 0000000..dbf66d6
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/cst-stringify.d.ts
@@ -0,0 +1,8 @@
+import type { CollectionItem, Token } from './cst.js';
+/**
+ * Stringify a CST document, token, or collection item
+ *
+ * Fair warning: This applies no validation whatsoever, and
+ * simply concatenates the sources in their logical order.
+ */
+export declare const stringify: (cst: Token | CollectionItem) => string;
diff --git a/MistyCore/node_modules/yaml/dist/parse/cst-stringify.js b/MistyCore/node_modules/yaml/dist/parse/cst-stringify.js
new file mode 100644
index 0000000..78e8c37
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/cst-stringify.js
@@ -0,0 +1,63 @@
+'use strict';
+
+/**
+ * Stringify a CST document, token, or collection item
+ *
+ * Fair warning: This applies no validation whatsoever, and
+ * simply concatenates the sources in their logical order.
+ */
+const stringify = (cst) => 'type' in cst ? stringifyToken(cst) : stringifyItem(cst);
+function stringifyToken(token) {
+ switch (token.type) {
+ case 'block-scalar': {
+ let res = '';
+ for (const tok of token.props)
+ res += stringifyToken(tok);
+ return res + token.source;
+ }
+ case 'block-map':
+ case 'block-seq': {
+ let res = '';
+ for (const item of token.items)
+ res += stringifyItem(item);
+ return res;
+ }
+ case 'flow-collection': {
+ let res = token.start.source;
+ for (const item of token.items)
+ res += stringifyItem(item);
+ for (const st of token.end)
+ res += st.source;
+ return res;
+ }
+ case 'document': {
+ let res = stringifyItem(token);
+ if (token.end)
+ for (const st of token.end)
+ res += st.source;
+ return res;
+ }
+ default: {
+ let res = token.source;
+ if ('end' in token && token.end)
+ for (const st of token.end)
+ res += st.source;
+ return res;
+ }
+ }
+}
+function stringifyItem({ start, key, sep, value }) {
+ let res = '';
+ for (const st of start)
+ res += st.source;
+ if (key)
+ res += stringifyToken(key);
+ if (sep)
+ for (const st of sep)
+ res += st.source;
+ if (value)
+ res += stringifyToken(value);
+ return res;
+}
+
+exports.stringify = stringify;
diff --git a/MistyCore/node_modules/yaml/dist/parse/cst-visit.d.ts b/MistyCore/node_modules/yaml/dist/parse/cst-visit.d.ts
new file mode 100644
index 0000000..71c6029
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/cst-visit.d.ts
@@ -0,0 +1,39 @@
+import type { CollectionItem, Document } from './cst.js';
+export declare type VisitPath = readonly ['key' | 'value', number][];
+export declare type Visitor = (item: CollectionItem, path: VisitPath) => number | symbol | Visitor | void;
+/**
+ * Apply a visitor to a CST document or item.
+ *
+ * Walks through the tree (depth-first) starting from the root, calling a
+ * `visitor` function with two arguments when entering each item:
+ * - `item`: The current item, which included the following members:
+ * - `start: SourceToken[]` – Source tokens before the key or value,
+ * possibly including its anchor or tag.
+ * - `key?: Token | null` – Set for pair values. May then be `null`, if
+ * the key before the `:` separator is empty.
+ * - `sep?: SourceToken[]` – Source tokens between the key and the value,
+ * which should include the `:` map value indicator if `value` is set.
+ * - `value?: Token` – The value of a sequence item, or of a map pair.
+ * - `path`: The steps from the root to the current node, as an array of
+ * `['key' | 'value', number]` tuples.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this token, continue with
+ * next sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current item, then continue with the next one
+ * - `number`: Set the index of the next step. This is useful especially if
+ * the index of the current token has changed.
+ * - `function`: Define the next visitor for this item. After the original
+ * visitor is called on item entry, next visitors are called after handling
+ * a non-empty `key` and when exiting the item.
+ */
+export declare function visit(cst: Document | CollectionItem, visitor: Visitor): void;
+export declare namespace visit {
+ var BREAK: symbol;
+ var SKIP: symbol;
+ var REMOVE: symbol;
+ var itemAtPath: (cst: Document | CollectionItem, path: VisitPath) => CollectionItem | undefined;
+ var parentCollection: (cst: Document | CollectionItem, path: VisitPath) => import("./cst.js").BlockMap | import("./cst.js").BlockSequence | import("./cst.js").FlowCollection;
+}
diff --git a/MistyCore/node_modules/yaml/dist/parse/cst-visit.js b/MistyCore/node_modules/yaml/dist/parse/cst-visit.js
new file mode 100644
index 0000000..9ceee93
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/cst-visit.js
@@ -0,0 +1,99 @@
+'use strict';
+
+const BREAK = Symbol('break visit');
+const SKIP = Symbol('skip children');
+const REMOVE = Symbol('remove item');
+/**
+ * Apply a visitor to a CST document or item.
+ *
+ * Walks through the tree (depth-first) starting from the root, calling a
+ * `visitor` function with two arguments when entering each item:
+ * - `item`: The current item, which included the following members:
+ * - `start: SourceToken[]` – Source tokens before the key or value,
+ * possibly including its anchor or tag.
+ * - `key?: Token | null` – Set for pair values. May then be `null`, if
+ * the key before the `:` separator is empty.
+ * - `sep?: SourceToken[]` – Source tokens between the key and the value,
+ * which should include the `:` map value indicator if `value` is set.
+ * - `value?: Token` – The value of a sequence item, or of a map pair.
+ * - `path`: The steps from the root to the current node, as an array of
+ * `['key' | 'value', number]` tuples.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this token, continue with
+ * next sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current item, then continue with the next one
+ * - `number`: Set the index of the next step. This is useful especially if
+ * the index of the current token has changed.
+ * - `function`: Define the next visitor for this item. After the original
+ * visitor is called on item entry, next visitors are called after handling
+ * a non-empty `key` and when exiting the item.
+ */
+function visit(cst, visitor) {
+ if ('type' in cst && cst.type === 'document')
+ cst = { start: cst.start, value: cst.value };
+ _visit(Object.freeze([]), cst, visitor);
+}
+// Without the `as symbol` casts, TS declares these in the `visit`
+// namespace using `var`, but then complains about that because
+// `unique symbol` must be `const`.
+/** Terminate visit traversal completely */
+visit.BREAK = BREAK;
+/** Do not visit the children of the current item */
+visit.SKIP = SKIP;
+/** Remove the current item */
+visit.REMOVE = REMOVE;
+/** Find the item at `path` from `cst` as the root */
+visit.itemAtPath = (cst, path) => {
+ let item = cst;
+ for (const [field, index] of path) {
+ const tok = item?.[field];
+ if (tok && 'items' in tok) {
+ item = tok.items[index];
+ }
+ else
+ return undefined;
+ }
+ return item;
+};
+/**
+ * Get the immediate parent collection of the item at `path` from `cst` as the root.
+ *
+ * Throws an error if the collection is not found, which should never happen if the item itself exists.
+ */
+visit.parentCollection = (cst, path) => {
+ const parent = visit.itemAtPath(cst, path.slice(0, -1));
+ const field = path[path.length - 1][0];
+ const coll = parent?.[field];
+ if (coll && 'items' in coll)
+ return coll;
+ throw new Error('Parent collection not found');
+};
+function _visit(path, item, visitor) {
+ let ctrl = visitor(item, path);
+ if (typeof ctrl === 'symbol')
+ return ctrl;
+ for (const field of ['key', 'value']) {
+ const token = item[field];
+ if (token && 'items' in token) {
+ for (let i = 0; i < token.items.length; ++i) {
+ const ci = _visit(Object.freeze(path.concat([[field, i]])), token.items[i], visitor);
+ if (typeof ci === 'number')
+ i = ci - 1;
+ else if (ci === BREAK)
+ return BREAK;
+ else if (ci === REMOVE) {
+ token.items.splice(i, 1);
+ i -= 1;
+ }
+ }
+ if (typeof ctrl === 'function' && field === 'key')
+ ctrl = ctrl(item, path);
+ }
+ }
+ return typeof ctrl === 'function' ? ctrl(item, path) : ctrl;
+}
+
+exports.visit = visit;
diff --git a/MistyCore/node_modules/yaml/dist/parse/cst.d.ts b/MistyCore/node_modules/yaml/dist/parse/cst.d.ts
new file mode 100644
index 0000000..e5dd4e7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/cst.d.ts
@@ -0,0 +1,106 @@
+export { createScalarToken, resolveAsScalar, setScalarValue } from './cst-scalar.js';
+export { stringify } from './cst-stringify.js';
+export { visit, Visitor, VisitPath } from './cst-visit.js';
+export interface SourceToken {
+ type: 'byte-order-mark' | 'doc-mode' | 'doc-start' | 'space' | 'comment' | 'newline' | 'directive-line' | 'anchor' | 'tag' | 'seq-item-ind' | 'explicit-key-ind' | 'map-value-ind' | 'flow-map-start' | 'flow-map-end' | 'flow-seq-start' | 'flow-seq-end' | 'flow-error-end' | 'comma' | 'block-scalar-header';
+ offset: number;
+ indent: number;
+ source: string;
+}
+export interface ErrorToken {
+ type: 'error';
+ offset: number;
+ source: string;
+ message: string;
+}
+export interface Directive {
+ type: 'directive';
+ offset: number;
+ source: string;
+}
+export interface Document {
+ type: 'document';
+ offset: number;
+ start: SourceToken[];
+ value?: Token;
+ end?: SourceToken[];
+}
+export interface DocumentEnd {
+ type: 'doc-end';
+ offset: number;
+ source: string;
+ end?: SourceToken[];
+}
+export interface FlowScalar {
+ type: 'alias' | 'scalar' | 'single-quoted-scalar' | 'double-quoted-scalar';
+ offset: number;
+ indent: number;
+ source: string;
+ end?: SourceToken[];
+}
+export interface BlockScalar {
+ type: 'block-scalar';
+ offset: number;
+ indent: number;
+ props: Token[];
+ source: string;
+}
+export interface BlockMap {
+ type: 'block-map';
+ offset: number;
+ indent: number;
+ items: Array<{
+ start: SourceToken[];
+ key?: never;
+ sep?: never;
+ value?: never;
+ } | {
+ start: SourceToken[];
+ key: Token | null;
+ sep: SourceToken[];
+ value?: Token;
+ }>;
+}
+export interface BlockSequence {
+ type: 'block-seq';
+ offset: number;
+ indent: number;
+ items: Array<{
+ start: SourceToken[];
+ key?: never;
+ sep?: never;
+ value?: Token;
+ }>;
+}
+export declare type CollectionItem = {
+ start: SourceToken[];
+ key?: Token | null;
+ sep?: SourceToken[];
+ value?: Token;
+};
+export interface FlowCollection {
+ type: 'flow-collection';
+ offset: number;
+ indent: number;
+ start: SourceToken;
+ items: CollectionItem[];
+ end: SourceToken[];
+}
+export declare type Token = SourceToken | ErrorToken | Directive | Document | DocumentEnd | FlowScalar | BlockScalar | BlockMap | BlockSequence | FlowCollection;
+export declare type TokenType = SourceToken['type'] | DocumentEnd['type'] | FlowScalar['type'];
+/** The byte order mark */
+export declare const BOM = "\uFEFF";
+/** Start of doc-mode */
+export declare const DOCUMENT = "\u0002";
+/** Unexpected end of flow-mode */
+export declare const FLOW_END = "\u0018";
+/** Next token is a scalar value */
+export declare const SCALAR = "\u001F";
+/** @returns `true` if `token` is a flow or block collection */
+export declare const isCollection: (token: Token | null | undefined) => token is BlockMap | BlockSequence | FlowCollection;
+/** @returns `true` if `token` is a flow or block scalar; not an alias */
+export declare const isScalar: (token: Token | null | undefined) => token is BlockScalar | FlowScalar;
+/** Get a printable representation of a lexer token */
+export declare function prettyToken(token: string): string;
+/** Identify the type of a lexer token. May return `null` for unknown tokens. */
+export declare function tokenType(source: string): TokenType | null;
diff --git a/MistyCore/node_modules/yaml/dist/parse/cst.js b/MistyCore/node_modules/yaml/dist/parse/cst.js
new file mode 100644
index 0000000..613c229
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/cst.js
@@ -0,0 +1,112 @@
+'use strict';
+
+var cstScalar = require('./cst-scalar.js');
+var cstStringify = require('./cst-stringify.js');
+var cstVisit = require('./cst-visit.js');
+
+/** The byte order mark */
+const BOM = '\u{FEFF}';
+/** Start of doc-mode */
+const DOCUMENT = '\x02'; // C0: Start of Text
+/** Unexpected end of flow-mode */
+const FLOW_END = '\x18'; // C0: Cancel
+/** Next token is a scalar value */
+const SCALAR = '\x1f'; // C0: Unit Separator
+/** @returns `true` if `token` is a flow or block collection */
+const isCollection = (token) => !!token && 'items' in token;
+/** @returns `true` if `token` is a flow or block scalar; not an alias */
+const isScalar = (token) => !!token &&
+ (token.type === 'scalar' ||
+ token.type === 'single-quoted-scalar' ||
+ token.type === 'double-quoted-scalar' ||
+ token.type === 'block-scalar');
+/* istanbul ignore next */
+/** Get a printable representation of a lexer token */
+function prettyToken(token) {
+ switch (token) {
+ case BOM:
+ return '<BOM>';
+ case DOCUMENT:
+ return '<DOC>';
+ case FLOW_END:
+ return '<FLOW_END>';
+ case SCALAR:
+ return '<SCALAR>';
+ default:
+ return JSON.stringify(token);
+ }
+}
+/** Identify the type of a lexer token. May return `null` for unknown tokens. */
+function tokenType(source) {
+ switch (source) {
+ case BOM:
+ return 'byte-order-mark';
+ case DOCUMENT:
+ return 'doc-mode';
+ case FLOW_END:
+ return 'flow-error-end';
+ case SCALAR:
+ return 'scalar';
+ case '---':
+ return 'doc-start';
+ case '...':
+ return 'doc-end';
+ case '':
+ case '\n':
+ case '\r\n':
+ return 'newline';
+ case '-':
+ return 'seq-item-ind';
+ case '?':
+ return 'explicit-key-ind';
+ case ':':
+ return 'map-value-ind';
+ case '{':
+ return 'flow-map-start';
+ case '}':
+ return 'flow-map-end';
+ case '[':
+ return 'flow-seq-start';
+ case ']':
+ return 'flow-seq-end';
+ case ',':
+ return 'comma';
+ }
+ switch (source[0]) {
+ case ' ':
+ case '\t':
+ return 'space';
+ case '#':
+ return 'comment';
+ case '%':
+ return 'directive-line';
+ case '*':
+ return 'alias';
+ case '&':
+ return 'anchor';
+ case '!':
+ return 'tag';
+ case "'":
+ return 'single-quoted-scalar';
+ case '"':
+ return 'double-quoted-scalar';
+ case '|':
+ case '>':
+ return 'block-scalar-header';
+ }
+ return null;
+}
+
+exports.createScalarToken = cstScalar.createScalarToken;
+exports.resolveAsScalar = cstScalar.resolveAsScalar;
+exports.setScalarValue = cstScalar.setScalarValue;
+exports.stringify = cstStringify.stringify;
+exports.visit = cstVisit.visit;
+exports.BOM = BOM;
+exports.DOCUMENT = DOCUMENT;
+exports.FLOW_END = FLOW_END;
+exports.SCALAR = SCALAR;
+exports.isCollection = isCollection;
+exports.isScalar = isScalar;
+exports.prettyToken = prettyToken;
+exports.tokenType = tokenType;
diff --git a/MistyCore/node_modules/yaml/dist/parse/lexer.d.ts b/MistyCore/node_modules/yaml/dist/parse/lexer.d.ts
new file mode 100644
index 0000000..238e7b5
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/lexer.d.ts
@@ -0,0 +1,87 @@
+/**
+ * Splits an input string into lexical tokens, i.e. smaller strings that are
+ * easily identifiable by `tokens.tokenType()`.
+ *
+ * Lexing starts always in a "stream" context. Incomplete input may be buffered
+ * until a complete token can be emitted.
+ *
+ * In addition to slices of the original input, the following control characters
+ * may also be emitted:
+ *
+ * - `\x02` (Start of Text): A document starts with the next token
+ * - `\x18` (Cancel): Unexpected end of flow-mode (indicates an error)
+ * - `\x1f` (Unit Separator): Next token is a scalar value
+ * - `\u{FEFF}` (Byte order mark): Emitted separately outside documents
+ */
+export declare class Lexer {
+ /**
+ * Flag indicating whether the end of the current buffer marks the end of
+ * all input
+ */
+ private atEnd;
+ /**
+ * Explicit indent set in block scalar header, as an offset from the current
+ * minimum indent, so e.g. set to 1 from a header `|2+`. Set to -1 if not
+ * explicitly set.
+ */
+ private blockScalarIndent;
+ /**
+ * Block scalars that include a + (keep) chomping indicator in their header
+ * include trailing empty lines, which are otherwise excluded from the
+ * scalar's contents.
+ */
+ private blockScalarKeep;
+ /** Current input */
+ private buffer;
+ /**
+ * Flag noting whether the map value indicator : can immediately follow this
+ * node within a flow context.
+ */
+ private flowKey;
+ /** Count of surrounding flow collection levels. */
+ private flowLevel;
+ /**
+ * Minimum level of indentation required for next lines to be parsed as a
+ * part of the current scalar value.
+ */
+ private indentNext;
+ /** Indentation level of the current line. */
+ private indentValue;
+ /** Position of the next \n character. */
+ private lineEndPos;
+ /** Stores the state of the lexer if reaching the end of incpomplete input */
+ private next;
+ /** A pointer to `buffer`; the current position of the lexer. */
+ private pos;
+ /**
+ * Generate YAML tokens from the `source` string. If `incomplete`,
+ * a part of the last line may be left as a buffer for the next call.
+ *
+ * @returns A generator of lexical tokens
+ */
+ lex(source: string, incomplete?: boolean): Generator<string, void, unknown>;
+ private atLineEnd;
+ private charAt;
+ private continueScalar;
+ private getLine;
+ private hasChars;
+ private setNext;
+ private peek;
+ private parseNext;
+ private parseStream;
+ private parseLineStart;
+ private parseBlockStart;
+ private parseDocument;
+ private parseFlowCollection;
+ private parseQuotedScalar;
+ private parseBlockScalarHeader;
+ private parseBlockScalar;
+ private parsePlainScalar;
+ private pushCount;
+ private pushToIndex;
+ private pushIndicators;
+ private pushTag;
+ private pushNewline;
+ private pushSpaces;
+ private pushUntil;
+}
diff --git a/MistyCore/node_modules/yaml/dist/parse/lexer.js b/MistyCore/node_modules/yaml/dist/parse/lexer.js
new file mode 100644
index 0000000..f408ce4
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/lexer.js
@@ -0,0 +1,703 @@
+'use strict';
+
+var cst = require('./cst.js');
+
+/*
+START -> stream
+
+stream
+ directive -> line-end -> stream
+ indent + line-end -> stream
+ [else] -> line-start
+
+line-end
+ comment -> line-end
+ newline -> .
+ input-end -> END
+
+line-start
+ doc-start -> doc
+ doc-end -> stream
+ [else] -> indent -> block-start
+
+block-start
+ seq-item-start -> block-start
+ explicit-key-start -> block-start
+ map-value-start -> block-start
+ [else] -> doc
+
+doc
+ line-end -> line-start
+ spaces -> doc
+ anchor -> doc
+ tag -> doc
+ flow-start -> flow -> doc
+ flow-end -> error -> doc
+ seq-item-start -> error -> doc
+ explicit-key-start -> error -> doc
+ map-value-start -> doc
+ alias -> doc
+ quote-start -> quoted-scalar -> doc
+ block-scalar-header -> line-end -> block-scalar(min) -> line-start
+ [else] -> plain-scalar(false, min) -> doc
+
+flow
+ line-end -> flow
+ spaces -> flow
+ anchor -> flow
+ tag -> flow
+ flow-start -> flow -> flow
+ flow-end -> .
+ seq-item-start -> error -> flow
+ explicit-key-start -> flow
+ map-value-start -> flow
+ alias -> flow
+ quote-start -> quoted-scalar -> flow
+ comma -> flow
+ [else] -> plain-scalar(true, 0) -> flow
+
+quoted-scalar
+ quote-end -> .
+ [else] -> quoted-scalar
+
+block-scalar(min)
+ newline + peek(indent < min) -> .
+ [else] -> block-scalar(min)
+
+plain-scalar(is-flow, min)
+ scalar-end(is-flow) -> .
+ peek(newline + (indent < min)) -> .
+ [else] -> plain-scalar(min)
+*/
+function isEmpty(ch) {
+ switch (ch) {
+ case undefined:
+ case ' ':
+ case '\n':
+ case '\r':
+ case '\t':
+ return true;
+ default:
+ return false;
+ }
+}
+const hexDigits = '0123456789ABCDEFabcdef'.split('');
+const tagChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()".split('');
+const invalidFlowScalarChars = ',[]{}'.split('');
+const invalidAnchorChars = ' ,[]{}\n\r\t'.split('');
+const isNotAnchorChar = (ch) => !ch || invalidAnchorChars.includes(ch);
+/**
+ * Splits an input string into lexical tokens, i.e. smaller strings that are
+ * easily identifiable by `tokens.tokenType()`.
+ *
+ * Lexing starts always in a "stream" context. Incomplete input may be buffered
+ * until a complete token can be emitted.
+ *
+ * In addition to slices of the original input, the following control characters
+ * may also be emitted:
+ *
+ * - `\x02` (Start of Text): A document starts with the next token
+ * - `\x18` (Cancel): Unexpected end of flow-mode (indicates an error)
+ * - `\x1f` (Unit Separator): Next token is a scalar value
+ * - `\u{FEFF}` (Byte order mark): Emitted separately outside documents
+ */
+class Lexer {
+ constructor() {
+ /**
+ * Flag indicating whether the end of the current buffer marks the end of
+ * all input
+ */
+ this.atEnd = false;
+ /**
+ * Explicit indent set in block scalar header, as an offset from the current
+ * minimum indent, so e.g. set to 1 from a header `|2+`. Set to -1 if not
+ * explicitly set.
+ */
+ this.blockScalarIndent = -1;
+ /**
+ * Block scalars that include a + (keep) chomping indicator in their header
+ * include trailing empty lines, which are otherwise excluded from the
+ * scalar's contents.
+ */
+ this.blockScalarKeep = false;
+ /** Current input */
+ this.buffer = '';
+ /**
+ * Flag noting whether the map value indicator : can immediately follow this
+ * node within a flow context.
+ */
+ this.flowKey = false;
+ /** Count of surrounding flow collection levels. */
+ this.flowLevel = 0;
+ /**
+ * Minimum level of indentation required for next lines to be parsed as a
+ * part of the current scalar value.
+ */
+ this.indentNext = 0;
+ /** Indentation level of the current line. */
+ this.indentValue = 0;
+ /** Position of the next \n character. */
+ this.lineEndPos = null;
+ /** Stores the state of the lexer if reaching the end of incpomplete input */
+ this.next = null;
+ /** A pointer to `buffer`; the current position of the lexer. */
+ this.pos = 0;
+ }
+ /**
+ * Generate YAML tokens from the `source` string. If `incomplete`,
+ * a part of the last line may be left as a buffer for the next call.
+ *
+ * @returns A generator of lexical tokens
+ */
+ *lex(source, incomplete = false) {
+ if (source) {
+ this.buffer = this.buffer ? this.buffer + source : source;
+ this.lineEndPos = null;
+ }
+ this.atEnd = !incomplete;
+ let next = this.next ?? 'stream';
+ while (next && (incomplete || this.hasChars(1)))
+ next = yield* this.parseNext(next);
+ }
+ atLineEnd() {
+ let i = this.pos;
+ let ch = this.buffer[i];
+ while (ch === ' ' || ch === '\t')
+ ch = this.buffer[++i];
+ if (!ch || ch === '#' || ch === '\n')
+ return true;
+ if (ch === '\r')
+ return this.buffer[i + 1] === '\n';
+ return false;
+ }
+ charAt(n) {
+ return this.buffer[this.pos + n];
+ }
+ continueScalar(offset) {
+ let ch = this.buffer[offset];
+ if (this.indentNext > 0) {
+ let indent = 0;
+ while (ch === ' ')
+ ch = this.buffer[++indent + offset];
+ if (ch === '\r') {
+ const next = this.buffer[indent + offset + 1];
+ if (next === '\n' || (!next && !this.atEnd))
+ return offset + indent + 1;
+ }
+ return ch === '\n' || indent >= this.indentNext || (!ch && !this.atEnd)
+ ? offset + indent
+ : -1;
+ }
+ if (ch === '-' || ch === '.') {
+ const dt = this.buffer.substr(offset, 3);
+ if ((dt === '---' || dt === '...') && isEmpty(this.buffer[offset + 3]))
+ return -1;
+ }
+ return offset;
+ }
+ getLine() {
+ let end = this.lineEndPos;
+ if (typeof end !== 'number' || (end !== -1 && end < this.pos)) {
+ end = this.buffer.indexOf('\n', this.pos);
+ this.lineEndPos = end;
+ }
+ if (end === -1)
+ return this.atEnd ? this.buffer.substring(this.pos) : null;
+ if (this.buffer[end - 1] === '\r')
+ end -= 1;
+ return this.buffer.substring(this.pos, end);
+ }
+ hasChars(n) {
+ return this.pos + n <= this.buffer.length;
+ }
+ setNext(state) {
+ this.buffer = this.buffer.substring(this.pos);
+ this.pos = 0;
+ this.lineEndPos = null;
+ this.next = state;
+ return null;
+ }
+ peek(n) {
+ return this.buffer.substr(this.pos, n);
+ }
+ *parseNext(next) {
+ switch (next) {
+ case 'stream':
+ return yield* this.parseStream();
+ case 'line-start':
+ return yield* this.parseLineStart();
+ case 'block-start':
+ return yield* this.parseBlockStart();
+ case 'doc':
+ return yield* this.parseDocument();
+ case 'flow':
+ return yield* this.parseFlowCollection();
+ case 'quoted-scalar':
+ return yield* this.parseQuotedScalar();
+ case 'block-scalar':
+ return yield* this.parseBlockScalar();
+ case 'plain-scalar':
+ return yield* this.parsePlainScalar();
+ }
+ }
+ *parseStream() {
+ let line = this.getLine();
+ if (line === null)
+ return this.setNext('stream');
+ if (line[0] === cst.BOM) {
+ yield* this.pushCount(1);
+ line = line.substring(1);
+ }
+ if (line[0] === '%') {
+ let dirEnd = line.length;
+ const cs = line.indexOf('#');
+ if (cs !== -1) {
+ const ch = line[cs - 1];
+ if (ch === ' ' || ch === '\t')
+ dirEnd = cs - 1;
+ }
+ while (true) {
+ const ch = line[dirEnd - 1];
+ if (ch === ' ' || ch === '\t')
+ dirEnd -= 1;
+ else
+ break;
+ }
+ const n = (yield* this.pushCount(dirEnd)) + (yield* this.pushSpaces(true));
+ yield* this.pushCount(line.length - n); // possible comment
+ this.pushNewline();
+ return 'stream';
+ }
+ if (this.atLineEnd()) {
+ const sp = yield* this.pushSpaces(true);
+ yield* this.pushCount(line.length - sp);
+ yield* this.pushNewline();
+ return 'stream';
+ }
+ yield cst.DOCUMENT;
+ return yield* this.parseLineStart();
+ }
+ *parseLineStart() {
+ const ch = this.charAt(0);
+ if (!ch && !this.atEnd)
+ return this.setNext('line-start');
+ if (ch === '-' || ch === '.') {
+ if (!this.atEnd && !this.hasChars(4))
+ return this.setNext('line-start');
+ const s = this.peek(3);
+ if (s === '---' && isEmpty(this.charAt(3))) {
+ yield* this.pushCount(3);
+ this.indentValue = 0;
+ this.indentNext = 0;
+ return 'doc';
+ }
+ else if (s === '...' && isEmpty(this.charAt(3))) {
+ yield* this.pushCount(3);
+ return 'stream';
+ }
+ }
+ this.indentValue = yield* this.pushSpaces(false);
+ if (this.indentNext > this.indentValue && !isEmpty(this.charAt(1)))
+ this.indentNext = this.indentValue;
+ return yield* this.parseBlockStart();
+ }
+ *parseBlockStart() {
+ const [ch0, ch1] = this.peek(2);
+ if (!ch1 && !this.atEnd)
+ return this.setNext('block-start');
+ if ((ch0 === '-' || ch0 === '?' || ch0 === ':') && isEmpty(ch1)) {
+ const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
+ this.indentNext = this.indentValue + 1;
+ this.indentValue += n;
+ return yield* this.parseBlockStart();
+ }
+ return 'doc';
+ }
+ *parseDocument() {
+ yield* this.pushSpaces(true);
+ const line = this.getLine();
+ if (line === null)
+ return this.setNext('doc');
+ let n = yield* this.pushIndicators();
+ switch (line[n]) {
+ case '#':
+ yield* this.pushCount(line.length - n);
+ // fallthrough
+ case undefined:
+ yield* this.pushNewline();
+ return yield* this.parseLineStart();
+ case '{':
+ case '[':
+ yield* this.pushCount(1);
+ this.flowKey = false;
+ this.flowLevel = 1;
+ return 'flow';
+ case '}':
+ case ']':
+ // this is an error
+ yield* this.pushCount(1);
+ return 'doc';
+ case '*':
+ yield* this.pushUntil(isNotAnchorChar);
+ return 'doc';
+ case '"':
+ case "'":
+ return yield* this.parseQuotedScalar();
+ case '|':
+ case '>':
+ n += yield* this.parseBlockScalarHeader();
+ n += yield* this.pushSpaces(true);
+ yield* this.pushCount(line.length - n);
+ yield* this.pushNewline();
+ return yield* this.parseBlockScalar();
+ default:
+ return yield* this.parsePlainScalar();
+ }
+ }
+ *parseFlowCollection() {
+ let nl, sp;
+ let indent = -1;
+ do {
+ nl = yield* this.pushNewline();
+ if (nl > 0) {
+ sp = yield* this.pushSpaces(false);
+ this.indentValue = indent = sp;
+ }
+ else {
+ sp = 0;
+ }
+ sp += yield* this.pushSpaces(true);
+ } while (nl + sp > 0);
+ const line = this.getLine();
+ if (line === null)
+ return this.setNext('flow');
+ if ((indent !== -1 && indent < this.indentNext && line[0] !== '#') ||
+ (indent === 0 &&
+ (line.startsWith('---') || line.startsWith('...')) &&
+ isEmpty(line[3]))) {
+ // Allowing for the terminal ] or } at the same (rather than greater)
+ // indent level as the initial [ or { is technically invalid, but
+ // failing here would be surprising to users.
+ const atFlowEndMarker = indent === this.indentNext - 1 &&
+ this.flowLevel === 1 &&
+ (line[0] === ']' || line[0] === '}');
+ if (!atFlowEndMarker) {
+ // this is an error
+ this.flowLevel = 0;
+ yield cst.FLOW_END;
+ return yield* this.parseLineStart();
+ }
+ }
+ let n = 0;
+ while (line[n] === ',') {
+ n += yield* this.pushCount(1);
+ n += yield* this.pushSpaces(true);
+ this.flowKey = false;
+ }
+ n += yield* this.pushIndicators();
+ switch (line[n]) {
+ case undefined:
+ return 'flow';
+ case '#':
+ yield* this.pushCount(line.length - n);
+ return 'flow';
+ case '{':
+ case '[':
+ yield* this.pushCount(1);
+ this.flowKey = false;
+ this.flowLevel += 1;
+ return 'flow';
+ case '}':
+ case ']':
+ yield* this.pushCount(1);
+ this.flowKey = true;
+ this.flowLevel -= 1;
+ return this.flowLevel ? 'flow' : 'doc';
+ case '*':
+ yield* this.pushUntil(isNotAnchorChar);
+ return 'flow';
+ case '"':
+ case "'":
+ this.flowKey = true;
+ return yield* this.parseQuotedScalar();
+ case ':': {
+ const next = this.charAt(1);
+ if (this.flowKey || isEmpty(next) || next === ',') {
+ this.flowKey = false;
+ yield* this.pushCount(1);
+ yield* this.pushSpaces(true);
+ return 'flow';
+ }
+ }
+ // fallthrough
+ default:
+ this.flowKey = false;
+ return yield* this.parsePlainScalar();
+ }
+ }
+ *parseQuotedScalar() {
+ const quote = this.charAt(0);
+ let end = this.buffer.indexOf(quote, this.pos + 1);
+ if (quote === "'") {
+ while (end !== -1 && this.buffer[end + 1] === "'")
+ end = this.buffer.indexOf("'", end + 2);
+ }
+ else {
+ // double-quote
+ while (end !== -1) {
+ let n = 0;
+ while (this.buffer[end - 1 - n] === '\\')
+ n += 1;
+ if (n % 2 === 0)
+ break;
+ end = this.buffer.indexOf('"', end + 1);
+ }
+ }
+ // Only looking for newlines within the quotes
+ const qb = this.buffer.substring(0, end);
+ let nl = qb.indexOf('\n', this.pos);
+ if (nl !== -1) {
+ while (nl !== -1) {
+ const cs = this.continueScalar(nl + 1);
+ if (cs === -1)
+ break;
+ nl = qb.indexOf('\n', cs);
+ }
+ if (nl !== -1) {
+ // this is an error caused by an unexpected unindent
+ end = nl - (qb[nl - 1] === '\r' ? 2 : 1);
+ }
+ }
+ if (end === -1) {
+ if (!this.atEnd)
+ return this.setNext('quoted-scalar');
+ end = this.buffer.length;
+ }
+ yield* this.pushToIndex(end + 1, false);
+ return this.flowLevel ? 'flow' : 'doc';
+ }
+ *parseBlockScalarHeader() {
+ this.blockScalarIndent = -1;
+ this.blockScalarKeep = false;
+ let i = this.pos;
+ while (true) {
+ const ch = this.buffer[++i];
+ if (ch === '+')
+ this.blockScalarKeep = true;
+ else if (ch > '0' && ch <= '9')
+ this.blockScalarIndent = Number(ch) - 1;
+ else if (ch !== '-')
+ break;
+ }
+ return yield* this.pushUntil(ch => isEmpty(ch) || ch === '#');
+ }
+ *parseBlockScalar() {
+ let nl = this.pos - 1; // may be -1 if this.pos === 0
+ let indent = 0;
+ let ch;
+ loop: for (let i = this.pos; (ch = this.buffer[i]); ++i) {
+ switch (ch) {
+ case ' ':
+ indent += 1;
+ break;
+ case '\n':
+ nl = i;
+ indent = 0;
+ break;
+ case '\r': {
+ const next = this.buffer[i + 1];
+ if (!next && !this.atEnd)
+ return this.setNext('block-scalar');
+ if (next === '\n')
+ break;
+ } // fallthrough
+ default:
+ break loop;
+ }
+ }
+ if (!ch && !this.atEnd)
+ return this.setNext('block-scalar');
+ if (indent >= this.indentNext) {
+ if (this.blockScalarIndent === -1)
+ this.indentNext = indent;
+ else
+ this.indentNext += this.blockScalarIndent;
+ do {
+ const cs = this.continueScalar(nl + 1);
+ if (cs === -1)
+ break;
+ nl = this.buffer.indexOf('\n', cs);
+ } while (nl !== -1);
+ if (nl === -1) {
+ if (!this.atEnd)
+ return this.setNext('block-scalar');
+ nl = this.buffer.length;
+ }
+ }
+ if (!this.blockScalarKeep) {
+ do {
+ let i = nl - 1;
+ let ch = this.buffer[i];
+ if (ch === '\r')
+ ch = this.buffer[--i];
+ const lastChar = i; // Drop the line if last char not more indented
+ while (ch === ' ' || ch === '\t')
+ ch = this.buffer[--i];
+ if (ch === '\n' && i >= this.pos && i + 1 + indent > lastChar)
+ nl = i;
+ else
+ break;
+ } while (true);
+ }
+ yield cst.SCALAR;
+ yield* this.pushToIndex(nl + 1, true);
+ return yield* this.parseLineStart();
+ }
+ *parsePlainScalar() {
+ const inFlow = this.flowLevel > 0;
+ let end = this.pos - 1;
+ let i = this.pos - 1;
+ let ch;
+ while ((ch = this.buffer[++i])) {
+ if (ch === ':') {
+ const next = this.buffer[i + 1];
+ if (isEmpty(next) || (inFlow && next === ','))
+ break;
+ end = i;
+ }
+ else if (isEmpty(ch)) {
+ let next = this.buffer[i + 1];
+ if (ch === '\r') {
+ if (next === '\n') {
+ i += 1;
+ ch = '\n';
+ next = this.buffer[i + 1];
+ }
+ else
+ end = i;
+ }
+ if (next === '#' || (inFlow && invalidFlowScalarChars.includes(next)))
+ break;
+ if (ch === '\n') {
+ const cs = this.continueScalar(i + 1);
+ if (cs === -1)
+ break;
+ i = Math.max(i, cs - 2); // to advance, but still account for ' #'
+ }
+ }
+ else {
+ if (inFlow && invalidFlowScalarChars.includes(ch))
+ break;
+ end = i;
+ }
+ }
+ if (!ch && !this.atEnd)
+ return this.setNext('plain-scalar');
+ yield cst.SCALAR;
+ yield* this.pushToIndex(end + 1, true);
+ return inFlow ? 'flow' : 'doc';
+ }
+ *pushCount(n) {
+ if (n > 0) {
+ yield this.buffer.substr(this.pos, n);
+ this.pos += n;
+ return n;
+ }
+ return 0;
+ }
+ *pushToIndex(i, allowEmpty) {
+ const s = this.buffer.slice(this.pos, i);
+ if (s) {
+ yield s;
+ this.pos += s.length;
+ return s.length;
+ }
+ else if (allowEmpty)
+ yield '';
+ return 0;
+ }
+ *pushIndicators() {
+ switch (this.charAt(0)) {
+ case '!':
+ return ((yield* this.pushTag()) +
+ (yield* this.pushSpaces(true)) +
+ (yield* this.pushIndicators()));
+ case '&':
+ return ((yield* this.pushUntil(isNotAnchorChar)) +
+ (yield* this.pushSpaces(true)) +
+ (yield* this.pushIndicators()));
+ case '-': // this is an error
+ case '?': // this is an error outside flow collections
+ case ':': {
+ const inFlow = this.flowLevel > 0;
+ const ch1 = this.charAt(1);
+ if (isEmpty(ch1) || (inFlow && invalidFlowScalarChars.includes(ch1))) {
+ if (!inFlow)
+ this.indentNext = this.indentValue + 1;
+ else if (this.flowKey)
+ this.flowKey = false;
+ return ((yield* this.pushCount(1)) +
+ (yield* this.pushSpaces(true)) +
+ (yield* this.pushIndicators()));
+ }
+ }
+ }
+ return 0;
+ }
+ *pushTag() {
+ if (this.charAt(1) === '<') {
+ let i = this.pos + 2;
+ let ch = this.buffer[i];
+ while (!isEmpty(ch) && ch !== '>')
+ ch = this.buffer[++i];
+ return yield* this.pushToIndex(ch === '>' ? i + 1 : i, false);
+ }
+ else {
+ let i = this.pos + 1;
+ let ch = this.buffer[i];
+ while (ch) {
+ if (tagChars.includes(ch))
+ ch = this.buffer[++i];
+ else if (ch === '%' &&
+ hexDigits.includes(this.buffer[i + 1]) &&
+ hexDigits.includes(this.buffer[i + 2])) {
+ ch = this.buffer[(i += 3)];
+ }
+ else
+ break;
+ }
+ return yield* this.pushToIndex(i, false);
+ }
+ }
+ *pushNewline() {
+ const ch = this.buffer[this.pos];
+ if (ch === '\n')
+ return yield* this.pushCount(1);
+ else if (ch === '\r' && this.charAt(1) === '\n')
+ return yield* this.pushCount(2);
+ else
+ return 0;
+ }
+ *pushSpaces(allowTabs) {
+ let i = this.pos - 1;
+ let ch;
+ do {
+ ch = this.buffer[++i];
+ } while (ch === ' ' || (allowTabs && ch === '\t'));
+ const n = i - this.pos;
+ if (n > 0) {
+ yield this.buffer.substr(this.pos, n);
+ this.pos = i;
+ }
+ return n;
+ }
+ *pushUntil(test) {
+ let i = this.pos;
+ let ch = this.buffer[i];
+ while (!test(ch))
+ ch = this.buffer[++i];
+ return yield* this.pushToIndex(i, false);
+ }
+}
+
+exports.Lexer = Lexer;
diff --git a/MistyCore/node_modules/yaml/dist/parse/line-counter.d.ts b/MistyCore/node_modules/yaml/dist/parse/line-counter.d.ts
new file mode 100644
index 0000000..b469095
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/line-counter.d.ts
@@ -0,0 +1,22 @@
+/**
+ * Tracks newlines during parsing in order to provide an efficient API for
+ * determining the one-indexed `{ line, col }` position for any offset
+ * within the input.
+ */
+export declare class LineCounter {
+ lineStarts: number[];
+ /**
+ * Should be called in ascending order. Otherwise, call
+ * `lineCounter.lineStarts.sort()` before calling `linePos()`.
+ */
+ addNewLine: (offset: number) => number;
+ /**
+ * Performs a binary search and returns the 1-indexed { line, col }
+ * position of `offset`. If `line === 0`, `addNewLine` has never been
+ * called or `offset` is before the first known newline.
+ */
+ linePos: (offset: number) => {
+ line: number;
+ col: number;
+ };
+}
diff --git a/MistyCore/node_modules/yaml/dist/parse/line-counter.js b/MistyCore/node_modules/yaml/dist/parse/line-counter.js
new file mode 100644
index 0000000..0e7383b
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/line-counter.js
@@ -0,0 +1,41 @@
+'use strict';
+
+/**
+ * Tracks newlines during parsing in order to provide an efficient API for
+ * determining the one-indexed `{ line, col }` position for any offset
+ * within the input.
+ */
+class LineCounter {
+ constructor() {
+ this.lineStarts = [];
+ /**
+ * Should be called in ascending order. Otherwise, call
+ * `lineCounter.lineStarts.sort()` before calling `linePos()`.
+ */
+ this.addNewLine = (offset) => this.lineStarts.push(offset);
+ /**
+ * Performs a binary search and returns the 1-indexed { line, col }
+ * position of `offset`. If `line === 0`, `addNewLine` has never been
+ * called or `offset` is before the first known newline.
+ */
+ this.linePos = (offset) => {
+ let low = 0;
+ let high = this.lineStarts.length;
+ while (low < high) {
+ const mid = (low + high) >> 1; // Math.floor((low + high) / 2)
+ if (this.lineStarts[mid] < offset)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+ if (this.lineStarts[low] === offset)
+ return { line: low + 1, col: 1 };
+ if (low === 0)
+ return { line: 0, col: offset };
+ const start = this.lineStarts[low - 1];
+ return { line: low, col: offset - start + 1 };
+ };
+ }
+}
+
+exports.LineCounter = LineCounter;
diff --git a/MistyCore/node_modules/yaml/dist/parse/parser.d.ts b/MistyCore/node_modules/yaml/dist/parse/parser.d.ts
new file mode 100644
index 0000000..8f3159f
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/parser.d.ts
@@ -0,0 +1,84 @@
+import { Token } from './cst.js';
+/**
+ * A YAML concrete syntax tree (CST) parser
+ *
+ * ```ts
+ * const src: string = ...
+ * for (const token of new Parser().parse(src)) {
+ * // token: Token
+ * }
+ * ```
+ *
+ * To use the parser with a user-provided lexer:
+ *
+ * ```ts
+ * function* parse(source: string, lexer: Lexer) {
+ * const parser = new Parser()
+ * for (const lexeme of lexer.lex(source))
+ * yield* parser.next(lexeme)
+ * yield* parser.end()
+ * }
+ *
+ * const src: string = ...
+ * const lexer = new Lexer()
+ * for (const token of parse(src, lexer)) {
+ * // token: Token
+ * }
+ * ```
+ */
+export declare class Parser {
+ private onNewLine?;
+ /** If true, space and sequence indicators count as indentation */
+ private atNewLine;
+ /** If true, next token is a scalar value */
+ private atScalar;
+ /** Current indentation level */
+ private indent;
+ /** Current offset since the start of parsing */
+ offset: number;
+ /** On the same line with a block map key */
+ private onKeyLine;
+ /** Top indicates the node that's currently being built */
+ stack: Token[];
+ /** The source of the current token, set in parse() */
+ private source;
+ /** The type of the current token, set in parse() */
+ private type;
+ /**
+ * @param onNewLine - If defined, called separately with the start position of
+ * each new line (in `parse()`, including the start of input).
+ */
+ constructor(onNewLine?: (offset: number) => void);
+ /**
+ * Parse `source` as a YAML stream.
+ * If `incomplete`, a part of the last line may be left as a buffer for the next call.
+ *
+ * Errors are not thrown, but yielded as `{ type: 'error', message }` tokens.
+ *
+ * @returns A generator of tokens representing each directive, document, and other structure.
+ */
+ parse(source: string, incomplete?: boolean): Generator<Token, void, unknown>;
+ /**
+ * Advance the parser by the `source` of one lexical token.
+ */
+ next(source: string): Generator<Token, void, unknown>;
+ private lexer;
+ /** Call at end of input to push out any remaining constructions */
+ end(): Generator<Token, void, unknown>;
+ private get sourceToken();
+ private step;
+ private peek;
+ private pop;
+ private stream;
+ private document;
+ private scalar;
+ private blockScalar;
+ private blockMap;
+ private blockSequence;
+ private flowCollection;
+ private flowScalar;
+ private startBlockValue;
+ private atIndentedComment;
+ private documentEnd;
+ private lineEnd;
+}
diff --git a/MistyCore/node_modules/yaml/dist/parse/parser.js b/MistyCore/node_modules/yaml/dist/parse/parser.js
new file mode 100644
index 0000000..8dcdf5d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/parse/parser.js
@@ -0,0 +1,954 @@
+'use strict';
+
+var cst = require('./cst.js');
+var lexer = require('./lexer.js');
+
+function includesToken(list, type) {
+ for (let i = 0; i < list.length; ++i)
+ if (list[i].type === type)
+ return true;
+ return false;
+}
+function findNonEmptyIndex(list) {
+ for (let i = 0; i < list.length; ++i) {
+ switch (list[i].type) {
+ case 'space':
+ case 'comment':
+ case 'newline':
+ break;
+ default:
+ return i;
+ }
+ }
+ return -1;
+}
+function isFlowToken(token) {
+ switch (token?.type) {
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ case 'flow-collection':
+ return true;
+ default:
+ return false;
+ }
+}
+function getPrevProps(parent) {
+ switch (parent.type) {
+ case 'document':
+ return parent.start;
+ case 'block-map': {
+ const it = parent.items[parent.items.length - 1];
+ return it.sep ?? it.start;
+ }
+ case 'block-seq':
+ return parent.items[parent.items.length - 1].start;
+ /* istanbul ignore next should not happen */
+ default:
+ return [];
+ }
+}
+/** Note: May modify input array */
+function getFirstKeyStartProps(prev) {
+ if (prev.length === 0)
+ return [];
+ let i = prev.length;
+ loop: while (--i >= 0) {
+ switch (prev[i].type) {
+ case 'doc-start':
+ case 'explicit-key-ind':
+ case 'map-value-ind':
+ case 'seq-item-ind':
+ case 'newline':
+ break loop;
+ }
+ }
+ while (prev[++i]?.type === 'space') {
+ /* loop */
+ }
+ return prev.splice(i, prev.length);
+}
+function fixFlowSeqItems(fc) {
+ if (fc.start.type === 'flow-seq-start') {
+ for (const it of fc.items) {
+ if (it.sep &&
+ !it.value &&
+ !includesToken(it.start, 'explicit-key-ind') &&
+ !includesToken(it.sep, 'map-value-ind')) {
+ if (it.key)
+ it.value = it.key;
+ delete it.key;
+ if (isFlowToken(it.value)) {
+ if (it.value.end)
+ Array.prototype.push.apply(it.value.end, it.sep);
+ else
+ it.value.end = it.sep;
+ }
+ else
+ Array.prototype.push.apply(it.start, it.sep);
+ delete it.sep;
+ }
+ }
+ }
+}
+/**
+ * A YAML concrete syntax tree (CST) parser
+ *
+ * ```ts
+ * const src: string = ...
+ * for (const token of new Parser().parse(src)) {
+ * // token: Token
+ * }
+ * ```
+ *
+ * To use the parser with a user-provided lexer:
+ *
+ * ```ts
+ * function* parse(source: string, lexer: Lexer) {
+ * const parser = new Parser()
+ * for (const lexeme of lexer.lex(source))
+ * yield* parser.next(lexeme)
+ * yield* parser.end()
+ * }
+ *
+ * const src: string = ...
+ * const lexer = new Lexer()
+ * for (const token of parse(src, lexer)) {
+ * // token: Token
+ * }
+ * ```
+ */
+class Parser {
+ /**
+ * @param onNewLine - If defined, called separately with the start position of
+ * each new line (in `parse()`, including the start of input).
+ */
+ constructor(onNewLine) {
+ /** If true, space and sequence indicators count as indentation */
+ this.atNewLine = true;
+ /** If true, next token is a scalar value */
+ this.atScalar = false;
+ /** Current indentation level */
+ this.indent = 0;
+ /** Current offset since the start of parsing */
+ this.offset = 0;
+ /** On the same line with a block map key */
+ this.onKeyLine = false;
+ /** Top indicates the node that's currently being built */
+ this.stack = [];
+ /** The source of the current token, set in parse() */
+ this.source = '';
+ /** The type of the current token, set in parse() */
+ this.type = '';
+ // Must be defined after `next()`
+ this.lexer = new lexer.Lexer();
+ this.onNewLine = onNewLine;
+ }
+ /**
+ * Parse `source` as a YAML stream.
+ * If `incomplete`, a part of the last line may be left as a buffer for the next call.
+ *
+ * Errors are not thrown, but yielded as `{ type: 'error', message }` tokens.
+ *
+ * @returns A generator of tokens representing each directive, document, and other structure.
+ */
+ *parse(source, incomplete = false) {
+ if (this.onNewLine && this.offset === 0)
+ this.onNewLine(0);
+ for (const lexeme of this.lexer.lex(source, incomplete))
+ yield* this.next(lexeme);
+ if (!incomplete)
+ yield* this.end();
+ }
+ /**
+ * Advance the parser by the `source` of one lexical token.
+ */
+ *next(source) {
+ this.source = source;
+ if (process.env.LOG_TOKENS)
+ console.log('|', cst.prettyToken(source));
+ if (this.atScalar) {
+ this.atScalar = false;
+ yield* this.step();
+ this.offset += source.length;
+ return;
+ }
+ const type = cst.tokenType(source);
+ if (!type) {
+ const message = `Not a YAML token: ${source}`;
+ yield* this.pop({ type: 'error', offset: this.offset, message, source });
+ this.offset += source.length;
+ }
+ else if (type === 'scalar') {
+ this.atNewLine = false;
+ this.atScalar = true;
+ this.type = 'scalar';
+ }
+ else {
+ this.type = type;
+ yield* this.step();
+ switch (type) {
+ case 'newline':
+ this.atNewLine = true;
+ this.indent = 0;
+ if (this.onNewLine)
+ this.onNewLine(this.offset + source.length);
+ break;
+ case 'space':
+ if (this.atNewLine && source[0] === ' ')
+ this.indent += source.length;
+ break;
+ case 'explicit-key-ind':
+ case 'map-value-ind':
+ case 'seq-item-ind':
+ if (this.atNewLine)
+ this.indent += source.length;
+ break;
+ case 'doc-mode':
+ case 'flow-error-end':
+ return;
+ default:
+ this.atNewLine = false;
+ }
+ this.offset += source.length;
+ }
+ }
+ /** Call at end of input to push out any remaining constructions */
+ *end() {
+ while (this.stack.length > 0)
+ yield* this.pop();
+ }
+ get sourceToken() {
+ const st = {
+ type: this.type,
+ offset: this.offset,
+ indent: this.indent,
+ source: this.source
+ };
+ return st;
+ }
+ *step() {
+ const top = this.peek(1);
+ if (this.type === 'doc-end' && (!top || top.type !== 'doc-end')) {
+ while (this.stack.length > 0)
+ yield* this.pop();
+ this.stack.push({
+ type: 'doc-end',
+ offset: this.offset,
+ source: this.source
+ });
+ return;
+ }
+ if (!top)
+ return yield* this.stream();
+ switch (top.type) {
+ case 'document':
+ return yield* this.document(top);
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ return yield* this.scalar(top);
+ case 'block-scalar':
+ return yield* this.blockScalar(top);
+ case 'block-map':
+ return yield* this.blockMap(top);
+ case 'block-seq':
+ return yield* this.blockSequence(top);
+ case 'flow-collection':
+ return yield* this.flowCollection(top);
+ case 'doc-end':
+ return yield* this.documentEnd(top);
+ }
+ /* istanbul ignore next should not happen */
+ yield* this.pop();
+ }
+ peek(n) {
+ return this.stack[this.stack.length - n];
+ }
+ *pop(error) {
+ const token = error ?? this.stack.pop();
+ /* istanbul ignore if should not happen */
+ if (!token) {
+ const message = 'Tried to pop an empty stack';
+ yield { type: 'error', offset: this.offset, source: '', message };
+ }
+ else if (this.stack.length === 0) {
+ yield token;
+ }
+ else {
+ const top = this.peek(1);
+ if (token.type === 'block-scalar') {
+ // Block scalars use their parent rather than header indent
+ token.indent = 'indent' in top ? top.indent : 0;
+ }
+ else if (token.type === 'flow-collection' && top.type === 'document') {
+ // Ignore all indent for top-level flow collections
+ token.indent = 0;
+ }
+ if (token.type === 'flow-collection')
+ fixFlowSeqItems(token);
+ switch (top.type) {
+ case 'document':
+ top.value = token;
+ break;
+ case 'block-scalar':
+ top.props.push(token); // error
+ break;
+ case 'block-map': {
+ const it = top.items[top.items.length - 1];
+ if (it.value) {
+ top.items.push({ start: [], key: token, sep: [] });
+ this.onKeyLine = true;
+ return;
+ }
+ else if (it.sep) {
+ it.value = token;
+ }
+ else {
+ Object.assign(it, { key: token, sep: [] });
+ this.onKeyLine = !includesToken(it.start, 'explicit-key-ind');
+ return;
+ }
+ break;
+ }
+ case 'block-seq': {
+ const it = top.items[top.items.length - 1];
+ if (it.value)
+ top.items.push({ start: [], value: token });
+ else
+ it.value = token;
+ break;
+ }
+ case 'flow-collection': {
+ const it = top.items[top.items.length - 1];
+ if (!it || it.value)
+ top.items.push({ start: [], key: token, sep: [] });
+ else if (it.sep)
+ it.value = token;
+ else
+ Object.assign(it, { key: token, sep: [] });
+ return;
+ }
+ /* istanbul ignore next should not happen */
+ default:
+ yield* this.pop();
+ yield* this.pop(token);
+ }
+ if ((top.type === 'document' ||
+ top.type === 'block-map' ||
+ top.type === 'block-seq') &&
+ (token.type === 'block-map' || token.type === 'block-seq')) {
+ const last = token.items[token.items.length - 1];
+ if (last &&
+ !last.sep &&
+ !last.value &&
+ last.start.length > 0 &&
+ findNonEmptyIndex(last.start) === -1 &&
+ (token.indent === 0 ||
+ last.start.every(st => st.type !== 'comment' || st.indent < token.indent))) {
+ if (top.type === 'document')
+ top.end = last.start;
+ else
+ top.items.push({ start: last.start });
+ token.items.splice(-1, 1);
+ }
+ }
+ }
+ }
+ *stream() {
+ switch (this.type) {
+ case 'directive-line':
+ yield { type: 'directive', offset: this.offset, source: this.source };
+ return;
+ case 'byte-order-mark':
+ case 'space':
+ case 'comment':
+ case 'newline':
+ yield this.sourceToken;
+ return;
+ case 'doc-mode':
+ case 'doc-start': {
+ const doc = {
+ type: 'document',
+ offset: this.offset,
+ start: []
+ };
+ if (this.type === 'doc-start')
+ doc.start.push(this.sourceToken);
+ this.stack.push(doc);
+ return;
+ }
+ }
+ yield {
+ type: 'error',
+ offset: this.offset,
+ message: `Unexpected ${this.type} token in YAML stream`,
+ source: this.source
+ };
+ }
+ *document(doc) {
+ if (doc.value)
+ return yield* this.lineEnd(doc);
+ switch (this.type) {
+ case 'doc-start': {
+ if (findNonEmptyIndex(doc.start) !== -1) {
+ yield* this.pop();
+ yield* this.step();
+ }
+ else
+ doc.start.push(this.sourceToken);
+ return;
+ }
+ case 'anchor':
+ case 'tag':
+ case 'space':
+ case 'comment':
+ case 'newline':
+ doc.start.push(this.sourceToken);
+ return;
+ }
+ const bv = this.startBlockValue(doc);
+ if (bv)
+ this.stack.push(bv);
+ else {
+ yield {
+ type: 'error',
+ offset: this.offset,
+ message: `Unexpected ${this.type} token in YAML document`,
+ source: this.source
+ };
+ }
+ }
+ *scalar(scalar) {
+ if (this.type === 'map-value-ind') {
+ const prev = getPrevProps(this.peek(2));
+ const start = getFirstKeyStartProps(prev);
+ let sep;
+ if (scalar.end) {
+ sep = scalar.end;
+ sep.push(this.sourceToken);
+ delete scalar.end;
+ }
+ else
+ sep = [this.sourceToken];
+ const map = {
+ type: 'block-map',
+ offset: scalar.offset,
+ indent: scalar.indent,
+ items: [{ start, key: scalar, sep }]
+ };
+ this.onKeyLine = true;
+ this.stack[this.stack.length - 1] = map;
+ }
+ else
+ yield* this.lineEnd(scalar);
+ }
+ *blockScalar(scalar) {
+ switch (this.type) {
+ case 'space':
+ case 'comment':
+ case 'newline':
+ scalar.props.push(this.sourceToken);
+ return;
+ case 'scalar':
+ scalar.source = this.source;
+ // block-scalar source includes trailing newline
+ this.atNewLine = true;
+ this.indent = 0;
+ if (this.onNewLine) {
+ let nl = this.source.indexOf('\n') + 1;
+ while (nl !== 0) {
+ this.onNewLine(this.offset + nl);
+ nl = this.source.indexOf('\n', nl) + 1;
+ }
+ }
+ yield* this.pop();
+ break;
+ /* istanbul ignore next should not happen */
+ default:
+ yield* this.pop();
+ yield* this.step();
+ }
+ }
+ *blockMap(map) {
+ const it = map.items[map.items.length - 1];
+ // it.sep is true-ish if pair already has key or : separator
+ switch (this.type) {
+ case 'newline':
+ this.onKeyLine = false;
+ if (it.value) {
+ const end = 'end' in it.value ? it.value.end : undefined;
+ const last = Array.isArray(end) ? end[end.length - 1] : undefined;
+ if (last?.type === 'comment')
+ end?.push(this.sourceToken);
+ else
+ map.items.push({ start: [this.sourceToken] });
+ }
+ else if (it.sep) {
+ it.sep.push(this.sourceToken);
+ }
+ else {
+ it.start.push(this.sourceToken);
+ }
+ return;
+ case 'space':
+ case 'comment':
+ if (it.value) {
+ map.items.push({ start: [this.sourceToken] });
+ }
+ else if (it.sep) {
+ it.sep.push(this.sourceToken);
+ }
+ else {
+ if (this.atIndentedComment(it.start, map.indent)) {
+ const prev = map.items[map.items.length - 2];
+ const end = prev?.value?.end;
+ if (Array.isArray(end)) {
+ Array.prototype.push.apply(end, it.start);
+ end.push(this.sourceToken);
+ map.items.pop();
+ return;
+ }
+ }
+ it.start.push(this.sourceToken);
+ }
+ return;
+ }
+ if (this.indent >= map.indent) {
+ const atNextItem = !this.onKeyLine && this.indent === map.indent && it.sep;
+ // For empty nodes, assign newline-separated not indented empty tokens to following node
+ let start = [];
+ if (atNextItem && it.sep && !it.value) {
+ const nl = [];
+ for (let i = 0; i < it.sep.length; ++i) {
+ const st = it.sep[i];
+ switch (st.type) {
+ case 'newline':
+ nl.push(i);
+ break;
+ case 'space':
+ break;
+ case 'comment':
+ if (st.indent > map.indent)
+ nl.length = 0;
+ break;
+ default:
+ nl.length = 0;
+ }
+ }
+ if (nl.length >= 2)
+ start = it.sep.splice(nl[1]);
+ }
+ switch (this.type) {
+ case 'anchor':
+ case 'tag':
+ if (atNextItem || it.value) {
+ start.push(this.sourceToken);
+ map.items.push({ start });
+ this.onKeyLine = true;
+ }
+ else if (it.sep) {
+ it.sep.push(this.sourceToken);
+ }
+ else {
+ it.start.push(this.sourceToken);
+ }
+ return;
+ case 'explicit-key-ind':
+ if (!it.sep && !includesToken(it.start, 'explicit-key-ind')) {
+ it.start.push(this.sourceToken);
+ }
+ else if (atNextItem || it.value) {
+ start.push(this.sourceToken);
+ map.items.push({ start });
+ }
+ else {
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start: [this.sourceToken] }]
+ });
+ }
+ this.onKeyLine = true;
+ return;
+ case 'map-value-ind':
+ if (includesToken(it.start, 'explicit-key-ind')) {
+ if (!it.sep) {
+ if (includesToken(it.start, 'newline')) {
+ Object.assign(it, { key: null, sep: [this.sourceToken] });
+ }
+ else {
+ const start = getFirstKeyStartProps(it.start);
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start, key: null, sep: [this.sourceToken] }]
+ });
+ }
+ }
+ else if (it.value) {
+ map.items.push({ start: [], key: null, sep: [this.sourceToken] });
+ }
+ else if (includesToken(it.sep, 'map-value-ind')) {
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start, key: null, sep: [this.sourceToken] }]
+ });
+ }
+ else if (isFlowToken(it.key) &&
+ !includesToken(it.sep, 'newline')) {
+ const start = getFirstKeyStartProps(it.start);
+ const key = it.key;
+ const sep = it.sep;
+ sep.push(this.sourceToken);
+ // @ts-expect-error type guard is wrong here
+ delete it.key, delete it.sep;
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start, key, sep }]
+ });
+ }
+ else if (start.length > 0) {
+ // Not actually at next item
+ it.sep = it.sep.concat(start, this.sourceToken);
+ }
+ else {
+ it.sep.push(this.sourceToken);
+ }
+ }
+ else {
+ if (!it.sep) {
+ Object.assign(it, { key: null, sep: [this.sourceToken] });
+ }
+ else if (it.value || atNextItem) {
+ map.items.push({ start, key: null, sep: [this.sourceToken] });
+ }
+ else if (includesToken(it.sep, 'map-value-ind')) {
+ this.stack.push({
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start: [], key: null, sep: [this.sourceToken] }]
+ });
+ }
+ else {
+ it.sep.push(this.sourceToken);
+ }
+ }
+ this.onKeyLine = true;
+ return;
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar': {
+ const fs = this.flowScalar(this.type);
+ if (atNextItem || it.value) {
+ map.items.push({ start, key: fs, sep: [] });
+ this.onKeyLine = true;
+ }
+ else if (it.sep) {
+ this.stack.push(fs);
+ }
+ else {
+ Object.assign(it, { key: fs, sep: [] });
+ this.onKeyLine = true;
+ }
+ return;
+ }
+ default: {
+ const bv = this.startBlockValue(map);
+ if (bv) {
+ if (atNextItem &&
+ bv.type !== 'block-seq' &&
+ includesToken(it.start, 'explicit-key-ind')) {
+ map.items.push({ start });
+ }
+ this.stack.push(bv);
+ return;
+ }
+ }
+ }
+ }
+ yield* this.pop();
+ yield* this.step();
+ }
+ *blockSequence(seq) {
+ const it = seq.items[seq.items.length - 1];
+ switch (this.type) {
+ case 'newline':
+ if (it.value) {
+ const end = 'end' in it.value ? it.value.end : undefined;
+ const last = Array.isArray(end) ? end[end.length - 1] : undefined;
+ if (last?.type === 'comment')
+ end?.push(this.sourceToken);
+ else
+ seq.items.push({ start: [this.sourceToken] });
+ }
+ else
+ it.start.push(this.sourceToken);
+ return;
+ case 'space':
+ case 'comment':
+ if (it.value)
+ seq.items.push({ start: [this.sourceToken] });
+ else {
+ if (this.atIndentedComment(it.start, seq.indent)) {
+ const prev = seq.items[seq.items.length - 2];
+ const end = prev?.value?.end;
+ if (Array.isArray(end)) {
+ Array.prototype.push.apply(end, it.start);
+ end.push(this.sourceToken);
+ seq.items.pop();
+ return;
+ }
+ }
+ it.start.push(this.sourceToken);
+ }
+ return;
+ case 'anchor':
+ case 'tag':
+ if (it.value || this.indent <= seq.indent)
+ break;
+ it.start.push(this.sourceToken);
+ return;
+ case 'seq-item-ind':
+ if (this.indent !== seq.indent)
+ break;
+ if (it.value || includesToken(it.start, 'seq-item-ind'))
+ seq.items.push({ start: [this.sourceToken] });
+ else
+ it.start.push(this.sourceToken);
+ return;
+ }
+ if (this.indent > seq.indent) {
+ const bv = this.startBlockValue(seq);
+ if (bv) {
+ this.stack.push(bv);
+ return;
+ }
+ }
+ yield* this.pop();
+ yield* this.step();
+ }
+ *flowCollection(fc) {
+ const it = fc.items[fc.items.length - 1];
+ if (this.type === 'flow-error-end') {
+ let top;
+ do {
+ yield* this.pop();
+ top = this.peek(1);
+ } while (top && top.type === 'flow-collection');
+ }
+ else if (fc.end.length === 0) {
+ switch (this.type) {
+ case 'comma':
+ case 'explicit-key-ind':
+ if (!it || it.sep)
+ fc.items.push({ start: [this.sourceToken] });
+ else
+ it.start.push(this.sourceToken);
+ return;
+ case 'map-value-ind':
+ if (!it || it.value)
+ fc.items.push({ start: [], key: null, sep: [this.sourceToken] });
+ else if (it.sep)
+ it.sep.push(this.sourceToken);
+ else
+ Object.assign(it, { key: null, sep: [this.sourceToken] });
+ return;
+ case 'space':
+ case 'comment':
+ case 'newline':
+ case 'anchor':
+ case 'tag':
+ if (!it || it.value)
+ fc.items.push({ start: [this.sourceToken] });
+ else if (it.sep)
+ it.sep.push(this.sourceToken);
+ else
+ it.start.push(this.sourceToken);
+ return;
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar': {
+ const fs = this.flowScalar(this.type);
+ if (!it || it.value)
+ fc.items.push({ start: [], key: fs, sep: [] });
+ else if (it.sep)
+ this.stack.push(fs);
+ else
+ Object.assign(it, { key: fs, sep: [] });
+ return;
+ }
+ case 'flow-map-end':
+ case 'flow-seq-end':
+ fc.end.push(this.sourceToken);
+ return;
+ }
+ const bv = this.startBlockValue(fc);
+ /* istanbul ignore else should not happen */
+ if (bv)
+ this.stack.push(bv);
+ else {
+ yield* this.pop();
+ yield* this.step();
+ }
+ }
+ else {
+ const parent = this.peek(2);
+ if (parent.type === 'block-map' &&
+ ((this.type === 'map-value-ind' && parent.indent === fc.indent) ||
+ (this.type === 'newline' &&
+ !parent.items[parent.items.length - 1].sep))) {
+ yield* this.pop();
+ yield* this.step();
+ }
+ else if (this.type === 'map-value-ind' &&
+ parent.type !== 'flow-collection') {
+ const prev = getPrevProps(parent);
+ const start = getFirstKeyStartProps(prev);
+ fixFlowSeqItems(fc);
+ const sep = fc.end.splice(1, fc.end.length);
+ sep.push(this.sourceToken);
+ const map = {
+ type: 'block-map',
+ offset: fc.offset,
+ indent: fc.indent,
+ items: [{ start, key: fc, sep }]
+ };
+ this.onKeyLine = true;
+ this.stack[this.stack.length - 1] = map;
+ }
+ else {
+ yield* this.lineEnd(fc);
+ }
+ }
+ }
+ flowScalar(type) {
+ if (this.onNewLine) {
+ let nl = this.source.indexOf('\n') + 1;
+ while (nl !== 0) {
+ this.onNewLine(this.offset + nl);
+ nl = this.source.indexOf('\n', nl) + 1;
+ }
+ }
+ return {
+ type,
+ offset: this.offset,
+ indent: this.indent,
+ source: this.source
+ };
+ }
+ startBlockValue(parent) {
+ switch (this.type) {
+ case 'alias':
+ case 'scalar':
+ case 'single-quoted-scalar':
+ case 'double-quoted-scalar':
+ return this.flowScalar(this.type);
+ case 'block-scalar-header':
+ return {
+ type: 'block-scalar',
+ offset: this.offset,
+ indent: this.indent,
+ props: [this.sourceToken],
+ source: ''
+ };
+ case 'flow-map-start':
+ case 'flow-seq-start':
+ return {
+ type: 'flow-collection',
+ offset: this.offset,
+ indent: this.indent,
+ start: this.sourceToken,
+ items: [],
+ end: []
+ };
+ case 'seq-item-ind':
+ return {
+ type: 'block-seq',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start: [this.sourceToken] }]
+ };
+ case 'explicit-key-ind': {
+ this.onKeyLine = true;
+ const prev = getPrevProps(parent);
+ const start = getFirstKeyStartProps(prev);
+ start.push(this.sourceToken);
+ return {
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start }]
+ };
+ }
+ case 'map-value-ind': {
+ this.onKeyLine = true;
+ const prev = getPrevProps(parent);
+ const start = getFirstKeyStartProps(prev);
+ return {
+ type: 'block-map',
+ offset: this.offset,
+ indent: this.indent,
+ items: [{ start, key: null, sep: [this.sourceToken] }]
+ };
+ }
+ }
+ return null;
+ }
+ atIndentedComment(start, indent) {
+ if (this.type !== 'comment')
+ return false;
+ if (this.indent <= indent)
+ return false;
+ return start.every(st => st.type === 'newline' || st.type === 'space');
+ }
+ *documentEnd(docEnd) {
+ if (this.type !== 'doc-mode') {
+ if (docEnd.end)
+ docEnd.end.push(this.sourceToken);
+ else
+ docEnd.end = [this.sourceToken];
+ if (this.type === 'newline')
+ yield* this.pop();
+ }
+ }
+ *lineEnd(token) {
+ switch (this.type) {
+ case 'comma':
+ case 'doc-start':
+ case 'doc-end':
+ case 'flow-seq-end':
+ case 'flow-map-end':
+ case 'map-value-ind':
+ yield* this.pop();
+ yield* this.step();
+ break;
+ case 'newline':
+ this.onKeyLine = false;
+ // fallthrough
+ case 'space':
+ case 'comment':
+ default:
+ // all other values are errors
+ if (token.end)
+ token.end.push(this.sourceToken);
+ else
+ token.end = [this.sourceToken];
+ if (this.type === 'newline')
+ yield* this.pop();
+ }
+ }
+}
+
+exports.Parser = Parser;
diff --git a/MistyCore/node_modules/yaml/dist/public-api.d.ts b/MistyCore/node_modules/yaml/dist/public-api.d.ts
new file mode 100644
index 0000000..82a4d4f
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/public-api.d.ts
@@ -0,0 +1,43 @@
+import { Composer } from './compose/composer.js';
+import type { Reviver } from './doc/applyReviver.js';
+import { Document, Replacer } from './doc/Document.js';
+import type { ParsedNode } from './nodes/Node.js';
+import type { CreateNodeOptions, DocumentOptions, ParseOptions, SchemaOptions, ToJSOptions, ToStringOptions } from './options.js';
+export interface EmptyStream extends Array<Document.Parsed>, ReturnType<Composer['streamInfo']> {
+ empty: true;
+}
+/**
+ * Parse the input as a stream of YAML documents.
+ *
+ * Documents should be separated from each other by `...` or `---` marker lines.
+ *
+ * @returns If an empty `docs` array is returned, it will be of type
+ * EmptyStream and contain additional stream information. In
+ * TypeScript, you should use `'empty' in docs` as a type guard for it.
+ */
+export declare function parseAllDocuments<T extends ParsedNode = ParsedNode>(source: string, options?: ParseOptions & DocumentOptions & SchemaOptions): Document.Parsed<T>[] | EmptyStream;
+/** Parse an input string into a single YAML.Document */
+export declare function parseDocument<T extends ParsedNode = ParsedNode>(source: string, options?: ParseOptions & DocumentOptions & SchemaOptions): Document.Parsed<T>;
+/**
+ * Parse an input string into JavaScript.
+ *
+ * Only supports input consisting of a single YAML document; for multi-document
+ * support you should use `YAML.parseAllDocuments`. May throw on error, and may
+ * log warnings using `console.warn`.
+ *
+ * @param str - A string with YAML formatting.
+ * @param reviver - A reviver function, as in `JSON.parse()`
+ * @returns The value will match the type of the root value of the parsed YAML
+ * document, so Maps become objects, Sequences arrays, and scalars result in
+ * nulls, booleans, numbers and strings.
+ */
+export declare function parse(src: string, options?: ParseOptions & DocumentOptions & SchemaOptions & ToJSOptions): any;
+export declare function parse(src: string, reviver: Reviver, options?: ParseOptions & DocumentOptions & SchemaOptions & ToJSOptions): any;
+/**
+ * Stringify a value as a YAML document.
+ *
+ * @param replacer - A replacer array or function, as in `JSON.stringify()`
+ * @returns Will always include `\n` as the last character, as is expected of YAML documents.
+ */
+export declare function stringify(value: any, options?: DocumentOptions & SchemaOptions & ParseOptions & CreateNodeOptions & ToStringOptions): string;
+export declare function stringify(value: any, replacer?: Replacer | null, options?: string | number | (DocumentOptions & SchemaOptions & ParseOptions & CreateNodeOptions & ToStringOptions)): string;
diff --git a/MistyCore/node_modules/yaml/dist/public-api.js b/MistyCore/node_modules/yaml/dist/public-api.js
new file mode 100644
index 0000000..38aad92
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/public-api.js
@@ -0,0 +1,104 @@
+'use strict';
+
+var composer = require('./compose/composer.js');
+var Document = require('./doc/Document.js');
+var errors = require('./errors.js');
+var log = require('./log.js');
+var lineCounter = require('./parse/line-counter.js');
+var parser = require('./parse/parser.js');
+
+function parseOptions(options) {
+ const prettyErrors = options.prettyErrors !== false;
+ const lineCounter$1 = options.lineCounter || (prettyErrors && new lineCounter.LineCounter()) || null;
+ return { lineCounter: lineCounter$1, prettyErrors };
+}
+/**
+ * Parse the input as a stream of YAML documents.
+ *
+ * Documents should be separated from each other by `...` or `---` marker lines.
+ *
+ * @returns If an empty `docs` array is returned, it will be of type
+ * EmptyStream and contain additional stream information. In
+ * TypeScript, you should use `'empty' in docs` as a type guard for it.
+ */
+function parseAllDocuments(source, options = {}) {
+ const { lineCounter, prettyErrors } = parseOptions(options);
+ const parser$1 = new parser.Parser(lineCounter?.addNewLine);
+ const composer$1 = new composer.Composer(options);
+ const docs = Array.from(composer$1.compose(parser$1.parse(source)));
+ if (prettyErrors && lineCounter)
+ for (const doc of docs) {
+ doc.errors.forEach(errors.prettifyError(source, lineCounter));
+ doc.warnings.forEach(errors.prettifyError(source, lineCounter));
+ }
+ if (docs.length > 0)
+ return docs;
+ return Object.assign([], { empty: true }, composer$1.streamInfo());
+}
+/** Parse an input string into a single YAML.Document */
+function parseDocument(source, options = {}) {
+ const { lineCounter, prettyErrors } = parseOptions(options);
+ const parser$1 = new parser.Parser(lineCounter?.addNewLine);
+ const composer$1 = new composer.Composer(options);
+ // `doc` is always set by compose.end(true) at the very latest
+ let doc = null;
+ for (const _doc of composer$1.compose(parser$1.parse(source), true, source.length)) {
+ if (!doc)
+ doc = _doc;
+ else if (doc.options.logLevel !== 'silent') {
+ doc.errors.push(new errors.YAMLParseError(_doc.range.slice(0, 2), 'MULTIPLE_DOCS', 'Source contains multiple documents; please use YAML.parseAllDocuments()'));
+ break;
+ }
+ }
+ if (prettyErrors && lineCounter) {
+ doc.errors.forEach(errors.prettifyError(source, lineCounter));
+ doc.warnings.forEach(errors.prettifyError(source, lineCounter));
+ }
+ return doc;
+}
+function parse(src, reviver, options) {
+ let _reviver = undefined;
+ if (typeof reviver === 'function') {
+ _reviver = reviver;
+ }
+ else if (options === undefined && reviver && typeof reviver === 'object') {
+ options = reviver;
+ }
+ const doc = parseDocument(src, options);
+ if (!doc)
+ return null;
+ doc.warnings.forEach(warning => log.warn(doc.options.logLevel, warning));
+ if (doc.errors.length > 0) {
+ if (doc.options.logLevel !== 'silent')
+ throw doc.errors[0];
+ else
+ doc.errors = [];
+ }
+ return doc.toJS(Object.assign({ reviver: _reviver }, options));
+}
+function stringify(value, replacer, options) {
+ let _replacer = null;
+ if (typeof replacer === 'function' || Array.isArray(replacer)) {
+ _replacer = replacer;
+ }
+ else if (options === undefined && replacer) {
+ options = replacer;
+ }
+ if (typeof options === 'string')
+ options = options.length;
+ if (typeof options === 'number') {
+ const indent = Math.round(options);
+ options = indent < 1 ? undefined : indent > 8 ? { indent: 8 } : { indent };
+ }
+ if (value === undefined) {
+ const { keepUndefined } = options ?? replacer ?? {};
+ if (!keepUndefined)
+ return undefined;
+ }
+ return new Document.Document(value, _replacer, options).toString(options);
+}
+
+exports.parse = parse;
+exports.parseAllDocuments = parseAllDocuments;
+exports.parseDocument = parseDocument;
+exports.stringify = stringify;
diff --git a/MistyCore/node_modules/yaml/dist/schema/Schema.d.ts b/MistyCore/node_modules/yaml/dist/schema/Schema.d.ts
new file mode 100644
index 0000000..0d53d5b
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/Schema.d.ts
@@ -0,0 +1,18 @@
+import { MAP, SCALAR, SEQ } from '../nodes/Node.js';
+import type { Pair } from '../nodes/Pair.js';
+import type { SchemaOptions, ToStringOptions } from '../options.js';
+import type { CollectionTag, ScalarTag } from './types.js';
+export declare class Schema {
+ compat: Array<CollectionTag | ScalarTag> | null;
+ knownTags: Record<string, CollectionTag | ScalarTag>;
+ merge: boolean;
+ name: string;
+ sortMapEntries: ((a: Pair, b: Pair) => number) | null;
+ tags: Array<CollectionTag | ScalarTag>;
+ toStringOptions: Readonly<ToStringOptions> | null;
+ readonly [MAP]: CollectionTag;
+ readonly [SCALAR]: ScalarTag;
+ readonly [SEQ]: CollectionTag;
+ constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }: SchemaOptions);
+ clone(): Schema;
+}
diff --git a/MistyCore/node_modules/yaml/dist/schema/Schema.js b/MistyCore/node_modules/yaml/dist/schema/Schema.js
new file mode 100644
index 0000000..f31b1a9
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/Schema.js
@@ -0,0 +1,40 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+var map = require('./common/map.js');
+var seq = require('./common/seq.js');
+var string = require('./common/string.js');
+var tags = require('./tags.js');
+
+const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
+class Schema {
+ constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }) {
+ this.compat = Array.isArray(compat)
+ ? tags.getTags(compat, 'compat')
+ : compat
+ ? tags.getTags(null, compat)
+ : null;
+ this.merge = !!merge;
+ this.name = (typeof schema === 'string' && schema) || 'core';
+ this.knownTags = resolveKnownTags ? tags.coreKnownTags : {};
+ this.tags = tags.getTags(customTags, this.name);
+ this.toStringOptions = toStringDefaults ?? null;
+ Object.defineProperty(this, Node.MAP, { value: map.map });
+ Object.defineProperty(this, Node.SCALAR, { value: string.string });
+ Object.defineProperty(this, Node.SEQ, { value: seq.seq });
+ // Used by createMap()
+ this.sortMapEntries =
+ typeof sortMapEntries === 'function'
+ ? sortMapEntries
+ : sortMapEntries === true
+ ? sortMapEntriesByKey
+ : null;
+ }
+ clone() {
+ const copy = Object.create(Schema.prototype, Object.getOwnPropertyDescriptors(this));
+ copy.tags = this.tags.slice();
+ return copy;
+ }
+}
+
+exports.Schema = Schema;
diff --git a/MistyCore/node_modules/yaml/dist/schema/common/map.d.ts b/MistyCore/node_modules/yaml/dist/schema/common/map.d.ts
new file mode 100644
index 0000000..9b300f8
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/common/map.d.ts
@@ -0,0 +1,2 @@
+import type { CollectionTag } from '../types.js';
+export declare const map: CollectionTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/common/map.js b/MistyCore/node_modules/yaml/dist/schema/common/map.js
new file mode 100644
index 0000000..46dab3c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/common/map.js
@@ -0,0 +1,44 @@
+'use strict';
+
+var Node = require('../../nodes/Node.js');
+var Pair = require('../../nodes/Pair.js');
+var YAMLMap = require('../../nodes/YAMLMap.js');
+
+function createMap(schema, obj, ctx) {
+ const { keepUndefined, replacer } = ctx;
+ const map = new YAMLMap.YAMLMap(schema);
+ const add = (key, value) => {
+ if (typeof replacer === 'function')
+ value = replacer.call(obj, key, value);
+ else if (Array.isArray(replacer) && !replacer.includes(key))
+ return;
+ if (value !== undefined || keepUndefined)
+ map.items.push(Pair.createPair(key, value, ctx));
+ };
+ if (obj instanceof Map) {
+ for (const [key, value] of obj)
+ add(key, value);
+ }
+ else if (obj && typeof obj === 'object') {
+ for (const key of Object.keys(obj))
+ add(key, obj[key]);
+ }
+ if (typeof schema.sortMapEntries === 'function') {
+ map.items.sort(schema.sortMapEntries);
+ }
+ return map;
+}
+const map = {
+ collection: 'map',
+ createNode: createMap,
+ default: true,
+ nodeClass: YAMLMap.YAMLMap,
+ tag: 'tag:yaml.org,2002:map',
+ resolve(map, onError) {
+ if (!Node.isMap(map))
+ onError('Expected a mapping for this tag');
+ return map;
+ }
+};
+
+exports.map = map;
diff --git a/MistyCore/node_modules/yaml/dist/schema/common/null.d.ts b/MistyCore/node_modules/yaml/dist/schema/common/null.d.ts
new file mode 100644
index 0000000..66abea5
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/common/null.d.ts
@@ -0,0 +1,4 @@
+import type { ScalarTag } from '../types.js';
+export declare const nullTag: ScalarTag & {
+ test: RegExp;
+};
diff --git a/MistyCore/node_modules/yaml/dist/schema/common/null.js b/MistyCore/node_modules/yaml/dist/schema/common/null.js
new file mode 100644
index 0000000..cb353a7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/common/null.js
@@ -0,0 +1,17 @@
+'use strict';
+
+var Scalar = require('../../nodes/Scalar.js');
+
+const nullTag = {
+ identify: value => value == null,
+ createNode: () => new Scalar.Scalar(null),
+ default: true,
+ tag: 'tag:yaml.org,2002:null',
+ test: /^(?:~|[Nn]ull|NULL)?$/,
+ resolve: () => new Scalar.Scalar(null),
+ stringify: ({ source }, ctx) => typeof source === 'string' && nullTag.test.test(source)
+ ? source
+ : ctx.options.nullStr
+};
+
+exports.nullTag = nullTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/common/seq.d.ts b/MistyCore/node_modules/yaml/dist/schema/common/seq.d.ts
new file mode 100644
index 0000000..c038d30
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/common/seq.d.ts
@@ -0,0 +1,2 @@
+import type { CollectionTag } from '../types.js';
+export declare const seq: CollectionTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/common/seq.js b/MistyCore/node_modules/yaml/dist/schema/common/seq.js
new file mode 100644
index 0000000..0c48bde
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/common/seq.js
@@ -0,0 +1,35 @@
+'use strict';
+
+var createNode = require('../../doc/createNode.js');
+var Node = require('../../nodes/Node.js');
+var YAMLSeq = require('../../nodes/YAMLSeq.js');
+
+function createSeq(schema, obj, ctx) {
+ const { replacer } = ctx;
+ const seq = new YAMLSeq.YAMLSeq(schema);
+ if (obj && Symbol.iterator in Object(obj)) {
+ let i = 0;
+ for (let it of obj) {
+ if (typeof replacer === 'function') {
+ const key = obj instanceof Set ? it : String(i++);
+ it = replacer.call(obj, key, it);
+ }
+ seq.items.push(createNode.createNode(it, undefined, ctx));
+ }
+ }
+ return seq;
+}
+const seq = {
+ collection: 'seq',
+ createNode: createSeq,
+ default: true,
+ nodeClass: YAMLSeq.YAMLSeq,
+ tag: 'tag:yaml.org,2002:seq',
+ resolve(seq, onError) {
+ if (!Node.isSeq(seq))
+ onError('Expected a sequence for this tag');
+ return seq;
+ }
+};
+
+exports.seq = seq;
diff --git a/MistyCore/node_modules/yaml/dist/schema/common/string.d.ts b/MistyCore/node_modules/yaml/dist/schema/common/string.d.ts
new file mode 100644
index 0000000..539c9b1
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/common/string.d.ts
@@ -0,0 +1,2 @@
+import type { ScalarTag } from '../types.js';
+export declare const string: ScalarTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/common/string.js b/MistyCore/node_modules/yaml/dist/schema/common/string.js
new file mode 100644
index 0000000..7601420
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/common/string.js
@@ -0,0 +1,16 @@
+'use strict';
+
+var stringifyString = require('../../stringify/stringifyString.js');
+
+const string = {
+ identify: value => typeof value === 'string',
+ default: true,
+ tag: 'tag:yaml.org,2002:str',
+ resolve: str => str,
+ stringify(item, ctx, onComment, onChompKeep) {
+ ctx = Object.assign({ actualString: true }, ctx);
+ return stringifyString.stringifyString(item, ctx, onComment, onChompKeep);
+ }
+};
+
+exports.string = string;
diff --git a/MistyCore/node_modules/yaml/dist/schema/core/bool.d.ts b/MistyCore/node_modules/yaml/dist/schema/core/bool.d.ts
new file mode 100644
index 0000000..e4bdc4c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/core/bool.d.ts
@@ -0,0 +1,4 @@
+import type { ScalarTag } from '../types.js';
+export declare const boolTag: ScalarTag & {
+ test: RegExp;
+};
diff --git a/MistyCore/node_modules/yaml/dist/schema/core/bool.js b/MistyCore/node_modules/yaml/dist/schema/core/bool.js
new file mode 100644
index 0000000..4def73c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/core/bool.js
@@ -0,0 +1,21 @@
+'use strict';
+
+var Scalar = require('../../nodes/Scalar.js');
+
+const boolTag = {
+ identify: value => typeof value === 'boolean',
+ default: true,
+ tag: 'tag:yaml.org,2002:bool',
+ test: /^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,
+ resolve: str => new Scalar.Scalar(str[0] === 't' || str[0] === 'T'),
+ stringify({ source, value }, ctx) {
+ if (source && boolTag.test.test(source)) {
+ const sv = source[0] === 't' || source[0] === 'T';
+ if (value === sv)
+ return source;
+ }
+ return value ? ctx.options.trueStr : ctx.options.falseStr;
+ }
+};
+
+exports.boolTag = boolTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/core/float.d.ts b/MistyCore/node_modules/yaml/dist/schema/core/float.d.ts
new file mode 100644
index 0000000..22f0249
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/core/float.d.ts
@@ -0,0 +1,4 @@
+import type { ScalarTag } from '../types.js';
+export declare const floatNaN: ScalarTag;
+export declare const floatExp: ScalarTag;
+export declare const float: ScalarTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/core/float.js b/MistyCore/node_modules/yaml/dist/schema/core/float.js
new file mode 100644
index 0000000..a1c96dd
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/core/float.js
@@ -0,0 +1,47 @@
+'use strict';
+
+var Scalar = require('../../nodes/Scalar.js');
+var stringifyNumber = require('../../stringify/stringifyNumber.js');
+
+const floatNaN = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^(?:[-+]?\.(?:inf|Inf|INF|nan|NaN|NAN))$/,
+ resolve: str => str.slice(-3).toLowerCase() === 'nan'
+ ? NaN
+ : str[0] === '-'
+ ? Number.NEGATIVE_INFINITY
+ : Number.POSITIVE_INFINITY,
+ stringify: stringifyNumber.stringifyNumber
+};
+const floatExp = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ format: 'EXP',
+ test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
+ resolve: str => parseFloat(str),
+ stringify(node) {
+ const num = Number(node.value);
+ return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node);
+ }
+};
+const float = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,
+ resolve(str) {
+ const node = new Scalar.Scalar(parseFloat(str));
+ const dot = str.indexOf('.');
+ if (dot !== -1 && str[str.length - 1] === '0')
+ node.minFractionDigits = str.length - dot - 1;
+ return node;
+ },
+ stringify: stringifyNumber.stringifyNumber
+};
+
+exports.float = float;
+exports.floatExp = floatExp;
+exports.floatNaN = floatNaN;
diff --git a/MistyCore/node_modules/yaml/dist/schema/core/int.d.ts b/MistyCore/node_modules/yaml/dist/schema/core/int.d.ts
new file mode 100644
index 0000000..35e2d4b
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/core/int.d.ts
@@ -0,0 +1,4 @@
+import type { ScalarTag } from '../types.js';
+export declare const intOct: ScalarTag;
+export declare const int: ScalarTag;
+export declare const intHex: ScalarTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/core/int.js b/MistyCore/node_modules/yaml/dist/schema/core/int.js
new file mode 100644
index 0000000..fe4c9ca
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/core/int.js
@@ -0,0 +1,42 @@
+'use strict';
+
+var stringifyNumber = require('../../stringify/stringifyNumber.js');
+
+const intIdentify = (value) => typeof value === 'bigint' || Number.isInteger(value);
+const intResolve = (str, offset, radix, { intAsBigInt }) => (intAsBigInt ? BigInt(str) : parseInt(str.substring(offset), radix));
+function intStringify(node, radix, prefix) {
+ const { value } = node;
+ if (intIdentify(value) && value >= 0)
+ return prefix + value.toString(radix);
+ return stringifyNumber.stringifyNumber(node);
+}
+const intOct = {
+ identify: value => intIdentify(value) && value >= 0,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'OCT',
+ test: /^0o[0-7]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 2, 8, opt),
+ stringify: node => intStringify(node, 8, '0o')
+};
+const int = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ test: /^[-+]?[0-9]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
+ stringify: stringifyNumber.stringifyNumber
+};
+const intHex = {
+ identify: value => intIdentify(value) && value >= 0,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'HEX',
+ test: /^0x[0-9a-fA-F]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
+ stringify: node => intStringify(node, 16, '0x')
+};
+
+exports.int = int;
+exports.intHex = intHex;
+exports.intOct = intOct;
diff --git a/MistyCore/node_modules/yaml/dist/schema/core/schema.d.ts b/MistyCore/node_modules/yaml/dist/schema/core/schema.d.ts
new file mode 100644
index 0000000..7663949
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/core/schema.d.ts
@@ -0,0 +1 @@
+export declare const schema: (import("../types.js").ScalarTag | import("../types.js").CollectionTag)[];
diff --git a/MistyCore/node_modules/yaml/dist/schema/core/schema.js b/MistyCore/node_modules/yaml/dist/schema/core/schema.js
new file mode 100644
index 0000000..6ab87f2
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/core/schema.js
@@ -0,0 +1,25 @@
+'use strict';
+
+var map = require('../common/map.js');
+var _null = require('../common/null.js');
+var seq = require('../common/seq.js');
+var string = require('../common/string.js');
+var bool = require('./bool.js');
+var float = require('./float.js');
+var int = require('./int.js');
+
+const schema = [
+ map.map,
+ seq.seq,
+ string.string,
+ _null.nullTag,
+ bool.boolTag,
+ int.intOct,
+ int.int,
+ int.intHex,
+ float.floatNaN,
+ float.floatExp,
+ float.float
+];
+
+exports.schema = schema;
diff --git a/MistyCore/node_modules/yaml/dist/schema/json-schema.d.ts b/MistyCore/node_modules/yaml/dist/schema/json-schema.d.ts
new file mode 100644
index 0000000..20b005d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/json-schema.d.ts
@@ -0,0 +1,69 @@
+declare type JsonSchema = boolean | ArraySchema | ObjectSchema | NumberSchema | StringSchema;
+declare type JsonType = 'array' | 'object' | 'string' | 'number' | 'integer' | 'boolean' | 'null';
+interface CommonSchema {
+ type?: JsonType | JsonType[];
+ const?: unknown;
+ enum?: unknown[];
+ format?: string;
+ allOf?: JsonSchema[];
+ anyOf?: JsonSchema[];
+ oneOf?: JsonSchema[];
+ not?: JsonSchema;
+ if?: JsonSchema;
+ then?: JsonSchema;
+ else?: JsonSchema;
+ $id?: string;
+ $defs?: Record<string, JsonSchema>;
+ $anchor?: string;
+ $dynamicAnchor?: string;
+ $ref?: string;
+ $dynamicRef?: string;
+ $schema?: string;
+ $vocabulary?: Record<string, boolean>;
+ $comment?: string;
+ default?: unknown;
+ deprecated?: boolean;
+ readOnly?: boolean;
+ writeOnly?: boolean;
+ title?: string;
+ description?: string;
+ examples?: unknown[];
+}
+interface ArraySchema extends CommonSchema {
+ prefixItems?: JsonSchema[];
+ items?: JsonSchema;
+ contains?: JsonSchema;
+ unevaluatedItems?: JsonSchema;
+ maxItems?: number;
+ minItems?: number;
+ uniqueItems?: boolean;
+ maxContains?: number;
+ minContains?: number;
+}
+interface ObjectSchema extends CommonSchema {
+ properties?: Record<string, JsonSchema>;
+ patternProperties?: Record<string, JsonSchema>;
+ additionalProperties?: JsonSchema;
+ propertyNames?: JsonSchema;
+ unevaluatedProperties?: JsonSchema;
+ maxProperties?: number;
+ minProperties?: number;
+ required?: string[];
+ dependentRequired?: Record<string, string[]>;
+ dependentSchemas?: Record<string, JsonSchema>;
+}
+interface StringSchema extends CommonSchema {
+ maxLength?: number;
+ minLength?: number;
+ patter?: string;
+ contentEncoding?: string;
+ contentMediaType?: string;
+ contentSchema?: JsonSchema;
+}
+interface NumberSchema extends CommonSchema {
+ multipleOf?: number;
+ maximum?: number;
+ exclusiveMaximum?: number;
+ minimum?: number;
+ exclusiveMinimum?: number;
+}
diff --git a/MistyCore/node_modules/yaml/dist/schema/json/schema.d.ts b/MistyCore/node_modules/yaml/dist/schema/json/schema.d.ts
new file mode 100644
index 0000000..a166ca2
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/json/schema.d.ts
@@ -0,0 +1,2 @@
+import { CollectionTag, ScalarTag } from '../types.js';
+export declare const schema: (ScalarTag | CollectionTag)[];
diff --git a/MistyCore/node_modules/yaml/dist/schema/json/schema.js b/MistyCore/node_modules/yaml/dist/schema/json/schema.js
new file mode 100644
index 0000000..31d0b4d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/json/schema.js
@@ -0,0 +1,64 @@
+'use strict';
+
+var Scalar = require('../../nodes/Scalar.js');
+var map = require('../common/map.js');
+var seq = require('../common/seq.js');
+
+function intIdentify(value) {
+ return typeof value === 'bigint' || Number.isInteger(value);
+}
+const stringifyJSON = ({ value }) => JSON.stringify(value);
+const jsonScalars = [
+ {
+ identify: value => typeof value === 'string',
+ default: true,
+ tag: 'tag:yaml.org,2002:str',
+ resolve: str => str,
+ stringify: stringifyJSON
+ },
+ {
+ identify: value => value == null,
+ createNode: () => new Scalar.Scalar(null),
+ default: true,
+ tag: 'tag:yaml.org,2002:null',
+ test: /^null$/,
+ resolve: () => null,
+ stringify: stringifyJSON
+ },
+ {
+ identify: value => typeof value === 'boolean',
+ default: true,
+ tag: 'tag:yaml.org,2002:bool',
+ test: /^true|false$/,
+ resolve: str => str === 'true',
+ stringify: stringifyJSON
+ },
+ {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ test: /^-?(?:0|[1-9][0-9]*)$/,
+ resolve: (str, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str, 10),
+ stringify: ({ value }) => intIdentify(value) ? value.toString() : JSON.stringify(value)
+ },
+ {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,
+ resolve: str => parseFloat(str),
+ stringify: stringifyJSON
+ }
+];
+const jsonError = {
+ default: true,
+ tag: '',
+ test: /^/,
+ resolve(str, onError) {
+ onError(`Unresolved plain scalar ${JSON.stringify(str)}`);
+ return str;
+ }
+};
+const schema = [map.map, seq.seq].concat(jsonScalars, jsonError);
+
+exports.schema = schema;
diff --git a/MistyCore/node_modules/yaml/dist/schema/tags.d.ts b/MistyCore/node_modules/yaml/dist/schema/tags.d.ts
new file mode 100644
index 0000000..8b4acf2
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/tags.d.ts
@@ -0,0 +1,40 @@
+import { SchemaOptions } from '../options.js';
+import type { CollectionTag, ScalarTag } from './types.js';
+declare const tagsByName: {
+ binary: ScalarTag;
+ bool: ScalarTag & {
+ test: RegExp;
+ };
+ float: ScalarTag;
+ floatExp: ScalarTag;
+ floatNaN: ScalarTag;
+ floatTime: ScalarTag;
+ int: ScalarTag;
+ intHex: ScalarTag;
+ intOct: ScalarTag;
+ intTime: ScalarTag;
+ map: CollectionTag;
+ null: ScalarTag & {
+ test: RegExp;
+ };
+ omap: CollectionTag;
+ pairs: CollectionTag;
+ seq: CollectionTag;
+ set: CollectionTag;
+ timestamp: ScalarTag & {
+ test: RegExp;
+ };
+};
+export declare type TagId = keyof typeof tagsByName;
+export declare type Tags = Array<ScalarTag | CollectionTag | TagId>;
+export declare const coreKnownTags: {
+ 'tag:yaml.org,2002:binary': ScalarTag;
+ 'tag:yaml.org,2002:omap': CollectionTag;
+ 'tag:yaml.org,2002:pairs': CollectionTag;
+ 'tag:yaml.org,2002:set': CollectionTag;
+ 'tag:yaml.org,2002:timestamp': ScalarTag & {
+ test: RegExp;
+ };
+};
+export declare function getTags(customTags: SchemaOptions['customTags'] | undefined, schemaName: string): (ScalarTag | CollectionTag)[];
+export {};
diff --git a/MistyCore/node_modules/yaml/dist/schema/tags.js b/MistyCore/node_modules/yaml/dist/schema/tags.js
new file mode 100644
index 0000000..e49d2b0
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/tags.js
@@ -0,0 +1,86 @@
+'use strict';
+
+var map = require('./common/map.js');
+var _null = require('./common/null.js');
+var seq = require('./common/seq.js');
+var string = require('./common/string.js');
+var bool = require('./core/bool.js');
+var float = require('./core/float.js');
+var int = require('./core/int.js');
+var schema = require('./core/schema.js');
+var schema$1 = require('./json/schema.js');
+var binary = require('./yaml-1.1/binary.js');
+var omap = require('./yaml-1.1/omap.js');
+var pairs = require('./yaml-1.1/pairs.js');
+var schema$2 = require('./yaml-1.1/schema.js');
+var set = require('./yaml-1.1/set.js');
+var timestamp = require('./yaml-1.1/timestamp.js');
+
+const schemas = new Map([
+ ['core', schema.schema],
+ ['failsafe', [map.map, seq.seq, string.string]],
+ ['json', schema$1.schema],
+ ['yaml11', schema$2.schema],
+ ['yaml-1.1', schema$2.schema]
+]);
+const tagsByName = {
+ binary: binary.binary,
+ bool: bool.boolTag,
+ float: float.float,
+ floatExp: float.floatExp,
+ floatNaN: float.floatNaN,
+ floatTime: timestamp.floatTime,
+ int: int.int,
+ intHex: int.intHex,
+ intOct: int.intOct,
+ intTime: timestamp.intTime,
+ map: map.map,
+ null: _null.nullTag,
+ omap: omap.omap,
+ pairs: pairs.pairs,
+ seq: seq.seq,
+ set: set.set,
+ timestamp: timestamp.timestamp
+};
+const coreKnownTags = {
+ 'tag:yaml.org,2002:binary': binary.binary,
+ 'tag:yaml.org,2002:omap': omap.omap,
+ 'tag:yaml.org,2002:pairs': pairs.pairs,
+ 'tag:yaml.org,2002:set': set.set,
+ 'tag:yaml.org,2002:timestamp': timestamp.timestamp
+};
+function getTags(customTags, schemaName) {
+ let tags = schemas.get(schemaName);
+ if (!tags) {
+ if (Array.isArray(customTags))
+ tags = [];
+ else {
+ const keys = Array.from(schemas.keys())
+ .filter(key => key !== 'yaml11')
+ .map(key => JSON.stringify(key))
+ .join(', ');
+ throw new Error(`Unknown schema "${schemaName}"; use one of ${keys} or define customTags array`);
+ }
+ }
+ if (Array.isArray(customTags)) {
+ for (const tag of customTags)
+ tags = tags.concat(tag);
+ }
+ else if (typeof customTags === 'function') {
+ tags = customTags(tags.slice());
+ }
+ return tags.map(tag => {
+ if (typeof tag !== 'string')
+ return tag;
+ const tagObj = tagsByName[tag];
+ if (tagObj)
+ return tagObj;
+ const keys = Object.keys(tagsByName)
+ .map(key => JSON.stringify(key))
+ .join(', ');
+ throw new Error(`Unknown custom tag "${tag}"; use one of ${keys}`);
+ });
+}
+
+exports.coreKnownTags = coreKnownTags;
+exports.getTags = getTags;
diff --git a/MistyCore/node_modules/yaml/dist/schema/types.d.ts b/MistyCore/node_modules/yaml/dist/schema/types.d.ts
new file mode 100644
index 0000000..13e8354
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/types.d.ts
@@ -0,0 +1,82 @@
+import type { CreateNodeContext } from '../doc/createNode.js';
+import type { Schema } from './Schema.js';
+import type { Node } from '../nodes/Node.js';
+import type { Scalar } from '../nodes/Scalar.js';
+import type { YAMLMap } from '../nodes/YAMLMap.js';
+import type { YAMLSeq } from '../nodes/YAMLSeq.js';
+import type { ParseOptions } from '../options.js';
+import type { StringifyContext } from '../stringify/stringify.js';
+interface TagBase {
+ /**
+ * An optional factory function, used e.g. by collections when wrapping JS objects as AST nodes.
+ */
+ createNode?: (schema: Schema, value: unknown, ctx: CreateNodeContext) => Node;
+ /**
+ * If `true`, together with `test` allows for values to be stringified without
+ * an explicit tag. For most cases, it's unlikely that you'll actually want to
+ * use this, even if you first think you do.
+ */
+ default: boolean;
+ /**
+ * If a tag has multiple forms that should be parsed and/or stringified
+ * differently, use `format` to identify them.
+ */
+ format?: string;
+ /**
+ * Used by `YAML.createNode` to detect your data type, e.g. using `typeof` or
+ * `instanceof`.
+ */
+ identify?: (value: unknown) => boolean;
+ /**
+ * The identifier for your data type, with which its stringified form will be
+ * prefixed. Should either be a !-prefixed local `!tag`, or a fully qualified
+ * `tag:domain,date:foo`.
+ */
+ tag: string;
+}
+export interface ScalarTag extends TagBase {
+ collection?: never;
+ nodeClass?: never;
+ /**
+ * Turns a value into an AST node.
+ * If returning a non-`Node` value, the output will be wrapped as a `Scalar`.
+ */
+ resolve(value: string, onError: (message: string) => void, options: ParseOptions): unknown;
+ /**
+ * Optional function stringifying a Scalar node. If your data includes a
+ * suitable `.toString()` method, you can probably leave this undefined and
+ * use the default stringifier.
+ *
+ * @param item The node being stringified.
+ * @param ctx Contains the stringifying context variables.
+ * @param onComment Callback to signal that the stringifier includes the
+ * item's comment in its output.
+ * @param onChompKeep Callback to signal that the output uses a block scalar
+ * type with the `+` chomping indicator.
+ */
+ stringify?: (item: Scalar, ctx: StringifyContext, onComment?: () => void, onChompKeep?: () => void) => string;
+ /**
+ * Together with `default` allows for values to be stringified without an
+ * explicit tag and detected using a regular expression. For most cases, it's
+ * unlikely that you'll actually want to use these, even if you first think
+ * you do.
+ */
+ test?: RegExp;
+}
+export interface CollectionTag extends TagBase {
+ stringify?: never;
+ test?: never;
+ /** The source collection type supported by this tag. */
+ collection: 'map' | 'seq';
+ /**
+ * The `Node` child class that implements this tag.
+ * If set, used to select this tag when stringifying.
+ */
+ nodeClass?: new () => Node;
+ /**
+ * Turns a value into an AST node.
+ * If returning a non-`Node` value, the output will be wrapped as a `Scalar`.
+ */
+ resolve(value: YAMLMap.Parsed | YAMLSeq.Parsed, onError: (message: string) => void, options: ParseOptions): unknown;
+}
+export {};
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts
new file mode 100644
index 0000000..2054970
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts
@@ -0,0 +1,2 @@
+import type { ScalarTag } from '../types.js';
+export declare const binary: ScalarTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/binary.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/binary.js
new file mode 100644
index 0000000..df93e05
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/binary.js
@@ -0,0 +1,68 @@
+'use strict';
+
+var Scalar = require('../../nodes/Scalar.js');
+var stringifyString = require('../../stringify/stringifyString.js');
+
+const binary = {
+ identify: value => value instanceof Uint8Array,
+ default: false,
+ tag: 'tag:yaml.org,2002:binary',
+ /**
+ * Returns a Buffer in node and an Uint8Array in browsers
+ *
+ * To use the resulting buffer as an image, you'll want to do something like:
+ *
+ * const blob = new Blob([buffer], { type: 'image/jpeg' })
+ * document.querySelector('#photo').src = URL.createObjectURL(blob)
+ */
+ resolve(src, onError) {
+ if (typeof Buffer === 'function') {
+ return Buffer.from(src, 'base64');
+ }
+ else if (typeof atob === 'function') {
+ // On IE 11, atob() can't handle newlines
+ const str = atob(src.replace(/[\n\r]/g, ''));
+ const buffer = new Uint8Array(str.length);
+ for (let i = 0; i < str.length; ++i)
+ buffer[i] = str.charCodeAt(i);
+ return buffer;
+ }
+ else {
+ onError('This environment does not support reading binary tags; either Buffer or atob is required');
+ return src;
+ }
+ },
+ stringify({ comment, type, value }, ctx, onComment, onChompKeep) {
+ const buf = value; // checked earlier by binary.identify()
+ let str;
+ if (typeof Buffer === 'function') {
+ str =
+ buf instanceof Buffer
+ ? buf.toString('base64')
+ : Buffer.from(buf.buffer).toString('base64');
+ }
+ else if (typeof btoa === 'function') {
+ let s = '';
+ for (let i = 0; i < buf.length; ++i)
+ s += String.fromCharCode(buf[i]);
+ str = btoa(s);
+ }
+ else {
+ throw new Error('This environment does not support writing binary tags; either Buffer or btoa is required');
+ }
+ if (!type)
+ type = Scalar.Scalar.BLOCK_LITERAL;
+ if (type !== Scalar.Scalar.QUOTE_DOUBLE) {
+ const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth);
+ const n = Math.ceil(str.length / lineWidth);
+ const lines = new Array(n);
+ for (let i = 0, o = 0; i < n; ++i, o += lineWidth) {
+ lines[i] = str.substr(o, lineWidth);
+ }
+ str = lines.join(type === Scalar.Scalar.BLOCK_LITERAL ? '\n' : ' ');
+ }
+ return stringifyString.stringifyString({ comment, type, value: str }, ctx, onComment, onChompKeep);
+ }
+};
+
+exports.binary = binary;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts
new file mode 100644
index 0000000..587b55b
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts
@@ -0,0 +1,7 @@
+import type { ScalarTag } from '../types.js';
+export declare const trueTag: ScalarTag & {
+ test: RegExp;
+};
+export declare const falseTag: ScalarTag & {
+ test: RegExp;
+};
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/bool.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/bool.js
new file mode 100644
index 0000000..fdb3b46
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/bool.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var Scalar = require('../../nodes/Scalar.js');
+
+function boolStringify({ value, source }, ctx) {
+ const boolObj = value ? trueTag : falseTag;
+ if (source && boolObj.test.test(source))
+ return source;
+ return value ? ctx.options.trueStr : ctx.options.falseStr;
+}
+const trueTag = {
+ identify: value => value === true,
+ default: true,
+ tag: 'tag:yaml.org,2002:bool',
+ test: /^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/,
+ resolve: () => new Scalar.Scalar(true),
+ stringify: boolStringify
+};
+const falseTag = {
+ identify: value => value === false,
+ default: true,
+ tag: 'tag:yaml.org,2002:bool',
+ test: /^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/i,
+ resolve: () => new Scalar.Scalar(false),
+ stringify: boolStringify
+};
+
+exports.falseTag = falseTag;
+exports.trueTag = trueTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts
new file mode 100644
index 0000000..22f0249
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts
@@ -0,0 +1,4 @@
+import type { ScalarTag } from '../types.js';
+export declare const floatNaN: ScalarTag;
+export declare const floatExp: ScalarTag;
+export declare const float: ScalarTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/float.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/float.js
new file mode 100644
index 0000000..4aea19a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/float.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var Scalar = require('../../nodes/Scalar.js');
+var stringifyNumber = require('../../stringify/stringifyNumber.js');
+
+const floatNaN = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^[-+]?\.(?:inf|Inf|INF|nan|NaN|NAN)$/,
+ resolve: (str) => str.slice(-3).toLowerCase() === 'nan'
+ ? NaN
+ : str[0] === '-'
+ ? Number.NEGATIVE_INFINITY
+ : Number.POSITIVE_INFINITY,
+ stringify: stringifyNumber.stringifyNumber
+};
+const floatExp = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ format: 'EXP',
+ test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
+ resolve: (str) => parseFloat(str.replace(/_/g, '')),
+ stringify(node) {
+ const num = Number(node.value);
+ return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node);
+ }
+};
+const float = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,
+ resolve(str) {
+ const node = new Scalar.Scalar(parseFloat(str.replace(/_/g, '')));
+ const dot = str.indexOf('.');
+ if (dot !== -1) {
+ const f = str.substring(dot + 1).replace(/_/g, '');
+ if (f[f.length - 1] === '0')
+ node.minFractionDigits = f.length;
+ }
+ return node;
+ },
+ stringify: stringifyNumber.stringifyNumber
+};
+
+exports.float = float;
+exports.floatExp = floatExp;
+exports.floatNaN = floatNaN;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts
new file mode 100644
index 0000000..3d92f37
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts
@@ -0,0 +1,5 @@
+import type { ScalarTag } from '../types.js';
+export declare const intBin: ScalarTag;
+export declare const intOct: ScalarTag;
+export declare const int: ScalarTag;
+export declare const intHex: ScalarTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/int.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/int.js
new file mode 100644
index 0000000..fdf47ca
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/int.js
@@ -0,0 +1,76 @@
+'use strict';
+
+var stringifyNumber = require('../../stringify/stringifyNumber.js');
+
+const intIdentify = (value) => typeof value === 'bigint' || Number.isInteger(value);
+function intResolve(str, offset, radix, { intAsBigInt }) {
+ const sign = str[0];
+ if (sign === '-' || sign === '+')
+ offset += 1;
+ str = str.substring(offset).replace(/_/g, '');
+ if (intAsBigInt) {
+ switch (radix) {
+ case 2:
+ str = `0b${str}`;
+ break;
+ case 8:
+ str = `0o${str}`;
+ break;
+ case 16:
+ str = `0x${str}`;
+ break;
+ }
+ const n = BigInt(str);
+ return sign === '-' ? BigInt(-1) * n : n;
+ }
+ const n = parseInt(str, radix);
+ return sign === '-' ? -1 * n : n;
+}
+function intStringify(node, radix, prefix) {
+ const { value } = node;
+ if (intIdentify(value)) {
+ const str = value.toString(radix);
+ return value < 0 ? '-' + prefix + str.substr(1) : prefix + str;
+ }
+ return stringifyNumber.stringifyNumber(node);
+}
+const intBin = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'BIN',
+ test: /^[-+]?0b[0-1_]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 2, 2, opt),
+ stringify: node => intStringify(node, 2, '0b')
+};
+const intOct = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'OCT',
+ test: /^[-+]?0[0-7_]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 1, 8, opt),
+ stringify: node => intStringify(node, 8, '0')
+};
+const int = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ test: /^[-+]?[0-9][0-9_]*$/,
+ resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
+ stringify: stringifyNumber.stringifyNumber
+};
+const intHex = {
+ identify: intIdentify,
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'HEX',
+ test: /^[-+]?0x[0-9a-fA-F_]+$/,
+ resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
+ stringify: node => intStringify(node, 16, '0x')
+};
+
+exports.int = int;
+exports.intBin = intBin;
+exports.intHex = intHex;
+exports.intOct = intOct;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts
new file mode 100644
index 0000000..a5a37cd
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts
@@ -0,0 +1,25 @@
+import { YAMLSeq } from '../../nodes/YAMLSeq.js';
+import { ToJSContext } from '../../nodes/toJS.js';
+import { CollectionTag } from '../types.js';
+export declare class YAMLOMap extends YAMLSeq {
+ static tag: string;
+ constructor();
+ add: (pair: import("../../index.js").Pair<any, any> | {
+ key: any;
+ value: any;
+ }, overwrite?: boolean | undefined) => void;
+ delete: (key: unknown) => boolean;
+ get: {
+ (key: unknown, keepScalar: true): import("../../index.js").Scalar<any> | undefined;
+ (key: unknown, keepScalar?: false | undefined): any;
+ (key: unknown, keepScalar?: boolean | undefined): any;
+ };
+ has: (key: unknown) => boolean;
+ set: (key: any, value: any) => void;
+ /**
+ * If `ctx` is given, the return type is actually `Map<unknown, unknown>`,
+ * but TypeScript won't allow widening the signature of a child method.
+ */
+ toJSON(_?: unknown, ctx?: ToJSContext): unknown[];
+}
+export declare const omap: CollectionTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/omap.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/omap.js
new file mode 100644
index 0000000..eb69d5a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/omap.js
@@ -0,0 +1,76 @@
+'use strict';
+
+var YAMLSeq = require('../../nodes/YAMLSeq.js');
+var toJS = require('../../nodes/toJS.js');
+var Node = require('../../nodes/Node.js');
+var YAMLMap = require('../../nodes/YAMLMap.js');
+var pairs = require('./pairs.js');
+
+class YAMLOMap extends YAMLSeq.YAMLSeq {
+ constructor() {
+ super();
+ this.add = YAMLMap.YAMLMap.prototype.add.bind(this);
+ this.delete = YAMLMap.YAMLMap.prototype.delete.bind(this);
+ this.get = YAMLMap.YAMLMap.prototype.get.bind(this);
+ this.has = YAMLMap.YAMLMap.prototype.has.bind(this);
+ this.set = YAMLMap.YAMLMap.prototype.set.bind(this);
+ this.tag = YAMLOMap.tag;
+ }
+ /**
+ * If `ctx` is given, the return type is actually `Map<unknown, unknown>`,
+ * but TypeScript won't allow widening the signature of a child method.
+ */
+ toJSON(_, ctx) {
+ if (!ctx)
+ return super.toJSON(_);
+ const map = new Map();
+ if (ctx?.onCreate)
+ ctx.onCreate(map);
+ for (const pair of this.items) {
+ let key, value;
+ if (Node.isPair(pair)) {
+ key = toJS.toJS(pair.key, '', ctx);
+ value = toJS.toJS(pair.value, key, ctx);
+ }
+ else {
+ key = toJS.toJS(pair, '', ctx);
+ }
+ if (map.has(key))
+ throw new Error('Ordered maps must not include duplicate keys');
+ map.set(key, value);
+ }
+ return map;
+ }
+}
+YAMLOMap.tag = 'tag:yaml.org,2002:omap';
+const omap = {
+ collection: 'seq',
+ identify: value => value instanceof Map,
+ nodeClass: YAMLOMap,
+ default: false,
+ tag: 'tag:yaml.org,2002:omap',
+ resolve(seq, onError) {
+ const pairs$1 = pairs.resolvePairs(seq, onError);
+ const seenKeys = [];
+ for (const { key } of pairs$1.items) {
+ if (Node.isScalar(key)) {
+ if (seenKeys.includes(key.value)) {
+ onError(`Ordered maps must not include duplicate keys: ${key.value}`);
+ }
+ else {
+ seenKeys.push(key.value);
+ }
+ }
+ }
+ return Object.assign(new YAMLOMap(), pairs$1);
+ },
+ createNode(schema, iterable, ctx) {
+ const pairs$1 = pairs.createPairs(schema, iterable, ctx);
+ const omap = new YAMLOMap();
+ omap.items = pairs$1.items;
+ return omap;
+ }
+};
+
+exports.YAMLOMap = YAMLOMap;
+exports.omap = omap;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts
new file mode 100644
index 0000000..8090ac2
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts
@@ -0,0 +1,10 @@
+import type { CreateNodeContext } from '../../doc/createNode.js';
+import { ParsedNode } from '../../nodes/Node.js';
+import { Pair } from '../../nodes/Pair.js';
+import { YAMLMap } from '../../nodes/YAMLMap.js';
+import { YAMLSeq } from '../../nodes/YAMLSeq.js';
+import type { Schema } from '../../schema/Schema.js';
+import type { CollectionTag } from '../types.js';
+export declare function resolvePairs(seq: YAMLSeq.Parsed<ParsedNode | Pair<ParsedNode, ParsedNode | null>> | YAMLMap.Parsed, onError: (message: string) => void): YAMLSeq.Parsed<Pair<ParsedNode, ParsedNode | null>>;
+export declare function createPairs(schema: Schema, iterable: unknown, ctx: CreateNodeContext): YAMLSeq<unknown>;
+export declare const pairs: CollectionTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/pairs.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/pairs.js
new file mode 100644
index 0000000..d27d34d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/pairs.js
@@ -0,0 +1,81 @@
+'use strict';
+
+var Node = require('../../nodes/Node.js');
+var Pair = require('../../nodes/Pair.js');
+var Scalar = require('../../nodes/Scalar.js');
+var YAMLSeq = require('../../nodes/YAMLSeq.js');
+
+function resolvePairs(seq, onError) {
+ if (Node.isSeq(seq)) {
+ for (let i = 0; i < seq.items.length; ++i) {
+ let item = seq.items[i];
+ if (Node.isPair(item))
+ continue;
+ else if (Node.isMap(item)) {
+ if (item.items.length > 1)
+ onError('Each pair must have its own sequence indicator');
+ const pair = item.items[0] || new Pair.Pair(new Scalar.Scalar(null));
+ if (item.commentBefore)
+ pair.key.commentBefore = pair.key.commentBefore
+ ? `${item.commentBefore}\n${pair.key.commentBefore}`
+ : item.commentBefore;
+ if (item.comment) {
+ const cn = pair.value ?? pair.key;
+ cn.comment = cn.comment
+ ? `${item.comment}\n${cn.comment}`
+ : item.comment;
+ }
+ item = pair;
+ }
+ seq.items[i] = Node.isPair(item) ? item : new Pair.Pair(item);
+ }
+ }
+ else
+ onError('Expected a sequence for this tag');
+ return seq;
+}
+function createPairs(schema, iterable, ctx) {
+ const { replacer } = ctx;
+ const pairs = new YAMLSeq.YAMLSeq(schema);
+ pairs.tag = 'tag:yaml.org,2002:pairs';
+ let i = 0;
+ if (iterable && Symbol.iterator in Object(iterable))
+ for (let it of iterable) {
+ if (typeof replacer === 'function')
+ it = replacer.call(iterable, String(i++), it);
+ let key, value;
+ if (Array.isArray(it)) {
+ if (it.length === 2) {
+ key = it[0];
+ value = it[1];
+ }
+ else
+ throw new TypeError(`Expected [key, value] tuple: ${it}`);
+ }
+ else if (it && it instanceof Object) {
+ const keys = Object.keys(it);
+ if (keys.length === 1) {
+ key = keys[0];
+ value = it[key];
+ }
+ else
+ throw new TypeError(`Expected { key: value } tuple: ${it}`);
+ }
+ else {
+ key = it;
+ }
+ pairs.items.push(Pair.createPair(key, value, ctx));
+ }
+ return pairs;
+}
+const pairs = {
+ collection: 'seq',
+ default: false,
+ tag: 'tag:yaml.org,2002:pairs',
+ resolve: resolvePairs,
+ createNode: createPairs
+};
+
+exports.createPairs = createPairs;
+exports.pairs = pairs;
+exports.resolvePairs = resolvePairs;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts
new file mode 100644
index 0000000..7663949
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts
@@ -0,0 +1 @@
+export declare const schema: (import("../types.js").ScalarTag | import("../types.js").CollectionTag)[];
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/schema.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/schema.js
new file mode 100644
index 0000000..c04270a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/schema.js
@@ -0,0 +1,39 @@
+'use strict';
+
+var map = require('../common/map.js');
+var _null = require('../common/null.js');
+var seq = require('../common/seq.js');
+var string = require('../common/string.js');
+var binary = require('./binary.js');
+var bool = require('./bool.js');
+var float = require('./float.js');
+var int = require('./int.js');
+var omap = require('./omap.js');
+var pairs = require('./pairs.js');
+var set = require('./set.js');
+var timestamp = require('./timestamp.js');
+
+const schema = [
+ map.map,
+ seq.seq,
+ string.string,
+ _null.nullTag,
+ bool.trueTag,
+ bool.falseTag,
+ int.intBin,
+ int.intOct,
+ int.int,
+ int.intHex,
+ float.floatNaN,
+ float.floatExp,
+ float.float,
+ binary.binary,
+ omap.omap,
+ pairs.pairs,
+ set.set,
+ timestamp.intTime,
+ timestamp.floatTime,
+ timestamp.timestamp
+];
+
+exports.schema = schema;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts
new file mode 100644
index 0000000..068f582
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts
@@ -0,0 +1,26 @@
+import type { Schema } from '../../schema/Schema.js';
+import { Pair } from '../../nodes/Pair.js';
+import { Scalar } from '../../nodes/Scalar.js';
+import { ToJSContext } from '../../nodes/toJS.js';
+import { YAMLMap } from '../../nodes/YAMLMap.js';
+import type { StringifyContext } from '../../stringify/stringify.js';
+import type { CollectionTag } from '../types.js';
+export declare class YAMLSet<T = unknown> extends YAMLMap<T, Scalar<null> | null> {
+ static tag: string;
+ constructor(schema?: Schema);
+ add(key: T | Pair<T, Scalar<null> | null> | {
+ key: T;
+ value: Scalar<null> | null;
+ }): void;
+ /**
+ * If `keepPair` is `true`, returns the Pair matching `key`.
+ * Otherwise, returns the value of that Pair's key.
+ */
+ get(key: unknown, keepPair?: boolean): any;
+ set(key: T, value: boolean): void;
+ /** @deprecated Will throw; `value` must be boolean */
+ set(key: T, value: null): void;
+ toJSON(_?: unknown, ctx?: ToJSContext): any;
+ toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
+}
+export declare const set: CollectionTag;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/set.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/set.js
new file mode 100644
index 0000000..c288a37
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/set.js
@@ -0,0 +1,95 @@
+'use strict';
+
+var Node = require('../../nodes/Node.js');
+var Pair = require('../../nodes/Pair.js');
+var YAMLMap = require('../../nodes/YAMLMap.js');
+
+class YAMLSet extends YAMLMap.YAMLMap {
+ constructor(schema) {
+ super(schema);
+ this.tag = YAMLSet.tag;
+ }
+ add(key) {
+ let pair;
+ if (Node.isPair(key))
+ pair = key;
+ else if (key &&
+ typeof key === 'object' &&
+ 'key' in key &&
+ 'value' in key &&
+ key.value === null)
+ pair = new Pair.Pair(key.key, null);
+ else
+ pair = new Pair.Pair(key, null);
+ const prev = YAMLMap.findPair(this.items, pair.key);
+ if (!prev)
+ this.items.push(pair);
+ }
+ /**
+ * If `keepPair` is `true`, returns the Pair matching `key`.
+ * Otherwise, returns the value of that Pair's key.
+ */
+ get(key, keepPair) {
+ const pair = YAMLMap.findPair(this.items, key);
+ return !keepPair && Node.isPair(pair)
+ ? Node.isScalar(pair.key)
+ ? pair.key.value
+ : pair.key
+ : pair;
+ }
+ set(key, value) {
+ if (typeof value !== 'boolean')
+ throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof value}`);
+ const prev = YAMLMap.findPair(this.items, key);
+ if (prev && !value) {
+ this.items.splice(this.items.indexOf(prev), 1);
+ }
+ else if (!prev && value) {
+ this.items.push(new Pair.Pair(key));
+ }
+ }
+ toJSON(_, ctx) {
+ return super.toJSON(_, ctx, Set);
+ }
+ toString(ctx, onComment, onChompKeep) {
+ if (!ctx)
+ return JSON.stringify(this);
+ if (this.hasAllNullValues(true))
+ return super.toString(Object.assign({}, ctx, { allNullValues: true }), onComment, onChompKeep);
+ else
+ throw new Error('Set items must all have null values');
+ }
+}
+YAMLSet.tag = 'tag:yaml.org,2002:set';
+const set = {
+ collection: 'map',
+ identify: value => value instanceof Set,
+ nodeClass: YAMLSet,
+ default: false,
+ tag: 'tag:yaml.org,2002:set',
+ resolve(map, onError) {
+ if (Node.isMap(map)) {
+ if (map.hasAllNullValues(true))
+ return Object.assign(new YAMLSet(), map);
+ else
+ onError('Set items must all have null values');
+ }
+ else
+ onError('Expected a mapping for this tag');
+ return map;
+ },
+ createNode(schema, iterable, ctx) {
+ const { replacer } = ctx;
+ const set = new YAMLSet(schema);
+ if (iterable && Symbol.iterator in Object(iterable))
+ for (let value of iterable) {
+ if (typeof replacer === 'function')
+ value = replacer.call(iterable, value, value);
+ set.items.push(Pair.createPair(value, null, ctx));
+ }
+ return set;
+ }
+};
+
+exports.YAMLSet = YAMLSet;
+exports.set = set;
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts
new file mode 100644
index 0000000..0c1d2d4
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts
@@ -0,0 +1,6 @@
+import type { ScalarTag } from '../types.js';
+export declare const intTime: ScalarTag;
+export declare const floatTime: ScalarTag;
+export declare const timestamp: ScalarTag & {
+ test: RegExp;
+};
diff --git a/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js
new file mode 100644
index 0000000..2d78ae8
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js
@@ -0,0 +1,105 @@
+'use strict';
+
+var stringifyNumber = require('../../stringify/stringifyNumber.js');
+
+/** Internal types handle bigint as number, because TS can't figure it out. */
+function parseSexagesimal(str, asBigInt) {
+ const sign = str[0];
+ const parts = sign === '-' || sign === '+' ? str.substring(1) : str;
+ const num = (n) => asBigInt ? BigInt(n) : Number(n);
+ const res = parts
+ .replace(/_/g, '')
+ .split(':')
+ .reduce((res, p) => res * num(60) + num(p), num(0));
+ return (sign === '-' ? num(-1) * res : res);
+}
+/**
+ * hhhh:mm:ss.sss
+ *
+ * Internal types handle bigint as number, because TS can't figure it out.
+ */
+function stringifySexagesimal(node) {
+ let { value } = node;
+ let num = (n) => n;
+ if (typeof value === 'bigint')
+ num = n => BigInt(n);
+ else if (isNaN(value) || !isFinite(value))
+ return stringifyNumber.stringifyNumber(node);
+ let sign = '';
+ if (value < 0) {
+ sign = '-';
+ value *= num(-1);
+ }
+ const _60 = num(60);
+ const parts = [value % _60]; // seconds, including ms
+ if (value < 60) {
+ parts.unshift(0); // at least one : is required
+ }
+ else {
+ value = (value - parts[0]) / _60;
+ parts.unshift(value % _60); // minutes
+ if (value >= 60) {
+ value = (value - parts[0]) / _60;
+ parts.unshift(value); // hours
+ }
+ }
+ return (sign +
+ parts
+ .map(n => (n < 10 ? '0' + String(n) : String(n)))
+ .join(':')
+ .replace(/000000\d*$/, '') // % 60 may introduce error
+ );
+}
+const intTime = {
+ identify: value => typeof value === 'bigint' || Number.isInteger(value),
+ default: true,
+ tag: 'tag:yaml.org,2002:int',
+ format: 'TIME',
+ test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,
+ resolve: (str, _onError, { intAsBigInt }) => parseSexagesimal(str, intAsBigInt),
+ stringify: stringifySexagesimal
+};
+const floatTime = {
+ identify: value => typeof value === 'number',
+ default: true,
+ tag: 'tag:yaml.org,2002:float',
+ format: 'TIME',
+ test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,
+ resolve: str => parseSexagesimal(str, false),
+ stringify: stringifySexagesimal
+};
+const timestamp = {
+ identify: value => value instanceof Date,
+ default: true,
+ tag: 'tag:yaml.org,2002:timestamp',
+ // If the time zone is omitted, the timestamp is assumed to be specified in UTC. The time part
+ // may be omitted altogether, resulting in a date format. In such a case, the time part is
+ // assumed to be 00:00:00Z (start of day, UTC).
+ test: RegExp('^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})' + // YYYY-Mm-Dd
+ '(?:' + // time is optional
+ '(?:t|T|[ \\t]+)' + // t | T | whitespace
+ '([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)' + // Hh:Mm:Ss(.ss)?
+ '(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?' + // Z | +5 | -03:30
+ ')?$'),
+ resolve(str) {
+ const match = str.match(timestamp.test);
+ if (!match)
+ throw new Error('!!timestamp expects a date, starting with yyyy-mm-dd');
+ const [, year, month, day, hour, minute, second] = match.map(Number);
+ const millisec = match[7] ? Number((match[7] + '00').substr(1, 3)) : 0;
+ let date = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
+ const tz = match[8];
+ if (tz && tz !== 'Z') {
+ let d = parseSexagesimal(tz, false);
+ if (Math.abs(d) < 30)
+ d *= 60;
+ date -= 60000 * d;
+ }
+ return new Date(date);
+ },
+ stringify: ({ value }) => value.toISOString().replace(/((T00:00)?:00)?\.000Z$/, '')
+};
+
+exports.floatTime = floatTime;
+exports.intTime = intTime;
+exports.timestamp = timestamp;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/foldFlowLines.d.ts b/MistyCore/node_modules/yaml/dist/stringify/foldFlowLines.d.ts
new file mode 100644
index 0000000..58f8c7b
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/foldFlowLines.d.ts
@@ -0,0 +1,34 @@
+export declare const FOLD_FLOW = "flow";
+export declare const FOLD_BLOCK = "block";
+export declare const FOLD_QUOTED = "quoted";
+/**
+ * `'block'` prevents more-indented lines from being folded;
+ * `'quoted'` allows for `\` escapes, including escaped newlines
+ */
+export declare type FoldMode = 'flow' | 'block' | 'quoted';
+export interface FoldOptions {
+ /**
+ * Accounts for leading contents on the first line, defaulting to
+ * `indent.length`
+ */
+ indentAtStart?: number;
+ /** Default: `80` */
+ lineWidth?: number;
+ /**
+ * Allow highly indented lines to stretch the line width or indent content
+ * from the start.
+ *
+ * Default: `20`
+ */
+ minContentWidth?: number;
+ /** Called once if the text is folded */
+ onFold?: () => void;
+ /** Called once if any line of text exceeds lineWidth characters */
+ onOverflow?: () => void;
+}
+/**
+ * Tries to keep input at up to `lineWidth` characters, splitting only on spaces
+ * not followed by newlines or spaces unless `mode` is `'quoted'`. Lines are
+ * terminated with `\n` and started with `indent`.
+ */
+export declare function foldFlowLines(text: string, indent: string, mode?: FoldMode, { indentAtStart, lineWidth, minContentWidth, onFold, onOverflow }?: FoldOptions): string;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/foldFlowLines.js b/MistyCore/node_modules/yaml/dist/stringify/foldFlowLines.js
new file mode 100644
index 0000000..efe7a25
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/foldFlowLines.js
@@ -0,0 +1,140 @@
+'use strict';
+
+const FOLD_FLOW = 'flow';
+const FOLD_BLOCK = 'block';
+const FOLD_QUOTED = 'quoted';
+/**
+ * Tries to keep input at up to `lineWidth` characters, splitting only on spaces
+ * not followed by newlines or spaces unless `mode` is `'quoted'`. Lines are
+ * terminated with `\n` and started with `indent`.
+ */
+function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
+ if (!lineWidth || lineWidth < 0)
+ return text;
+ const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
+ if (text.length <= endStep)
+ return text;
+ const folds = [];
+ const escapedFolds = {};
+ let end = lineWidth - indent.length;
+ if (typeof indentAtStart === 'number') {
+ if (indentAtStart > lineWidth - Math.max(2, minContentWidth))
+ folds.push(0);
+ else
+ end = lineWidth - indentAtStart;
+ }
+ let split = undefined;
+ let prev = undefined;
+ let overflow = false;
+ let i = -1;
+ let escStart = -1;
+ let escEnd = -1;
+ if (mode === FOLD_BLOCK) {
+ i = consumeMoreIndentedLines(text, i);
+ if (i !== -1)
+ end = i + endStep;
+ }
+ for (let ch; (ch = text[(i += 1)]);) {
+ if (mode === FOLD_QUOTED && ch === '\\') {
+ escStart = i;
+ switch (text[i + 1]) {
+ case 'x':
+ i += 3;
+ break;
+ case 'u':
+ i += 5;
+ break;
+ case 'U':
+ i += 9;
+ break;
+ default:
+ i += 1;
+ }
+ escEnd = i;
+ }
+ if (ch === '\n') {
+ if (mode === FOLD_BLOCK)
+ i = consumeMoreIndentedLines(text, i);
+ end = i + endStep;
+ split = undefined;
+ }
+ else {
+ if (ch === ' ' &&
+ prev &&
+ prev !== ' ' &&
+ prev !== '\n' &&
+ prev !== '\t') {
+ // space surrounded by non-space can be replaced with newline + indent
+ const next = text[i + 1];
+ if (next && next !== ' ' && next !== '\n' && next !== '\t')
+ split = i;
+ }
+ if (i >= end) {
+ if (split) {
+ folds.push(split);
+ end = split + endStep;
+ split = undefined;
+ }
+ else if (mode === FOLD_QUOTED) {
+ // white-space collected at end may stretch past lineWidth
+ while (prev === ' ' || prev === '\t') {
+ prev = ch;
+ ch = text[(i += 1)];
+ overflow = true;
+ }
+ // Account for newline escape, but don't break preceding escape
+ const j = i > escEnd + 1 ? i - 2 : escStart - 1;
+ // Bail out if lineWidth & minContentWidth are shorter than an escape string
+ if (escapedFolds[j])
+ return text;
+ folds.push(j);
+ escapedFolds[j] = true;
+ end = j + endStep;
+ split = undefined;
+ }
+ else {
+ overflow = true;
+ }
+ }
+ }
+ prev = ch;
+ }
+ if (overflow && onOverflow)
+ onOverflow();
+ if (folds.length === 0)
+ return text;
+ if (onFold)
+ onFold();
+ let res = text.slice(0, folds[0]);
+ for (let i = 0; i < folds.length; ++i) {
+ const fold = folds[i];
+ const end = folds[i + 1] || text.length;
+ if (fold === 0)
+ res = `\n${indent}${text.slice(0, end)}`;
+ else {
+ if (mode === FOLD_QUOTED && escapedFolds[fold])
+ res += `${text[fold]}\\`;
+ res += `\n${indent}${text.slice(fold + 1, end)}`;
+ }
+ }
+ return res;
+}
+/**
+ * Presumes `i + 1` is at the start of a line
+ * @returns index of last newline in more-indented block
+ */
+function consumeMoreIndentedLines(text, i) {
+ let ch = text[i + 1];
+ while (ch === ' ' || ch === '\t') {
+ do {
+ ch = text[(i += 1)];
+ } while (ch && ch !== '\n');
+ ch = text[i + 1];
+ }
+ return i;
+}
+
+exports.FOLD_BLOCK = FOLD_BLOCK;
+exports.FOLD_FLOW = FOLD_FLOW;
+exports.FOLD_QUOTED = FOLD_QUOTED;
+exports.foldFlowLines = foldFlowLines;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringify.d.ts b/MistyCore/node_modules/yaml/dist/stringify/stringify.d.ts
new file mode 100644
index 0000000..fe96889
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringify.d.ts
@@ -0,0 +1,20 @@
+import type { Document } from '../doc/Document.js';
+import type { Alias } from '../nodes/Alias.js';
+import type { ToStringOptions } from '../options.js';
+export declare type StringifyContext = {
+ actualString?: boolean;
+ allNullValues?: boolean;
+ anchors: Set<string>;
+ doc: Document;
+ forceBlockIndent?: boolean;
+ implicitKey?: boolean;
+ indent: string;
+ indentStep: string;
+ indentAtStart?: number;
+ inFlow: boolean | null;
+ inStringifyKey?: boolean;
+ options: Readonly<Required<Omit<ToStringOptions, 'collectionStyle' | 'indent'>>>;
+ resolvedAliases?: Set<Alias>;
+};
+export declare function createStringifyContext(doc: Document, options: ToStringOptions): StringifyContext;
+export declare function stringify(item: unknown, ctx: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringify.js b/MistyCore/node_modules/yaml/dist/stringify/stringify.js
new file mode 100644
index 0000000..a9a38c7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringify.js
@@ -0,0 +1,125 @@
+'use strict';
+
+var anchors = require('../doc/anchors.js');
+var Node = require('../nodes/Node.js');
+var stringifyComment = require('./stringifyComment.js');
+var stringifyString = require('./stringifyString.js');
+
+function createStringifyContext(doc, options) {
+ const opt = Object.assign({
+ blockQuote: true,
+ commentString: stringifyComment.stringifyComment,
+ defaultKeyType: null,
+ defaultStringType: 'PLAIN',
+ directives: null,
+ doubleQuotedAsJSON: false,
+ doubleQuotedMinMultiLineLength: 40,
+ falseStr: 'false',
+ indentSeq: true,
+ lineWidth: 80,
+ minContentWidth: 20,
+ nullStr: 'null',
+ simpleKeys: false,
+ singleQuote: null,
+ trueStr: 'true',
+ verifyAliasOrder: true
+ }, doc.schema.toStringOptions, options);
+ let inFlow;
+ switch (opt.collectionStyle) {
+ case 'block':
+ inFlow = false;
+ break;
+ case 'flow':
+ inFlow = true;
+ break;
+ default:
+ inFlow = null;
+ }
+ return {
+ anchors: new Set(),
+ doc,
+ indent: '',
+ indentStep: typeof opt.indent === 'number' ? ' '.repeat(opt.indent) : ' ',
+ inFlow,
+ options: opt
+ };
+}
+function getTagObject(tags, item) {
+ if (item.tag) {
+ const match = tags.filter(t => t.tag === item.tag);
+ if (match.length > 0)
+ return match.find(t => t.format === item.format) ?? match[0];
+ }
+ let tagObj = undefined;
+ let obj;
+ if (Node.isScalar(item)) {
+ obj = item.value;
+ const match = tags.filter(t => t.identify?.(obj));
+ tagObj =
+ match.find(t => t.format === item.format) ?? match.find(t => !t.format);
+ }
+ else {
+ obj = item;
+ tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass);
+ }
+ if (!tagObj) {
+ const name = obj?.constructor?.name ?? typeof obj;
+ throw new Error(`Tag not resolved for ${name} value`);
+ }
+ return tagObj;
+}
+// needs to be called before value stringifier to allow for circular anchor refs
+function stringifyProps(node, tagObj, { anchors: anchors$1, doc }) {
+ if (!doc.directives)
+ return '';
+ const props = [];
+ const anchor = (Node.isScalar(node) || Node.isCollection(node)) && node.anchor;
+ if (anchor && anchors.anchorIsValid(anchor)) {
+ anchors$1.add(anchor);
+ props.push(`&${anchor}`);
+ }
+ const tag = node.tag ? node.tag : tagObj.default ? null : tagObj.tag;
+ if (tag)
+ props.push(doc.directives.tagString(tag));
+ return props.join(' ');
+}
+function stringify(item, ctx, onComment, onChompKeep) {
+ if (Node.isPair(item))
+ return item.toString(ctx, onComment, onChompKeep);
+ if (Node.isAlias(item)) {
+ if (ctx.doc.directives)
+ return item.toString(ctx);
+ if (ctx.resolvedAliases?.has(item)) {
+ throw new TypeError(`Cannot stringify circular structure without alias nodes`);
+ }
+ else {
+ if (ctx.resolvedAliases)
+ ctx.resolvedAliases.add(item);
+ else
+ ctx.resolvedAliases = new Set([item]);
+ item = item.resolve(ctx.doc);
+ }
+ }
+ let tagObj = undefined;
+ const node = Node.isNode(item)
+ ? item
+ : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) });
+ if (!tagObj)
+ tagObj = getTagObject(ctx.doc.schema.tags, node);
+ const props = stringifyProps(node, tagObj, ctx);
+ if (props.length > 0)
+ ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
+ const str = typeof tagObj.stringify === 'function'
+ ? tagObj.stringify(node, ctx, onComment, onChompKeep)
+ : Node.isScalar(node)
+ ? stringifyString.stringifyString(node, ctx, onComment, onChompKeep)
+ : node.toString(ctx, onComment, onChompKeep);
+ if (!props)
+ return str;
+ return Node.isScalar(node) || str[0] === '{' || str[0] === '['
+ ? `${props} ${str}`
+ : `${props}\n${ctx.indent}${str}`;
+}
+
+exports.createStringifyContext = createStringifyContext;
+exports.stringify = stringify;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyCollection.d.ts b/MistyCore/node_modules/yaml/dist/stringify/stringifyCollection.d.ts
new file mode 100644
index 0000000..207d703
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyCollection.d.ts
@@ -0,0 +1,17 @@
+import { Collection } from '../nodes/Collection.js';
+import { StringifyContext } from './stringify.js';
+interface StringifyCollectionOptions {
+ blockItemPrefix: string;
+ flowChars: {
+ start: '{';
+ end: '}';
+ } | {
+ start: '[';
+ end: ']';
+ };
+ itemIndent: string;
+ onChompKeep?: () => void;
+ onComment?: () => void;
+}
+export declare function stringifyCollection(collection: Readonly<Collection>, ctx: StringifyContext, options: StringifyCollectionOptions): string;
+export {};
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyCollection.js b/MistyCore/node_modules/yaml/dist/stringify/stringifyCollection.js
new file mode 100644
index 0000000..f69c2bd
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyCollection.js
@@ -0,0 +1,153 @@
+'use strict';
+
+var Collection = require('../nodes/Collection.js');
+var Node = require('../nodes/Node.js');
+var stringify = require('./stringify.js');
+var stringifyComment = require('./stringifyComment.js');
+
+function stringifyCollection(collection, ctx, options) {
+ const flow = ctx.inFlow ?? collection.flow;
+ const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
+ return stringify(collection, ctx, options);
+}
+function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
+ const { indent, options: { commentString } } = ctx;
+ const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
+ let chompKeep = false; // flag for the preceding node's status
+ const lines = [];
+ for (let i = 0; i < items.length; ++i) {
+ const item = items[i];
+ let comment = null;
+ if (Node.isNode(item)) {
+ if (!chompKeep && item.spaceBefore)
+ lines.push('');
+ addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
+ if (item.comment)
+ comment = item.comment;
+ }
+ else if (Node.isPair(item)) {
+ const ik = Node.isNode(item.key) ? item.key : null;
+ if (ik) {
+ if (!chompKeep && ik.spaceBefore)
+ lines.push('');
+ addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
+ }
+ }
+ chompKeep = false;
+ let str = stringify.stringify(item, itemCtx, () => (comment = null), () => (chompKeep = true));
+ if (comment)
+ str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
+ if (chompKeep && comment)
+ chompKeep = false;
+ lines.push(blockItemPrefix + str);
+ }
+ let str;
+ if (lines.length === 0) {
+ str = flowChars.start + flowChars.end;
+ }
+ else {
+ str = lines[0];
+ for (let i = 1; i < lines.length; ++i) {
+ const line = lines[i];
+ str += line ? `\n${indent}${line}` : '\n';
+ }
+ }
+ if (comment) {
+ str += '\n' + stringifyComment.indentComment(commentString(comment), indent);
+ if (onComment)
+ onComment();
+ }
+ else if (chompKeep && onChompKeep)
+ onChompKeep();
+ return str;
+}
+function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemIndent, onComment }) {
+ const { indent, indentStep, options: { commentString } } = ctx;
+ itemIndent += indentStep;
+ const itemCtx = Object.assign({}, ctx, {
+ indent: itemIndent,
+ inFlow: true,
+ type: null
+ });
+ let reqNewline = false;
+ let linesAtValue = 0;
+ const lines = [];
+ for (let i = 0; i < items.length; ++i) {
+ const item = items[i];
+ let comment = null;
+ if (Node.isNode(item)) {
+ if (item.spaceBefore)
+ lines.push('');
+ addCommentBefore(ctx, lines, item.commentBefore, false);
+ if (item.comment)
+ comment = item.comment;
+ }
+ else if (Node.isPair(item)) {
+ const ik = Node.isNode(item.key) ? item.key : null;
+ if (ik) {
+ if (ik.spaceBefore)
+ lines.push('');
+ addCommentBefore(ctx, lines, ik.commentBefore, false);
+ if (ik.comment)
+ reqNewline = true;
+ }
+ const iv = Node.isNode(item.value) ? item.value : null;
+ if (iv) {
+ if (iv.comment)
+ comment = iv.comment;
+ if (iv.commentBefore)
+ reqNewline = true;
+ }
+ else if (item.value == null && ik && ik.comment) {
+ comment = ik.comment;
+ }
+ }
+ if (comment)
+ reqNewline = true;
+ let str = stringify.stringify(item, itemCtx, () => (comment = null));
+ if (i < items.length - 1)
+ str += ',';
+ if (comment)
+ str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
+ if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
+ reqNewline = true;
+ lines.push(str);
+ linesAtValue = lines.length;
+ }
+ let str;
+ const { start, end } = flowChars;
+ if (lines.length === 0) {
+ str = start + end;
+ }
+ else {
+ if (!reqNewline) {
+ const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
+ reqNewline = len > Collection.Collection.maxFlowStringSingleLineLength;
+ }
+ if (reqNewline) {
+ str = start;
+ for (const line of lines)
+ str += line ? `\n${indentStep}${indent}${line}` : '\n';
+ str += `\n${indent}${end}`;
+ }
+ else {
+ str = `${start} ${lines.join(' ')} ${end}`;
+ }
+ }
+ if (comment) {
+ str += stringifyComment.lineComment(str, commentString(comment), indent);
+ if (onComment)
+ onComment();
+ }
+ return str;
+}
+function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
+ if (comment && chompKeep)
+ comment = comment.replace(/^\n+/, '');
+ if (comment) {
+ const ic = stringifyComment.indentComment(commentString(comment), indent);
+ lines.push(ic.trimStart()); // Avoid double indent on first line
+ }
+}
+
+exports.stringifyCollection = stringifyCollection;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyComment.d.ts b/MistyCore/node_modules/yaml/dist/stringify/stringifyComment.d.ts
new file mode 100644
index 0000000..9fcf48d
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyComment.d.ts
@@ -0,0 +1,10 @@
+/**
+ * Stringifies a comment.
+ *
+ * Empty comment lines are left empty,
+ * lines consisting of a single space are replaced by `#`,
+ * and all other lines are prefixed with a `#`.
+ */
+export declare const stringifyComment: (str: string) => string;
+export declare function indentComment(comment: string, indent: string): string;
+export declare const lineComment: (str: string, indent: string, comment: string) => string;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyComment.js b/MistyCore/node_modules/yaml/dist/stringify/stringifyComment.js
new file mode 100644
index 0000000..26bf361
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyComment.js
@@ -0,0 +1,24 @@
+'use strict';
+
+/**
+ * Stringifies a comment.
+ *
+ * Empty comment lines are left empty,
+ * lines consisting of a single space are replaced by `#`,
+ * and all other lines are prefixed with a `#`.
+ */
+const stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, '#');
+function indentComment(comment, indent) {
+ if (/^\n+$/.test(comment))
+ return comment.substring(1);
+ return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
+}
+const lineComment = (str, indent, comment) => str.endsWith('\n')
+ ? indentComment(comment, indent)
+ : comment.includes('\n')
+ ? '\n' + indentComment(comment, indent)
+ : (str.endsWith(' ') ? '' : ' ') + comment;
+
+exports.indentComment = indentComment;
+exports.lineComment = lineComment;
+exports.stringifyComment = stringifyComment;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyDocument.d.ts b/MistyCore/node_modules/yaml/dist/stringify/stringifyDocument.d.ts
new file mode 100644
index 0000000..fb0633c
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyDocument.d.ts
@@ -0,0 +1,3 @@
+import { Document } from '../doc/Document.js';
+import { ToStringOptions } from '../options.js';
+export declare function stringifyDocument(doc: Readonly<Document>, options: ToStringOptions): string;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyDocument.js b/MistyCore/node_modules/yaml/dist/stringify/stringifyDocument.js
new file mode 100644
index 0000000..c3067e0
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyDocument.js
@@ -0,0 +1,87 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+var stringify = require('./stringify.js');
+var stringifyComment = require('./stringifyComment.js');
+
+function stringifyDocument(doc, options) {
+ const lines = [];
+ let hasDirectives = options.directives === true;
+ if (options.directives !== false && doc.directives) {
+ const dir = doc.directives.toString(doc);
+ if (dir) {
+ lines.push(dir);
+ hasDirectives = true;
+ }
+ else if (doc.directives.docStart)
+ hasDirectives = true;
+ }
+ if (hasDirectives)
+ lines.push('---');
+ const ctx = stringify.createStringifyContext(doc, options);
+ const { commentString } = ctx.options;
+ if (doc.commentBefore) {
+ if (lines.length !== 1)
+ lines.unshift('');
+ const cs = commentString(doc.commentBefore);
+ lines.unshift(stringifyComment.indentComment(cs, ''));
+ }
+ let chompKeep = false;
+ let contentComment = null;
+ if (doc.contents) {
+ if (Node.isNode(doc.contents)) {
+ if (doc.contents.spaceBefore && hasDirectives)
+ lines.push('');
+ if (doc.contents.commentBefore) {
+ const cs = commentString(doc.contents.commentBefore);
+ lines.push(stringifyComment.indentComment(cs, ''));
+ }
+ // top-level block scalars need to be indented if followed by a comment
+ ctx.forceBlockIndent = !!doc.comment;
+ contentComment = doc.contents.comment;
+ }
+ const onChompKeep = contentComment ? undefined : () => (chompKeep = true);
+ let body = stringify.stringify(doc.contents, ctx, () => (contentComment = null), onChompKeep);
+ if (contentComment)
+ body += stringifyComment.lineComment(body, '', commentString(contentComment));
+ if ((body[0] === '|' || body[0] === '>') &&
+ lines[lines.length - 1] === '---') {
+ // Top-level block scalars with a preceding doc marker ought to use the
+ // same line for their header.
+ lines[lines.length - 1] = `--- ${body}`;
+ }
+ else
+ lines.push(body);
+ }
+ else {
+ lines.push(stringify.stringify(doc.contents, ctx));
+ }
+ if (doc.directives?.docEnd) {
+ if (doc.comment) {
+ const cs = commentString(doc.comment);
+ if (cs.includes('\n')) {
+ lines.push('...');
+ lines.push(stringifyComment.indentComment(cs, ''));
+ }
+ else {
+ lines.push(`... ${cs}`);
+ }
+ }
+ else {
+ lines.push('...');
+ }
+ }
+ else {
+ let dc = doc.comment;
+ if (dc && chompKeep)
+ dc = dc.replace(/^\n+/, '');
+ if (dc) {
+ if ((!chompKeep || contentComment) && lines[lines.length - 1] !== '')
+ lines.push('');
+ lines.push(stringifyComment.indentComment(commentString(dc), ''));
+ }
+ }
+ return lines.join('\n') + '\n';
+}
+
+exports.stringifyDocument = stringifyDocument;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyNumber.d.ts b/MistyCore/node_modules/yaml/dist/stringify/stringifyNumber.d.ts
new file mode 100644
index 0000000..3c14df1
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyNumber.d.ts
@@ -0,0 +1,2 @@
+import type { Scalar } from '../nodes/Scalar.js';
+export declare function stringifyNumber({ format, minFractionDigits, tag, value }: Scalar): string;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyNumber.js b/MistyCore/node_modules/yaml/dist/stringify/stringifyNumber.js
new file mode 100644
index 0000000..4118ff6
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyNumber.js
@@ -0,0 +1,26 @@
+'use strict';
+
+function stringifyNumber({ format, minFractionDigits, tag, value }) {
+ if (typeof value === 'bigint')
+ return String(value);
+ const num = typeof value === 'number' ? value : Number(value);
+ if (!isFinite(num))
+ return isNaN(num) ? '.nan' : num < 0 ? '-.inf' : '.inf';
+ let n = JSON.stringify(value);
+ if (!format &&
+ minFractionDigits &&
+ (!tag || tag === 'tag:yaml.org,2002:float') &&
+ /^\d/.test(n)) {
+ let i = n.indexOf('.');
+ if (i < 0) {
+ i = n.length;
+ n += '.';
+ }
+ let d = minFractionDigits - (n.length - i - 1);
+ while (d-- > 0)
+ n += '0';
+ }
+ return n;
+}
+
+exports.stringifyNumber = stringifyNumber;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyPair.d.ts b/MistyCore/node_modules/yaml/dist/stringify/stringifyPair.d.ts
new file mode 100644
index 0000000..c512149
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyPair.d.ts
@@ -0,0 +1,3 @@
+import type { Pair } from '../nodes/Pair.js';
+import { StringifyContext } from './stringify.js';
+export declare function stringifyPair({ key, value }: Readonly<Pair>, ctx: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyPair.js b/MistyCore/node_modules/yaml/dist/stringify/stringifyPair.js
new file mode 100644
index 0000000..f48a053
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyPair.js
@@ -0,0 +1,127 @@
+'use strict';
+
+var Node = require('../nodes/Node.js');
+var Scalar = require('../nodes/Scalar.js');
+var stringify = require('./stringify.js');
+var stringifyComment = require('./stringifyComment.js');
+
+function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
+ const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
+ let keyComment = (Node.isNode(key) && key.comment) || null;
+ if (simpleKeys) {
+ if (keyComment) {
+ throw new Error('With simple keys, key nodes cannot have comments');
+ }
+ if (Node.isCollection(key)) {
+ const msg = 'With simple keys, collection cannot be used as a key value';
+ throw new Error(msg);
+ }
+ }
+ let explicitKey = !simpleKeys &&
+ (!key ||
+ (keyComment && value == null && !ctx.inFlow) ||
+ Node.isCollection(key) ||
+ (Node.isScalar(key)
+ ? key.type === Scalar.Scalar.BLOCK_FOLDED || key.type === Scalar.Scalar.BLOCK_LITERAL
+ : typeof key === 'object'));
+ ctx = Object.assign({}, ctx, {
+ allNullValues: false,
+ implicitKey: !explicitKey && (simpleKeys || !allNullValues),
+ indent: indent + indentStep
+ });
+ let keyCommentDone = false;
+ let chompKeep = false;
+ let str = stringify.stringify(key, ctx, () => (keyCommentDone = true), () => (chompKeep = true));
+ if (!explicitKey && !ctx.inFlow && str.length > 1024) {
+ if (simpleKeys)
+ throw new Error('With simple keys, single line scalar must not span more than 1024 characters');
+ explicitKey = true;
+ }
+ if (ctx.inFlow) {
+ if (allNullValues || value == null) {
+ if (keyCommentDone && onComment)
+ onComment();
+ return str === '' ? '?' : explicitKey ? `? ${str}` : str;
+ }
+ }
+ else if ((allNullValues && !simpleKeys) || (value == null && explicitKey)) {
+ str = `? ${str}`;
+ if (keyComment && !keyCommentDone) {
+ str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
+ }
+ else if (chompKeep && onChompKeep)
+ onChompKeep();
+ return str;
+ }
+ if (keyCommentDone)
+ keyComment = null;
+ if (explicitKey) {
+ if (keyComment)
+ str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
+ str = `? ${str}\n${indent}:`;
+ }
+ else {
+ str = `${str}:`;
+ if (keyComment)
+ str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
+ }
+ let vcb = '';
+ let valueComment = null;
+ if (Node.isNode(value)) {
+ if (value.spaceBefore)
+ vcb = '\n';
+ if (value.commentBefore) {
+ const cs = commentString(value.commentBefore);
+ vcb += `\n${stringifyComment.indentComment(cs, ctx.indent)}`;
+ }
+ valueComment = value.comment;
+ }
+ else if (value && typeof value === 'object') {
+ value = doc.createNode(value);
+ }
+ ctx.implicitKey = false;
+ if (!explicitKey && !keyComment && Node.isScalar(value))
+ ctx.indentAtStart = str.length + 1;
+ chompKeep = false;
+ if (!indentSeq &&
+ indentStep.length >= 2 &&
+ !ctx.inFlow &&
+ !explicitKey &&
+ Node.isSeq(value) &&
+ !value.flow &&
+ !value.tag &&
+ !value.anchor) {
+ // If indentSeq === false, consider '- ' as part of indentation where possible
+ ctx.indent = ctx.indent.substr(2);
+ }
+ let valueCommentDone = false;
+ const valueStr = stringify.stringify(value, ctx, () => (valueCommentDone = true), () => (chompKeep = true));
+ let ws = ' ';
+ if (vcb || keyComment) {
+ if (valueStr === '' && !ctx.inFlow)
+ ws = vcb === '\n' ? '\n\n' : vcb;
+ else
+ ws = `${vcb}\n${ctx.indent}`;
+ }
+ else if (!explicitKey && Node.isCollection(value)) {
+ const flow = valueStr[0] === '[' || valueStr[0] === '{';
+ if (!flow || valueStr.includes('\n'))
+ ws = `\n${ctx.indent}`;
+ }
+ else if (valueStr === '' || valueStr[0] === '\n')
+ ws = '';
+ str += ws + valueStr;
+ if (ctx.inFlow) {
+ if (valueCommentDone && onComment)
+ onComment();
+ }
+ else if (valueComment && !valueCommentDone) {
+ str += stringifyComment.lineComment(str, ctx.indent, commentString(valueComment));
+ }
+ else if (chompKeep && onChompKeep) {
+ onChompKeep();
+ }
+ return str;
+}
+
+exports.stringifyPair = stringifyPair;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyString.d.ts b/MistyCore/node_modules/yaml/dist/stringify/stringifyString.d.ts
new file mode 100644
index 0000000..a9904b9
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyString.d.ts
@@ -0,0 +1,3 @@
+import { Scalar } from '../nodes/Scalar.js';
+import type { StringifyContext } from './stringify.js';
+export declare function stringifyString(item: Scalar, ctx: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
diff --git a/MistyCore/node_modules/yaml/dist/stringify/stringifyString.js b/MistyCore/node_modules/yaml/dist/stringify/stringifyString.js
new file mode 100644
index 0000000..148a7a8
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/stringify/stringifyString.js
@@ -0,0 +1,316 @@
+'use strict';
+
+var Scalar = require('../nodes/Scalar.js');
+var foldFlowLines = require('./foldFlowLines.js');
+
+const getFoldOptions = (ctx) => ({
+ indentAtStart: ctx.indentAtStart,
+ lineWidth: ctx.options.lineWidth,
+ minContentWidth: ctx.options.minContentWidth
+});
+// Also checks for lines starting with %, as parsing the output as YAML 1.1 will
+// presume that's starting a new document.
+const containsDocumentMarker = (str) => /^(%|---|\.\.\.)/m.test(str);
+function lineLengthOverLimit(str, lineWidth, indentLength) {
+ if (!lineWidth || lineWidth < 0)
+ return false;
+ const limit = lineWidth - indentLength;
+ const strLen = str.length;
+ if (strLen <= limit)
+ return false;
+ for (let i = 0, start = 0; i < strLen; ++i) {
+ if (str[i] === '\n') {
+ if (i - start > limit)
+ return true;
+ start = i + 1;
+ if (strLen - start <= limit)
+ return false;
+ }
+ }
+ return true;
+}
+function doubleQuotedString(value, ctx) {
+ const json = JSON.stringify(value);
+ if (ctx.options.doubleQuotedAsJSON)
+ return json;
+ const { implicitKey } = ctx;
+ const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength;
+ const indent = ctx.indent || (containsDocumentMarker(value) ? ' ' : '');
+ let str = '';
+ let start = 0;
+ for (let i = 0, ch = json[i]; ch; ch = json[++i]) {
+ if (ch === ' ' && json[i + 1] === '\\' && json[i + 2] === 'n') {
+ // space before newline needs to be escaped to not be folded
+ str += json.slice(start, i) + '\\ ';
+ i += 1;
+ start = i;
+ ch = '\\';
+ }
+ if (ch === '\\')
+ switch (json[i + 1]) {
+ case 'u':
+ {
+ str += json.slice(start, i);
+ const code = json.substr(i + 2, 4);
+ switch (code) {
+ case '0000':
+ str += '\\0';
+ break;
+ case '0007':
+ str += '\\a';
+ break;
+ case '000b':
+ str += '\\v';
+ break;
+ case '001b':
+ str += '\\e';
+ break;
+ case '0085':
+ str += '\\N';
+ break;
+ case '00a0':
+ str += '\\_';
+ break;
+ case '2028':
+ str += '\\L';
+ break;
+ case '2029':
+ str += '\\P';
+ break;
+ default:
+ if (code.substr(0, 2) === '00')
+ str += '\\x' + code.substr(2);
+ else
+ str += json.substr(i, 6);
+ }
+ i += 5;
+ start = i + 1;
+ }
+ break;
+ case 'n':
+ if (implicitKey ||
+ json[i + 2] === '"' ||
+ json.length < minMultiLineLength) {
+ i += 1;
+ }
+ else {
+ // folding will eat first newline
+ str += json.slice(start, i) + '\n\n';
+ while (json[i + 2] === '\\' &&
+ json[i + 3] === 'n' &&
+ json[i + 4] !== '"') {
+ str += '\n';
+ i += 2;
+ }
+ str += indent;
+ // space after newline needs to be escaped to not be folded
+ if (json[i + 2] === ' ')
+ str += '\\';
+ i += 1;
+ start = i + 1;
+ }
+ break;
+ default:
+ i += 1;
+ }
+ }
+ str = start ? str + json.slice(start) : json;
+ return implicitKey
+ ? str
+ : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_QUOTED, getFoldOptions(ctx));
+}
+function singleQuotedString(value, ctx) {
+ if (ctx.options.singleQuote === false ||
+ (ctx.implicitKey && value.includes('\n')) ||
+ /[ \t]\n|\n[ \t]/.test(value) // single quoted string can't have leading or trailing whitespace around newline
+ )
+ return doubleQuotedString(value, ctx);
+ const indent = ctx.indent || (containsDocumentMarker(value) ? ' ' : '');
+ const res = "'" + value.replace(/'/g, "''").replace(/\n+/g, `$&\n${indent}`) + "'";
+ return ctx.implicitKey
+ ? res
+ : foldFlowLines.foldFlowLines(res, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx));
+}
+function quotedString(value, ctx) {
+ const { singleQuote } = ctx.options;
+ let qs;
+ if (singleQuote === false)
+ qs = doubleQuotedString;
+ else {
+ const hasDouble = value.includes('"');
+ const hasSingle = value.includes("'");
+ if (hasDouble && !hasSingle)
+ qs = singleQuotedString;
+ else if (hasSingle && !hasDouble)
+ qs = doubleQuotedString;
+ else
+ qs = singleQuote ? singleQuotedString : doubleQuotedString;
+ }
+ return qs(value, ctx);
+}
+function blockString({ comment, type, value }, ctx, onComment, onChompKeep) {
+ const { blockQuote, commentString, lineWidth } = ctx.options;
+ // 1. Block can't end in whitespace unless the last line is non-empty.
+ // 2. Strings consisting of only whitespace are best rendered explicitly.
+ if (!blockQuote || /\n[\t ]+$/.test(value) || /^\s*$/.test(value)) {
+ return quotedString(value, ctx);
+ }
+ const indent = ctx.indent ||
+ (ctx.forceBlockIndent || containsDocumentMarker(value) ? ' ' : '');
+ const literal = blockQuote === 'literal'
+ ? true
+ : blockQuote === 'folded' || type === Scalar.Scalar.BLOCK_FOLDED
+ ? false
+ : type === Scalar.Scalar.BLOCK_LITERAL
+ ? true
+ : !lineLengthOverLimit(value, lineWidth, indent.length);
+ if (!value)
+ return literal ? '|\n' : '>\n';
+ // determine chomping from whitespace at value end
+ let chomp;
+ let endStart;
+ for (endStart = value.length; endStart > 0; --endStart) {
+ const ch = value[endStart - 1];
+ if (ch !== '\n' && ch !== '\t' && ch !== ' ')
+ break;
+ }
+ let end = value.substring(endStart);
+ const endNlPos = end.indexOf('\n');
+ if (endNlPos === -1) {
+ chomp = '-'; // strip
+ }
+ else if (value === end || endNlPos !== end.length - 1) {
+ chomp = '+'; // keep
+ if (onChompKeep)
+ onChompKeep();
+ }
+ else {
+ chomp = ''; // clip
+ }
+ if (end) {
+ value = value.slice(0, -end.length);
+ if (end[end.length - 1] === '\n')
+ end = end.slice(0, -1);
+ end = end.replace(/\n+(?!\n|$)/g, `$&${indent}`);
+ }
+ // determine indent indicator from whitespace at value start
+ let startWithSpace = false;
+ let startEnd;
+ let startNlPos = -1;
+ for (startEnd = 0; startEnd < value.length; ++startEnd) {
+ const ch = value[startEnd];
+ if (ch === ' ')
+ startWithSpace = true;
+ else if (ch === '\n')
+ startNlPos = startEnd;
+ else
+ break;
+ }
+ let start = value.substring(0, startNlPos < startEnd ? startNlPos + 1 : startEnd);
+ if (start) {
+ value = value.substring(start.length);
+ start = start.replace(/\n+/g, `$&${indent}`);
+ }
+ const indentSize = indent ? '2' : '1'; // root is at -1
+ let header = (literal ? '|' : '>') + (startWithSpace ? indentSize : '') + chomp;
+ if (comment) {
+ header += ' ' + commentString(comment.replace(/ ?[\r\n]+/g, ' '));
+ if (onComment)
+ onComment();
+ }
+ if (literal) {
+ value = value.replace(/\n+/g, `$&${indent}`);
+ return `${header}\n${indent}${start}${value}${end}`;
+ }
+ value = value
+ .replace(/\n+/g, '\n$&')
+ .replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, '$1$2') // more-indented lines aren't folded
+ // ^ more-ind. ^ empty ^ capture next empty lines only at end of indent
+ .replace(/\n+/g, `$&${indent}`);
+ const body = foldFlowLines.foldFlowLines(`${start}${value}${end}`, indent, foldFlowLines.FOLD_BLOCK, getFoldOptions(ctx));
+ return `${header}\n${indent}${body}`;
+}
+function plainString(item, ctx, onComment, onChompKeep) {
+ const { type, value } = item;
+ const { actualString, implicitKey, indent, inFlow } = ctx;
+ if ((implicitKey && /[\n[\]{},]/.test(value)) ||
+ (inFlow && /[[\]{},]/.test(value))) {
+ return quotedString(value, ctx);
+ }
+ if (!value ||
+ /^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) {
+ // not allowed:
+ // - empty string, '-' or '?'
+ // - start with an indicator character (except [?:-]) or /[?-] /
+ // - '\n ', ': ' or ' \n' anywhere
+ // - '#' not preceded by a non-space char
+ // - end with ' ' or ':'
+ return implicitKey || inFlow || !value.includes('\n')
+ ? quotedString(value, ctx)
+ : blockString(item, ctx, onComment, onChompKeep);
+ }
+ if (!implicitKey &&
+ !inFlow &&
+ type !== Scalar.Scalar.PLAIN &&
+ value.includes('\n')) {
+ // Where allowed & type not set explicitly, prefer block style for multiline strings
+ return blockString(item, ctx, onComment, onChompKeep);
+ }
+ if (indent === '' && containsDocumentMarker(value)) {
+ ctx.forceBlockIndent = true;
+ return blockString(item, ctx, onComment, onChompKeep);
+ }
+ const str = value.replace(/\n+/g, `$&\n${indent}`);
+ // Verify that output will be parsed as a string, as e.g. plain numbers and
+ // booleans get parsed with those types in v1.2 (e.g. '42', 'true' & '0.9e-3'),
+ // and others in v1.1.
+ if (actualString) {
+ const test = (tag) => tag.default && tag.tag !== 'tag:yaml.org,2002:str' && tag.test?.test(str);
+ const { compat, tags } = ctx.doc.schema;
+ if (tags.some(test) || compat?.some(test))
+ return quotedString(value, ctx);
+ }
+ return implicitKey
+ ? str
+ : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx));
+}
+function stringifyString(item, ctx, onComment, onChompKeep) {
+ const { implicitKey, inFlow } = ctx;
+ const ss = typeof item.value === 'string'
+ ? item
+ : Object.assign({}, item, { value: String(item.value) });
+ let { type } = item;
+ if (type !== Scalar.Scalar.QUOTE_DOUBLE) {
+ // force double quotes on control characters & unpaired surrogates
+ if (/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(ss.value))
+ type = Scalar.Scalar.QUOTE_DOUBLE;
+ }
+ const _stringify = (_type) => {
+ switch (_type) {
+ case Scalar.Scalar.BLOCK_FOLDED:
+ case Scalar.Scalar.BLOCK_LITERAL:
+ return implicitKey || inFlow
+ ? quotedString(ss.value, ctx) // blocks are not valid inside flow containers
+ : blockString(ss, ctx, onComment, onChompKeep);
+ case Scalar.Scalar.QUOTE_DOUBLE:
+ return doubleQuotedString(ss.value, ctx);
+ case Scalar.Scalar.QUOTE_SINGLE:
+ return singleQuotedString(ss.value, ctx);
+ case Scalar.Scalar.PLAIN:
+ return plainString(ss, ctx, onComment, onChompKeep);
+ default:
+ return null;
+ }
+ };
+ let res = _stringify(type);
+ if (res === null) {
+ const { defaultKeyType, defaultStringType } = ctx.options;
+ const t = (implicitKey && defaultKeyType) || defaultStringType;
+ res = _stringify(t);
+ if (res === null)
+ throw new Error(`Unsupported default string type ${t}`);
+ }
+ return res;
+}
+
+exports.stringifyString = stringifyString;
diff --git a/MistyCore/node_modules/yaml/dist/test-events.d.ts b/MistyCore/node_modules/yaml/dist/test-events.d.ts
new file mode 100644
index 0000000..d1a2348
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/test-events.d.ts
@@ -0,0 +1,4 @@
+export declare function testEvents(src: string): {
+ events: string[];
+ error: unknown;
+};
diff --git a/MistyCore/node_modules/yaml/dist/test-events.js b/MistyCore/node_modules/yaml/dist/test-events.js
new file mode 100644
index 0000000..2c9220a
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/test-events.js
@@ -0,0 +1,134 @@
+'use strict';
+
+var Node = require('./nodes/Node.js');
+var publicApi = require('./public-api.js');
+var visit = require('./visit.js');
+
+const scalarChar = {
+ BLOCK_FOLDED: '>',
+ BLOCK_LITERAL: '|',
+ PLAIN: ':',
+ QUOTE_DOUBLE: '"',
+ QUOTE_SINGLE: "'"
+};
+function anchorExists(doc, anchor) {
+ let found = false;
+ visit.visit(doc, {
+ Value(_key, node) {
+ if (node.anchor === anchor) {
+ found = true;
+ return visit.visit.BREAK;
+ }
+ }
+ });
+ return found;
+}
+// test harness for yaml-test-suite event tests
+function testEvents(src) {
+ const docs = publicApi.parseAllDocuments(src);
+ const errDoc = docs.find(doc => doc.errors.length > 0);
+ const error = errDoc ? errDoc.errors[0].message : null;
+ const events = ['+STR'];
+ try {
+ for (let i = 0; i < docs.length; ++i) {
+ const doc = docs[i];
+ let root = doc.contents;
+ if (Array.isArray(root))
+ root = root[0];
+ const [rootStart] = doc.range || [0];
+ const error = doc.errors[0];
+ if (error && (!error.pos || error.pos[0] < rootStart))
+ throw new Error();
+ let docStart = '+DOC';
+ if (doc.directives.docStart)
+ docStart += ' ---';
+ else if (doc.contents &&
+ doc.contents.range[2] === doc.contents.range[0] &&
+ !doc.contents.anchor &&
+ !doc.contents.tag)
+ continue;
+ events.push(docStart);
+ addEvents(events, doc, error?.pos[0] ?? -1, root);
+ let docEnd = '-DOC';
+ if (doc.directives.docEnd)
+ docEnd += ' ...';
+ events.push(docEnd);
+ }
+ }
+ catch (e) {
+ return { events, error: error ?? e };
+ }
+ events.push('-STR');
+ return { events, error };
+}
+function addEvents(events, doc, errPos, node) {
+ if (!node) {
+ events.push('=VAL :');
+ return;
+ }
+ if (errPos !== -1 && Node.isNode(node) && node.range[0] >= errPos)
+ throw new Error();
+ let props = '';
+ let anchor = Node.isScalar(node) || Node.isCollection(node) ? node.anchor : undefined;
+ if (anchor) {
+ if (/\d$/.test(anchor)) {
+ const alt = anchor.replace(/\d$/, '');
+ if (anchorExists(doc, alt))
+ anchor = alt;
+ }
+ props = ` &${anchor}`;
+ }
+ if (Node.isNode(node) && node.tag)
+ props += ` <${node.tag}>`;
+ if (Node.isMap(node)) {
+ const ev = node.flow ? '+MAP {}' : '+MAP';
+ events.push(`${ev}${props}`);
+ node.items.forEach(({ key, value }) => {
+ addEvents(events, doc, errPos, key);
+ addEvents(events, doc, errPos, value);
+ });
+ events.push('-MAP');
+ }
+ else if (Node.isSeq(node)) {
+ const ev = node.flow ? '+SEQ []' : '+SEQ';
+ events.push(`${ev}${props}`);
+ node.items.forEach(item => {
+ addEvents(events, doc, errPos, item);
+ });
+ events.push('-SEQ');
+ }
+ else if (Node.isPair(node)) {
+ events.push(`+MAP${props}`);
+ addEvents(events, doc, errPos, node.key);
+ addEvents(events, doc, errPos, node.value);
+ events.push('-MAP');
+ }
+ else if (Node.isAlias(node)) {
+ let alias = node.source;
+ if (alias && /\d$/.test(alias)) {
+ const alt = alias.replace(/\d$/, '');
+ if (anchorExists(doc, alt))
+ alias = alt;
+ }
+ events.push(`=ALI${props} *${alias}`);
+ }
+ else {
+ const scalar = scalarChar[String(node.type)];
+ if (!scalar)
+ throw new Error(`Unexpected node type ${node.type}`);
+ const value = node.source
+ .replace(/\\/g, '\\\\')
+ .replace(/\0/g, '\\0')
+ .replace(/\x07/g, '\\a')
+ .replace(/\x08/g, '\\b')
+ .replace(/\t/g, '\\t')
+ .replace(/\n/g, '\\n')
+ .replace(/\v/g, '\\v')
+ .replace(/\f/g, '\\f')
+ .replace(/\r/g, '\\r')
+ .replace(/\x1b/g, '\\e');
+ events.push(`=VAL${props} ${scalar}${value}`);
+ }
+}
+
+exports.testEvents = testEvents;
diff --git a/MistyCore/node_modules/yaml/dist/util.d.ts b/MistyCore/node_modules/yaml/dist/util.d.ts
new file mode 100644
index 0000000..f1012d7
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/util.d.ts
@@ -0,0 +1,9 @@
+export { debug, LogLevelId, warn } from './log.js';
+export { findPair } from './nodes/YAMLMap.js';
+export { toJS, ToJSContext } from './nodes/toJS.js';
+export { map as mapTag } from './schema/common/map.js';
+export { seq as seqTag } from './schema/common/seq.js';
+export { string as stringTag } from './schema/common/string.js';
+export { foldFlowLines } from './stringify/foldFlowLines';
+export { stringifyNumber } from './stringify/stringifyNumber.js';
+export { stringifyString } from './stringify/stringifyString.js';
diff --git a/MistyCore/node_modules/yaml/dist/util.js b/MistyCore/node_modules/yaml/dist/util.js
new file mode 100644
index 0000000..9a38c10
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/util.js
@@ -0,0 +1,24 @@
+'use strict';
+
+var log = require('./log.js');
+var YAMLMap = require('./nodes/YAMLMap.js');
+var toJS = require('./nodes/toJS.js');
+var map = require('./schema/common/map.js');
+var seq = require('./schema/common/seq.js');
+var string = require('./schema/common/string.js');
+var foldFlowLines = require('./stringify/foldFlowLines.js');
+var stringifyNumber = require('./stringify/stringifyNumber.js');
+var stringifyString = require('./stringify/stringifyString.js');
+
+
+
+exports.debug = log.debug;
+exports.warn = log.warn;
+exports.findPair = YAMLMap.findPair;
+exports.toJS = toJS.toJS;
+exports.mapTag = map.map;
+exports.seqTag = seq.seq;
+exports.stringTag = string.string;
+exports.foldFlowLines = foldFlowLines.foldFlowLines;
+exports.stringifyNumber = stringifyNumber.stringifyNumber;
+exports.stringifyString = stringifyString.stringifyString;
diff --git a/MistyCore/node_modules/yaml/dist/visit.d.ts b/MistyCore/node_modules/yaml/dist/visit.d.ts
new file mode 100644
index 0000000..7926c00
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/visit.d.ts
@@ -0,0 +1,102 @@
+import type { Document } from './doc/Document.js';
+import type { Alias } from './nodes/Alias.js';
+import { Node } from './nodes/Node.js';
+import type { Pair } from './nodes/Pair.js';
+import type { Scalar } from './nodes/Scalar.js';
+import type { YAMLMap } from './nodes/YAMLMap.js';
+import type { YAMLSeq } from './nodes/YAMLSeq.js';
+export declare type visitorFn<T> = (key: number | 'key' | 'value' | null, node: T, path: readonly (Document | Node | Pair)[]) => void | symbol | number | Node | Pair;
+export declare type visitor = visitorFn<unknown> | {
+ Alias?: visitorFn<Alias>;
+ Collection?: visitorFn<YAMLMap | YAMLSeq>;
+ Map?: visitorFn<YAMLMap>;
+ Node?: visitorFn<Alias | Scalar | YAMLMap | YAMLSeq>;
+ Pair?: visitorFn<Pair>;
+ Scalar?: visitorFn<Scalar>;
+ Seq?: visitorFn<YAMLSeq>;
+ Value?: visitorFn<Scalar | YAMLMap | YAMLSeq>;
+};
+export declare type asyncVisitorFn<T> = (key: number | 'key' | 'value' | null, node: T, path: readonly (Document | Node | Pair)[]) => void | symbol | number | Node | Pair | Promise<void | symbol | number | Node | Pair>;
+export declare type asyncVisitor = asyncVisitorFn<unknown> | {
+ Alias?: asyncVisitorFn<Alias>;
+ Collection?: asyncVisitorFn<YAMLMap | YAMLSeq>;
+ Map?: asyncVisitorFn<YAMLMap>;
+ Node?: asyncVisitorFn<Alias | Scalar | YAMLMap | YAMLSeq>;
+ Pair?: asyncVisitorFn<Pair>;
+ Scalar?: asyncVisitorFn<Scalar>;
+ Seq?: asyncVisitorFn<YAMLSeq>;
+ Value?: asyncVisitorFn<Scalar | YAMLMap | YAMLSeq>;
+};
+/**
+ * Apply a visitor to an AST node or document.
+ *
+ * Walks through the tree (depth-first) starting from `node`, calling a
+ * `visitor` function with three arguments:
+ * - `key`: For sequence values and map `Pair`, the node's index in the
+ * collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
+ * `null` for the root node.
+ * - `node`: The current node.
+ * - `path`: The ancestry of the current node.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this node, continue with next
+ * sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current node, then continue with the next one
+ * - `Node`: Replace the current node, then continue by visiting it
+ * - `number`: While iterating the items of a sequence or map, set the index
+ * of the next step. This is useful especially if the index of the current
+ * node has changed.
+ *
+ * If `visitor` is a single function, it will be called with all values
+ * encountered in the tree, including e.g. `null` values. Alternatively,
+ * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
+ * `Alias` and `Scalar` node. To define the same visitor function for more than
+ * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
+ * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
+ * specific defined one will be used for each node.
+ */
+export declare function visit(node: Node | Document | null, visitor: visitor): void;
+export declare namespace visit {
+ var BREAK: symbol;
+ var SKIP: symbol;
+ var REMOVE: symbol;
+}
+/**
+ * Apply an async visitor to an AST node or document.
+ *
+ * Walks through the tree (depth-first) starting from `node`, calling a
+ * `visitor` function with three arguments:
+ * - `key`: For sequence values and map `Pair`, the node's index in the
+ * collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
+ * `null` for the root node.
+ * - `node`: The current node.
+ * - `path`: The ancestry of the current node.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `Promise`: Must resolve to one of the following values
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this node, continue with next
+ * sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current node, then continue with the next one
+ * - `Node`: Replace the current node, then continue by visiting it
+ * - `number`: While iterating the items of a sequence or map, set the index
+ * of the next step. This is useful especially if the index of the current
+ * node has changed.
+ *
+ * If `visitor` is a single function, it will be called with all values
+ * encountered in the tree, including e.g. `null` values. Alternatively,
+ * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
+ * `Alias` and `Scalar` node. To define the same visitor function for more than
+ * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
+ * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
+ * specific defined one will be used for each node.
+ */
+export declare function visitAsync(node: Node | Document | null, visitor: asyncVisitor): Promise<void>;
+export declare namespace visitAsync {
+ var BREAK: symbol;
+ var SKIP: symbol;
+ var REMOVE: symbol;
+}
diff --git a/MistyCore/node_modules/yaml/dist/visit.js b/MistyCore/node_modules/yaml/dist/visit.js
new file mode 100644
index 0000000..1f3db46
--- /dev/null
+++ b/MistyCore/node_modules/yaml/dist/visit.js
@@ -0,0 +1,236 @@
+'use strict';
+
+var Node = require('./nodes/Node.js');
+
+const BREAK = Symbol('break visit');
+const SKIP = Symbol('skip children');
+const REMOVE = Symbol('remove node');
+/**
+ * Apply a visitor to an AST node or document.
+ *
+ * Walks through the tree (depth-first) starting from `node`, calling a
+ * `visitor` function with three arguments:
+ * - `key`: For sequence values and map `Pair`, the node's index in the
+ * collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
+ * `null` for the root node.
+ * - `node`: The current node.
+ * - `path`: The ancestry of the current node.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this node, continue with next
+ * sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current node, then continue with the next one
+ * - `Node`: Replace the current node, then continue by visiting it
+ * - `number`: While iterating the items of a sequence or map, set the index
+ * of the next step. This is useful especially if the index of the current
+ * node has changed.
+ *
+ * If `visitor` is a single function, it will be called with all values
+ * encountered in the tree, including e.g. `null` values. Alternatively,
+ * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
+ * `Alias` and `Scalar` node. To define the same visitor function for more than
+ * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
+ * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
+ * specific defined one will be used for each node.
+ */
+function visit(node, visitor) {
+ const visitor_ = initVisitor(visitor);
+ if (Node.isDocument(node)) {
+ const cd = visit_(null, node.contents, visitor_, Object.freeze([node]));
+ if (cd === REMOVE)
+ node.contents = null;
+ }
+ else
+ visit_(null, node, visitor_, Object.freeze([]));
+}
+// Without the `as symbol` casts, TS declares these in the `visit`
+// namespace using `var`, but then complains about that because
+// `unique symbol` must be `const`.
+/** Terminate visit traversal completely */
+visit.BREAK = BREAK;
+/** Do not visit the children of the current node */
+visit.SKIP = SKIP;
+/** Remove the current node */
+visit.REMOVE = REMOVE;
+function visit_(key, node, visitor, path) {
+ const ctrl = callVisitor(key, node, visitor, path);
+ if (Node.isNode(ctrl) || Node.isPair(ctrl)) {
+ replaceNode(key, path, ctrl);
+ return visit_(key, ctrl, visitor, path);
+ }
+ if (typeof ctrl !== 'symbol') {
+ if (Node.isCollection(node)) {
+ path = Object.freeze(path.concat(node));
+ for (let i = 0; i < node.items.length; ++i) {
+ const ci = visit_(i, node.items[i], visitor, path);
+ if (typeof ci === 'number')
+ i = ci - 1;
+ else if (ci === BREAK)
+ return BREAK;
+ else if (ci === REMOVE) {
+ node.items.splice(i, 1);
+ i -= 1;
+ }
+ }
+ }
+ else if (Node.isPair(node)) {
+ path = Object.freeze(path.concat(node));
+ const ck = visit_('key', node.key, visitor, path);
+ if (ck === BREAK)
+ return BREAK;
+ else if (ck === REMOVE)
+ node.key = null;
+ const cv = visit_('value', node.value, visitor, path);
+ if (cv === BREAK)
+ return BREAK;
+ else if (cv === REMOVE)
+ node.value = null;
+ }
+ }
+ return ctrl;
+}
+/**
+ * Apply an async visitor to an AST node or document.
+ *
+ * Walks through the tree (depth-first) starting from `node`, calling a
+ * `visitor` function with three arguments:
+ * - `key`: For sequence values and map `Pair`, the node's index in the
+ * collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
+ * `null` for the root node.
+ * - `node`: The current node.
+ * - `path`: The ancestry of the current node.
+ *
+ * The return value of the visitor may be used to control the traversal:
+ * - `Promise`: Must resolve to one of the following values
+ * - `undefined` (default): Do nothing and continue
+ * - `visit.SKIP`: Do not visit the children of this node, continue with next
+ * sibling
+ * - `visit.BREAK`: Terminate traversal completely
+ * - `visit.REMOVE`: Remove the current node, then continue with the next one
+ * - `Node`: Replace the current node, then continue by visiting it
+ * - `number`: While iterating the items of a sequence or map, set the index
+ * of the next step. This is useful especially if the index of the current
+ * node has changed.
+ *
+ * If `visitor` is a single function, it will be called with all values
+ * encountered in the tree, including e.g. `null` values. Alternatively,
+ * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
+ * `Alias` and `Scalar` node. To define the same visitor function for more than
+ * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
+ * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
+ * specific defined one will be used for each node.
+ */
+async function visitAsync(node, visitor) {
+ const visitor_ = initVisitor(visitor);
+ if (Node.isDocument(node)) {
+ const cd = await visitAsync_(null, node.contents, visitor_, Object.freeze([node]));
+ if (cd === REMOVE)
+ node.contents = null;
+ }
+ else
+ await visitAsync_(null, node, visitor_, Object.freeze([]));
+}
+// Without the `as symbol` casts, TS declares these in the `visit`
+// namespace using `var`, but then complains about that because
+// `unique symbol` must be `const`.
+/** Terminate visit traversal completely */
+visitAsync.BREAK = BREAK;
+/** Do not visit the children of the current node */
+visitAsync.SKIP = SKIP;
+/** Remove the current node */
+visitAsync.REMOVE = REMOVE;
+async function visitAsync_(key, node, visitor, path) {
+ const ctrl = await callVisitor(key, node, visitor, path);
+ if (Node.isNode(ctrl) || Node.isPair(ctrl)) {
+ replaceNode(key, path, ctrl);
+ return visitAsync_(key, ctrl, visitor, path);
+ }
+ if (typeof ctrl !== 'symbol') {
+ if (Node.isCollection(node)) {
+ path = Object.freeze(path.concat(node));
+ for (let i = 0; i < node.items.length; ++i) {
+ const ci = await visitAsync_(i, node.items[i], visitor, path);
+ if (typeof ci === 'number')
+ i = ci - 1;
+ else if (ci === BREAK)
+ return BREAK;
+ else if (ci === REMOVE) {
+ node.items.splice(i, 1);
+ i -= 1;
+ }
+ }
+ }
+ else if (Node.isPair(node)) {
+ path = Object.freeze(path.concat(node));
+ const ck = await visitAsync_('key', node.key, visitor, path);
+ if (ck === BREAK)
+ return BREAK;
+ else if (ck === REMOVE)
+ node.key = null;
+ const cv = await visitAsync_('value', node.value, visitor, path);
+ if (cv === BREAK)
+ return BREAK;
+ else if (cv === REMOVE)
+ node.value = null;
+ }
+ }
+ return ctrl;
+}
+function initVisitor(visitor) {
+ if (typeof visitor === 'object' &&
+ (visitor.Collection || visitor.Node || visitor.Value)) {
+ return Object.assign({
+ Alias: visitor.Node,
+ Map: visitor.Node,
+ Scalar: visitor.Node,
+ Seq: visitor.Node
+ }, visitor.Value && {
+ Map: visitor.Value,
+ Scalar: visitor.Value,
+ Seq: visitor.Value
+ }, visitor.Collection && {
+ Map: visitor.Collection,
+ Seq: visitor.Collection
+ }, visitor);
+ }
+ return visitor;
+}
+function callVisitor(key, node, visitor, path) {
+ if (typeof visitor === 'function')
+ return visitor(key, node, path);
+ if (Node.isMap(node))
+ return visitor.Map?.(key, node, path);
+ if (Node.isSeq(node))
+ return visitor.Seq?.(key, node, path);
+ if (Node.isPair(node))
+ return visitor.Pair?.(key, node, path);
+ if (Node.isScalar(node))
+ return visitor.Scalar?.(key, node, path);
+ if (Node.isAlias(node))
+ return visitor.Alias?.(key, node, path);
+ return undefined;
+}
+function replaceNode(key, path, node) {
+ const parent = path[path.length - 1];
+ if (Node.isCollection(parent)) {
+ parent.items[key] = node;
+ }
+ else if (Node.isPair(parent)) {
+ if (key === 'key')
+ parent.key = node;
+ else
+ parent.value = node;
+ }
+ else if (Node.isDocument(parent)) {
+ parent.contents = node;
+ }
+ else {
+ const pt = Node.isAlias(parent) ? 'alias' : 'scalar';
+ throw new Error(`Cannot replace node with ${pt} parent`);
+ }
+}
+
+exports.visit = visit;
+exports.visitAsync = visitAsync;
diff --git a/MistyCore/node_modules/yaml/package.json b/MistyCore/node_modules/yaml/package.json
new file mode 100644
index 0000000..280e040
--- /dev/null
+++ b/MistyCore/node_modules/yaml/package.json
@@ -0,0 +1,94 @@
+{
+ "name": "yaml",
+ "version": "2.1.3",
+ "license": "ISC",
+ "author": "Eemeli Aro <eemeli@gmail.com>",
+ "repository": "github:eemeli/yaml",
+ "description": "JavaScript parser and stringifier for YAML",
+ "keywords": [
+ "YAML",
+ "parser",
+ "stringifier"
+ ],
+ "homepage": "https://eemeli.org/yaml/",
+ "files": [
+ "browser/",
+ "dist/",
+ "util.d.ts",
+ "util.js"
+ ],
+ "type": "commonjs",
+ "main": "./dist/index.js",
+ "browser": {
+ "./dist/index.js": "./browser/index.js",
+ "./dist/util.js": "./browser/dist/util.js",
+ "./util.js": "./browser/dist/util.js"
+ },
+ "exports": {
+ ".": {
+ "node": "./dist/index.js",
+ "default": "./browser/index.js"
+ },
+ "./package.json": "./package.json",
+ "./util": {
+ "node": "./dist/util.js",
+ "default": "./browser/dist/util.js"
+ }
+ },
+ "scripts": {
+ "build": "npm run build:node && npm run build:browser",
+ "build:browser": "rollup -c config/rollup.browser-config.js",
+ "build:node": "rollup -c config/rollup.node-config.js",
+ "clean": "git clean -fdxe node_modules",
+ "lint": "eslint src/",
+ "prettier": "prettier --write .",
+ "prestart": "npm run build:node",
+ "start": "node -i -e 'YAML=require(\"./dist/index.js\")'",
+ "test": "jest --config config/jest.config.js",
+ "test:all": "npm test && npm run test:types && npm run test:dist && npm run test:dist:types",
+ "test:browsers": "cd playground && npm test",
+ "test:dist": "npm run build:node && jest --config config/jest.config.js",
+ "test:dist:types": "tsc --allowJs --moduleResolution node --noEmit --target es5 dist/index.js",
+ "test:types": "tsc --noEmit",
+ "docs:install": "cd docs-slate && bundle install",
+ "docs:deploy": "cd docs-slate && ./deploy.sh",
+ "docs": "cd docs-slate && bundle exec middleman server",
+ "preversion": "npm test && npm run build",
+ "prepublishOnly": "npm run clean && npm test && npm run build"
+ },
+ "browserslist": "defaults, not ie 11",
+ "prettier": {
+ "arrowParens": "avoid",
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "none"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.12.10",
+ "@babel/plugin-proposal-class-properties": "^7.12.1",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1",
+ "@babel/plugin-transform-typescript": "^7.12.17",
+ "@babel/preset-env": "^7.12.11",
+ "@rollup/plugin-babel": "^5.2.3",
+ "@rollup/plugin-replace": "^4.0.0",
+ "@rollup/plugin-typescript": "^8.1.1",
+ "@types/jest": "^28.1.8",
+ "@types/node": "^12.20.47",
+ "@typescript-eslint/eslint-plugin": "^5.3.1",
+ "@typescript-eslint/parser": "^5.3.1",
+ "babel-jest": "^29.0.1",
+ "cross-env": "^7.0.3",
+ "eslint": "^8.2.0",
+ "eslint-config-prettier": "^8.1.0",
+ "fast-check": "^2.12.0",
+ "jest": "^29.0.1",
+ "jest-ts-webcompat-resolver": "^1.0.0",
+ "prettier": "^2.2.1",
+ "rollup": "^2.38.2",
+ "tslib": "^2.1.0",
+ "typescript": "^4.3.5"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+}
diff --git a/MistyCore/node_modules/yaml/util.d.ts b/MistyCore/node_modules/yaml/util.d.ts
new file mode 100644
index 0000000..c656480
--- /dev/null
+++ b/MistyCore/node_modules/yaml/util.d.ts
@@ -0,0 +1,3 @@
+// Workaround for incomplete exports support in TypeScript
+// https://github.com/microsoft/TypeScript/issues/33079
+export * from './dist/util.js'
diff --git a/MistyCore/node_modules/yaml/util.js b/MistyCore/node_modules/yaml/util.js
new file mode 100644
index 0000000..070103f
--- /dev/null
+++ b/MistyCore/node_modules/yaml/util.js
@@ -0,0 +1,2 @@
+// Re-exporter for Node.js < 12.16.0
+module.exports = require('./dist/util.js')
diff --git a/MistyCore/package-lock.json b/MistyCore/package-lock.json
new file mode 100644
index 0000000..ce45afb
--- /dev/null
+++ b/MistyCore/package-lock.json
@@ -0,0 +1,218 @@
+{
+ "name": "MistyCore",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "semver": "^7.3.8",
+ "systeminformation": "^5.12.11",
+ "yaml": "^2.1.3"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/systeminformation": {
+ "version": "5.12.11",
+ "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.12.11.tgz",
+ "integrity": "sha512-4N5nT4BFWqRyadTLO8c/t8/gM6wqgg26/WNjjZCS/UU7VuURuBy/pR6Z6+j0nD3ff+zCpX/sdVfyn+EoIg9saQ==",
+ "os": [
+ "darwin",
+ "linux",
+ "win32",
+ "freebsd",
+ "openbsd",
+ "netbsd",
+ "sunos",
+ "android"
+ ],
+ "bin": {
+ "systeminformation": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ },
+ "funding": {
+ "type": "Buy me a coffee",
+ "url": "https://www.buymeacoffee.com/systeminfo"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/yaml": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
+ "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
+ "engines": {
+ "node": ">= 14"
+ }
+ }
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "systeminformation": {
+ "version": "5.12.11",
+ "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.12.11.tgz",
+ "integrity": "sha512-4N5nT4BFWqRyadTLO8c/t8/gM6wqgg26/WNjjZCS/UU7VuURuBy/pR6Z6+j0nD3ff+zCpX/sdVfyn+EoIg9saQ=="
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "yaml": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
+ "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg=="
+ }
+ }
+}
diff --git a/MistyCore/package.json b/MistyCore/package.json
new file mode 100644
index 0000000..dfecfd5
--- /dev/null
+++ b/MistyCore/package.json
@@ -0,0 +1,8 @@
+{
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "semver": "^7.3.8",
+ "systeminformation": "^5.12.11",
+ "yaml": "^2.1.3"
+ }
+}
diff --git a/MistyCore/power.js b/MistyCore/power.js
new file mode 100644
index 0000000..2fce421
--- /dev/null
+++ b/MistyCore/power.js
@@ -0,0 +1,128 @@
+const child_process = require('child_process');
+const chalk = require('chalk');
+const fs = require("fs");
+
+function waitForState(daemon, status) {
+ return new Promise((resolve, reject) => {
+ let i = 0;
+ let me = setInterval(() => {
+ if (status === "running") {
+ if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() !== "-1") {
+ clearInterval(me);
+
+ if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() !== "0") {
+ resolve();
+ } else if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() !== "-2") {
+ reject();
+ } else {
+ resolve();
+ }
+ }
+ } else if (status === "stopped") {
+ if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() === "-1") {
+ clearInterval(me);
+ resolve();
+ }
+ if (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString().trim() === "-2") {
+ clearInterval(me);
+ reject();
+ }
+ } else {
+ clearInterval(me);
+ resolve();
+ }
+
+ if (i >= 100) {
+ reject();
+ }
+
+ i++;
+ }, 100);
+ });
+}
+
+module.exports = async (reboot) => {
+ log("MistyCore", "Beginning shut down process");
+ if (global.uiProcess) {
+ global.uiProcess.kill("SIGKILL");
+ log("MistyCore", "Terminated UI process");
+ }
+
+ console.clear();
+
+ log("MistyCore", "Showing banner");
+
+ require('./banner')();
+
+ console.log("");
+ console.log("MistyOS is shutting down...");
+ process.stdout.write(" Unloading MistyCore...");
+
+ log("MistyCore", "Done showing banner");
+ log("MistyCore-Startup", "Stopping running services...");
+
+ for (let name of fs.readdirSync(systemRoot + "/LaunchDaemons")) {
+ let daemon = name.substring(0, name.length - 4);
+
+ if (fs.existsSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon)) {
+ let state;
+ switch (fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + daemon).toString()) {
+ case "0":
+ state = "running";
+ break;
+ case "-1":
+ state = "stopped";
+ break;
+ case "-3":
+ state = "starting";
+ break;
+ case "-2":
+ state = "failed";
+ break;
+ default:
+ state = "running";
+ break
+ }
+
+ if (state === "running" || state === "starting") {
+ process.stdout.write("\n Stopping launch daemon: " + daemon + "...");
+ services.stop(name);
+
+ try {
+ await waitForState(daemon, "stopped");
+ process.stdout.write(chalk.green(" Success"));
+ } catch (e) {
+ process.stdout.write(chalk.yellow(" Failure"));
+
+ process.stdout.write("\n Force-stopping launch daemon: " + daemon + "...");
+ services.stop(name, true);
+
+ try {
+ await waitForState(daemon, "stopped");
+ process.stdout.write(chalk.green(" Success"));
+ } catch (e) {
+ process.stdout.write(chalk.yellow(" Failure"));
+ }
+ }
+ }
+ }
+ }
+
+ log("MistyCore", "Syncing disks");
+ process.stdout.write("\n Syncing disks...");
+ child_process.execSync('echo "s" > /System/Volumes/FieldService/sysrq-trigger');
+ process.stdout.write(chalk.green(" Success\n"));
+
+ if (reboot) {
+ log("MistyCore", "Reached reboot");
+ process.stdout.write(" Restarting machine...");
+ child_process.execSync('echo "b" > /System/Volumes/FieldService/sysrq-trigger');
+ process.stdout.write(chalk.green(" Success\n"));
+ } else {
+ log("MistyCore", "Reached shutdown");
+ process.stdout.write(" Powering off machine...");
+ child_process.execSync('echo "o" > /System/Volumes/FieldService/sysrq-trigger');
+ process.stdout.write(chalk.green(" Success\n"));
+ process.stdout.write(" It is now safe to turn off your computer.");
+ }
+} \ No newline at end of file
diff --git a/MistyCore/power/reboot.js b/MistyCore/power/reboot.js
new file mode 100644
index 0000000..5346421
--- /dev/null
+++ b/MistyCore/power/reboot.js
@@ -0,0 +1,12 @@
+let net = require('net');
+let systemRoot = "/System/Library";
+const socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", () => {
+ socket.write(JSON.stringify({
+ action: "REBOOT",
+ payload: {}
+ }));
+ socket.on('close', () => {
+ process.exit();
+ });
+ socket.destroy();
+}); \ No newline at end of file
diff --git a/MistyCore/power/shutdown.js b/MistyCore/power/shutdown.js
new file mode 100644
index 0000000..855e156
--- /dev/null
+++ b/MistyCore/power/shutdown.js
@@ -0,0 +1,12 @@
+let net = require('net');
+let systemRoot = "/System/Library";
+const socket = net.createConnection(systemRoot + "/../Volumes/VM/MistyCore-Socket", () => {
+ socket.write(JSON.stringify({
+ action: "SHUTDOWN",
+ payload: {}
+ }));
+ socket.on('close', () => {
+ process.exit();
+ });
+ socket.destroy();
+}); \ No newline at end of file
diff --git a/MistyCore/service.js b/MistyCore/service.js
new file mode 100644
index 0000000..91ada43
--- /dev/null
+++ b/MistyCore/service.js
@@ -0,0 +1,216 @@
+const fs = require("fs");
+const YAML = require('yaml');
+const child_process = require('child_process');
+
+global.servicesProcesses = {};
+global.servicesTimers = {};
+const chalk = require("chalk");
+
+let me = {
+ list: () => {
+ let services = {};
+
+ for (let name of fs.readdirSync(systemRoot + "/LaunchDaemons")) {
+ services[name.substring(0, name.length - 4)] = YAML.parse(fs.readFileSync(systemRoot + "/LaunchDaemons/" + name).toString());
+ }
+
+ log("MistyCore-LaunchDaemons", "Gathered list of launch daemons");
+ return services;
+ },
+
+ reachTarget: (target) => {
+ process.stdout.clearLine(null);
+ process.stdout.cursorTo(0);
+ process.stdout.write(" Loading launch daemons for target " + target + "...");
+
+ log("MistyCore-LaunchDaemons", "Reached target: " + target);
+ let matchingServices = [];
+
+ for (let name of fs.readdirSync(systemRoot + "/LaunchDaemons")) {
+ let service = YAML.parse(fs.readFileSync(systemRoot + "/LaunchDaemons/" + name).toString());
+ if (service.metadata.target === target || parseInt(service.metadata.target) === target) {
+ service.name = name;
+ matchingServices.push(service);
+ }
+ }
+
+ log("MistyCore-LaunchDaemons", "Starting " + matchingServices.length + " launch daemons");
+ process.stdout.write(chalk.green(" Success") + "\n");
+ for (let service of matchingServices) {
+ me.start(service.name);
+ }
+ },
+
+ stop: (name, force) => {
+ let displayName = name.substring(0, name.length - 4);
+ log("MistyCore-LaunchDaemons", "Stopping " + displayName);
+ log("MistyCore-LaunchDaemons", "Reading configuration from " + systemRoot + "/LaunchDaemons/" + name);
+
+ let service = YAML.parse(fs.readFileSync(systemRoot + "/LaunchDaemons/" + name).toString());
+ let pid = parseInt(fs.readFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName).toString());
+
+ if (pid === -1) {
+ log("MistyCore-LaunchDaemons", "Cannot stop " + displayName + ": launch daemon is not running");
+ } else {
+ if (service.commands.stop) {
+ log("MistyCore-LaunchDaemons", "Launch daemon is using start/stop commands, not stopping as a daemon");
+
+ try {
+ child_process.execSync(service.commands.stop, { shell: "/System/Binaries/sh" });
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-1");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ } catch (e) {
+ log("MistyCore-LaunchDaemons", "Launch daemon has failed to stop");
+ log("MistyCore-LaunchDaemons", e.stack);
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-2");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ }
+ } else {
+ if (force) {
+ log("MistyCore-LaunchDaemons", "Launch daemon is using start/stop commands, killing process");
+ process.kill(pid, "SIGKILL");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-1");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ } else {
+ log("MistyCore-LaunchDaemons", "Launch daemon is using start/stop commands, terminating process");
+ process.kill(pid);
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-1");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ }
+ }
+ }
+ },
+
+ restart: (name, force) => {
+ let displayName = name.substring(0, name.length - 4);
+ log("MistyCore-LaunchDaemons", "Restarting " + displayName);
+ log("MistyCore-LaunchDaemons", "Reading configuration from " + systemRoot + "/LaunchDaemons/" + name);
+ let service = YAML.parse(fs.readFileSync(systemRoot + "/LaunchDaemons/" + name).toString());
+
+ if (service.commands.restart) {
+ log("MistyCore-LaunchDaemons", "Launch daemon is using restart commands, not restarting as a daemon");
+ try {
+ child_process.execSync(service.commands.restart, { shell: "/System/Binaries/sh" });
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "0");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ } catch (e) {
+ log("MistyCore-LaunchDaemons", "Launch daemon has failed to restart");
+ log("MistyCore-LaunchDaemons", e.stack);
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-2");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ }
+ } else {
+ log("MistyCore-LaunchDaemons", "Launch daemon is not using restart commands, restarting as a daemon");
+ me.stop(name, force);
+ me.start(name, true);
+ }
+ },
+
+ start: (name, hidden) => {
+ let displayName = name.substring(0, name.length - 4);
+ fs.writeFileSync(systemRoot + "/Logs/LaunchDaemons/" + displayName + ".log", "");
+ log("MistyCore-LaunchDaemons", "Starting " + displayName);
+ log("MistyCore-LaunchDaemons", "Reading configuration from " + systemRoot + "/LaunchDaemons/" + name);
+ let service = YAML.parse(fs.readFileSync(systemRoot + "/LaunchDaemons/" + name).toString());
+
+ if (!hidden) {
+ process.stdout.clearLine(null);
+ process.stdout.cursorTo(0);
+ process.stdout.write(" Starting launch daemon: " + displayName + "...");
+ }
+
+ if (service.commands.stop) {
+ log("MistyCore-LaunchDaemons", "Launch daemon is using start/stop commands, not starting as a daemon");
+ try {
+ let proc = child_process.exec(service.commands.start, { shell: "/System/Binaries/sh" });
+ global.servicesProcesses[proc.pid] = proc;
+ global.servicesTimers[proc.pid] = setTimeout(() => {
+ proc.kill("SIGKILL");
+ log("MistyCore-LaunchDaemons", "Launch daemon has failed to start");
+ log("MistyCore-LaunchDaemons", "Startup timed out");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-2");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ }, 10000);
+ proc.on('exit', (code) => {
+ if (code === 0) {
+ log("MistyCore-LaunchDaemons", "Launch daemon has completed startup");
+ delete global.servicesProcesses[proc.pid];
+ clearTimeout(global.servicesTimers[proc.pid]);
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "0");
+ } else {
+ log("MistyCore-LaunchDaemons", "Launch daemon has failed to start");
+ log("MistyCore-LaunchDaemons", "Process exited with code " + code);
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-2");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ }
+ })
+ proc.stdout.on('data', (data) => {
+ fs.appendFileSync(systemRoot + "/Logs/LaunchDaemons/" + displayName + ".log", data);
+ log(displayName, data.toString());
+ });
+ proc.stderr.on('data', (data) => {
+ fs.appendFileSync(systemRoot + "/Logs/LaunchDaemons/" + displayName + ".log", data);
+ log(displayName, data.toString());
+ });
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-3");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+
+ if (!hidden) {
+ process.stdout.write(chalk.green(" Success") + "\n");
+ }
+ } catch (e) {
+ log("MistyCore-LaunchDaemons", "Launch daemon has failed to start");
+ log("MistyCore-LaunchDaemons", e.stack);
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-2");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+
+ if (!hidden) {
+ process.stdout.write(chalk.yellow(" Failure") + "\n");
+ console.log("");
+ console.log(chalk.red.inverse("MistyOS is unable to start up."));
+ console.log("");
+ console.log(chalk.red("A failing launch daemon is preventing MistyOS from starting up correctly."));
+ console.log(" " + chalk.red("Launch daemon: " + displayName));
+ console.log(" " + chalk.red("Error message: " + e.message));
+ console.log("");
+ console.log(chalk.red("Try starting your device in safe mode by holding Shift during start up."));
+ global.halt();
+ }
+ }
+ } else {
+ log("MistyCore-LaunchDaemons", "Launch daemon is not using start/stop commands, starting as a daemon");
+ try {
+ let proc = child_process.exec(service.commands.start, {shell: "/System/Binaries/sh"});
+ global.servicesProcesses[proc.pid] = proc;
+ proc.on('exit', (code) => {
+ if (code === 0 || code === null) {
+ log("MistyCore-LaunchDaemons", "Launch daemon has stopped");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-1");
+ } else {
+ log("MistyCore-LaunchDaemons", "Launch daemon has failed with code " + code);
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-2");
+ }
+
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ })
+ proc.stdout.on('data', (data) => {
+ fs.appendFileSync(systemRoot + "/Logs/LaunchDaemons/" + displayName + ".log", data);
+ log(displayName, data.toString());
+ });
+ proc.stderr.on('data', (data) => {
+ fs.appendFileSync(systemRoot + "/Logs/LaunchDaemons/" + displayName + ".log", data);
+ log(displayName, data.toString());
+ });
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, proc.pid.toString());
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ } catch (e) {
+ log("MistyCore-LaunchDaemons", "Launch daemon has failed to start");
+ log("MistyCore-LaunchDaemons", e.stack);
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemons/" + displayName, "-2");
+ fs.writeFileSync(systemRoot + "/../Volumes/VM/LaunchDaemonsTimes/" + displayName, new Date().getTime().toString());
+ }
+ }
+ }
+}
+
+module.exports = me; \ No newline at end of file
diff --git a/MistyCore/shell.js b/MistyCore/shell.js
new file mode 100644
index 0000000..7dc3c86
--- /dev/null
+++ b/MistyCore/shell.js
@@ -0,0 +1,709 @@
+// noinspection JSIncompatibleTypesComparison
+
+const fs = require('fs');
+const os = require('os');
+const chalk = require('chalk');
+const YAML = require('yaml');
+const path = require('path');
+
+global.systemRoot = path.resolve(__dirname + "/..");
+console.clear();
+require('./banner')();
+
+global.daemons = fs.readdirSync(systemRoot + "/LaunchDaemons").map(i => i.substring(0, i.length - 4));
+global.log = require('./log');
+log("Shell", "Starting up shell...");
+global.internalCommands = fs.readdirSync(__dirname + "/../Components");
+global.internalCommandsMetadata = internalCommands.map((i) => {
+ return YAML.parse(fs.readFileSync(__dirname + "/../Components/" + i + "/metadata.yml").toString());
+});
+
+global.commands = [...internalCommands];
+global.commandsMetadata = [...internalCommandsMetadata];
+
+let stdin = process.stdin;
+global.currentInput = "";
+global.inputPosition = 0;
+stdin.setRawMode(true);
+stdin.setEncoding('utf8');
+
+function prompt() {
+ return chalk.cyan(os.hostname() + ":") + chalk.blue(process.cwd() + "> ");
+}
+
+function promptNoColor() {
+ return os.hostname() + ":" + process.cwd() + "> ";
+}
+
+function main() {
+ global.currentInput = "";
+ global.inputPosition = 0;
+
+ stdin.resume();
+ updateInput();
+}
+
+stdin.on('data', function (key) {
+ if (key === '\u0003') {
+ main();
+ return;
+ }
+
+ if (key === '\u0004') {
+ process.exit();
+ return;
+ }
+
+ if (key === "\r" || key === "\n") {
+ replaceWithAliasIfPossible(true, () => {
+ if (key === "\r") {
+ process.stdout.write("\n");
+ } else {
+ process.stdout.write("\r");
+ }
+
+ stdin.pause();
+ let parts = currentInput.split(" ");
+ let command = parts[0];
+
+ if (commands.includes(command)) {
+ if (internalCommands.includes(command)) {
+ let metadata = commandsMetadata[commands.indexOf(command)];
+ parts[0] = __dirname + "/../Components/" + command + "/index.js";
+ let arguments = {
+ _finals: []
+ };
+ let willAddParameters = true;
+
+ for (let index in parts) {
+ if (index > 0) {
+ let part = parts[index];
+ let originalPart = part;
+
+ if (originalPart === "--") {
+ willAddParameters = false;
+ continue;
+ }
+
+ if (part.startsWith("--") && willAddParameters) part = part.substring(2);
+ if (part.startsWith("-") && willAddParameters) part = part.substring(1);
+
+ if (part.includes("=") && willAddParameters) {
+ let value = part.substring(part.split("=")[0].length + 1);
+
+ if (!isNaN(parseFloat(value))) {
+ value = parseFloat(value);
+ } else if (!isNaN(parseInt(value))) {
+ value = parseInt(value);
+ }
+
+ arguments[part.split("=")[0].toLowerCase()] = value;
+ } else {
+ if (originalPart.startsWith("-") && willAddParameters) {
+ arguments[part.toLowerCase()] = true;
+ } else {
+ if (part.trim() !== "") arguments["_finals"].push(part);
+ }
+ }
+ }
+ }
+
+ log("Shell", "Invoking command: " + command);
+
+ try {
+ if (metadata.internal) {
+ require(__dirname + "/../Components/" + command + "/index.js")(arguments);
+ } else {
+ stdin.setRawMode(false);
+ require('child_process').execFileSync(process.argv[0], [ parts[0], JSON.stringify(arguments) ], { stdio: "inherit" });
+ stdin.setRawMode(true);
+ }
+ } catch (e) {
+ stdin.setRawMode(true);
+ log("Shell", "Error while running: " + currentInput + "\n" + e.stack);
+ console.log("\n" + chalk.bgRed.white("<!>") + " " + chalk.red("Error while running command") + "\n");
+ main();
+ return;
+ }
+ }
+ } else {
+ log("Shell", "Attempted to run command " + command + " but it does not exist.");
+ console.log(chalk.bgRed.white("<!>") + " " + chalk.red("Command not found: ") + command);
+ }
+
+ main();
+ });
+ } else if (key === "\b" || key === "\x7F") {
+ if (global.currentInput !== "" && inputPosition > 0) {
+ global.currentInput = global.currentInput.substring(0, inputPosition - 1) + global.currentInput.substring(inputPosition);
+ inputPosition--;
+ updateInput();
+ }
+ } else if (key === " ") {
+ replaceWithAliasIfPossible(false);
+ } else if (key.startsWith("\x1B") || key === "\t") {
+ if (key === "\x1B[D") { // Left
+ cursorLeft();
+ } else if (key === "\x1B[C" || key === "\t") { // Right
+ cursorRight();
+ } else if (key === "\x1B[B") { // Down
+ } else if (key === "\x1B[A") { // Up
+ }
+ } else {
+ global.currentInput = global.currentInput.substring(0, inputPosition) + key + global.currentInput.substring(inputPosition);
+ inputPosition++;
+ updateInput();
+ }
+});
+
+function replaceWithAliasIfPossible(isEnter, callback) {
+ let text = currentInput;
+ if (text.trim() === "") return "";
+
+ let parts = text.split(" ");
+ let command = parts[0];
+
+ if (!commands.includes(command)) {
+ let inputLowerCase = command.toLowerCase();
+ let match = commands.filter(i => i.toLowerCase().startsWith(inputLowerCase))[0];
+
+ if (!match) {
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ let metadata = commandsMetadata[commands.indexOf(selectedCommand)];
+ if (metadata['aliases'] && metadata['aliases'].map(i => i.toLowerCase()).includes(command.toLowerCase())) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ parts[0] = alias;
+ global.currentInput = parts.join(" ") + " ";
+ global.inputPosition = currentInput.length;
+ global.currentInput = global.currentInput.substring(0, inputPosition) + " " + global.currentInput.substring(inputPosition);
+ global.currentInput = global.currentInput.trim() + " ";
+ global.inputPosition = currentInput.length;
+ if (isEnter) {
+ process.stdout.clearLine(0, () => {
+ process.stdout.cursorTo(0, () => {
+ process.stdout.write(prompt() + syntaxHighlighting(currentInput), () => {
+ if (callback) callback();
+ });
+ });
+ });
+ } else {
+ updateInput();
+ }
+ return;
+ }
+ }
+
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ if (selectedCommand.toLowerCase() === command.toLowerCase()) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ parts[0] = alias;
+ global.currentInput = parts.join(" ") + " ";
+ global.inputPosition = currentInput.length;
+ global.currentInput = global.currentInput.substring(0, inputPosition) + " " + global.currentInput.substring(inputPosition);
+ global.currentInput = global.currentInput.trim() + " ";
+ global.inputPosition = currentInput.length;
+ if (isEnter) {
+ process.stdout.clearLine(0, () => {
+ process.stdout.cursorTo(0, () => {
+ process.stdout.write(prompt() + syntaxHighlighting(currentInput), () => {
+ if (callback) callback();
+ });
+ });
+ });
+ } else {
+ updateInput();
+ }
+ return;
+ }
+ } else if (commands.includes(command)) {
+ let metadata = commandsMetadata[commands.indexOf(command)];
+
+ let arguments = {
+ _finals: []
+ };
+ let willAddParameters = true;
+
+ for (let index in parts) {
+ if (index > 0) {
+ let part = parts[index];
+ let originalPart = part;
+
+ if (originalPart === "--") {
+ willAddParameters = false;
+ continue;
+ }
+
+ if (part.startsWith("--") && willAddParameters) part = part.substring(2);
+ if (part.startsWith("-") && willAddParameters) part = part.substring(1);
+
+ if (part.includes("=") && willAddParameters) {
+ let value = part.substring(part.split("=")[0].length + 1);
+
+ if (!isNaN(parseFloat(value))) {
+ value = parseFloat(value);
+ } else if (!isNaN(parseInt(value))) {
+ value = parseInt(value);
+ }
+
+ arguments[part.split("=")[0].toLowerCase()] = value;
+ } else {
+ if (originalPart.startsWith("-") && willAddParameters) {
+ arguments[part.toLowerCase()] = true;
+ } else {
+ if (part.trim() !== "") arguments["_finals"].push(part);
+ }
+ }
+ }
+ }
+
+ if (arguments["_finals"].length > 0) {
+ let lastFinal = arguments["_finals"][arguments["_finals"].length - 1];
+
+ if (metadata && metadata['manual']['final'] && metadata['manual']['final']['command']) {
+ command = lastFinal;
+ let inputLowerCase = command.toLowerCase();
+ let match = commands.filter(i => i.toLowerCase().startsWith(inputLowerCase))[0];
+
+ if (!match) {
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ let metadata = commandsMetadata[commands.indexOf(selectedCommand)];
+ if (metadata['aliases'] && metadata['aliases'].map(i => i.toLowerCase()).includes(command.toLowerCase())) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ parts[parts.indexOf(lastFinal)] = alias;
+ global.currentInput = parts.join(" ") + " ";
+ global.inputPosition = currentInput.length;
+ global.currentInput = global.currentInput.substring(0, inputPosition) + " " + global.currentInput.substring(inputPosition);
+ global.currentInput = global.currentInput.trim() + " ";
+ global.inputPosition = currentInput.length;
+ if (isEnter) {
+ process.stdout.clearLine(0, () => {
+ process.stdout.cursorTo(0, () => {
+ process.stdout.write(prompt() + syntaxHighlighting(currentInput), () => {
+ if (callback) callback();
+ });
+ });
+ });
+ } else {
+ updateInput();
+ }
+ return;
+ }
+ }
+
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ if (selectedCommand.toLowerCase() === command.toLowerCase()) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ parts[parts.indexOf(lastFinal)] = alias;
+ global.currentInput = parts.join(" ") + " ";
+ global.inputPosition = currentInput.length;
+ global.currentInput = global.currentInput.substring(0, inputPosition) + " " + global.currentInput.substring(inputPosition);
+ global.currentInput = global.currentInput.trim() + " ";
+ global.inputPosition = currentInput.length;
+ if (isEnter) {
+ process.stdout.clearLine(0, () => {
+ process.stdout.cursorTo(0, () => {
+ process.stdout.write(prompt() + syntaxHighlighting(currentInput), () => {
+ if (callback) callback();
+ });
+ });
+ });
+ } else {
+ updateInput();
+ }
+ return;
+ }
+ } else if (metadata && metadata['manual']['final'] && metadata['manual']['final']['daemon']) {
+ command = lastFinal;
+
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ if (selectedCommand.toLowerCase() === command.toLowerCase()) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ parts[parts.indexOf(lastFinal)] = alias;
+ global.currentInput = parts.join(" ") + " ";
+ global.inputPosition = currentInput.length;
+ global.currentInput = global.currentInput.substring(0, inputPosition) + " " + global.currentInput.substring(inputPosition);
+ global.currentInput = global.currentInput.trim() + " ";
+ global.inputPosition = currentInput.length;
+ if (isEnter) {
+ process.stdout.clearLine(0, () => {
+ process.stdout.cursorTo(0, () => {
+ process.stdout.write(prompt() + syntaxHighlighting(currentInput), () => {
+ if (callback) callback();
+ });
+ });
+ });
+ } else {
+ updateInput();
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ if (!isEnter) {
+ global.currentInput = global.currentInput.substring(0, inputPosition) + " " + global.currentInput.substring(inputPosition);
+ inputPosition++;
+ updateInput();
+ } else {
+ process.stdout.clearLine(0, () => {
+ process.stdout.cursorTo(0, () => {
+ process.stdout.write(prompt() + syntaxHighlighting(currentInput), () => {
+ if (callback) callback();
+ });
+ });
+ });
+ }
+}
+
+function cursorLeft() {
+ if (inputPosition > 0) {
+ inputPosition--;
+ }
+
+ updateInput();
+}
+
+function cursorRight() {
+ if (inputPosition < currentInput.length) {
+ inputPosition++;
+ } else {
+ autoCompleteIfPossible();
+ }
+
+ updateInput();
+}
+
+function syntaxHighlighting(text) {
+ let parts = text.split(" ");
+ let coloredParts = [];
+ let willColorParameters = true;
+ let cmdMetadata = null;
+
+ for (let _index in parts) {
+ let index = parseInt(_index);
+ let part = parts[index];
+
+ if (index === 0) {
+ cmdMetadata = commandsMetadata[commands.indexOf(part)];
+
+ if (commands.includes(part)) {
+ coloredParts.push(chalk.green(part));
+ } else {
+ if (parts.length === 1) {
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ let metadata = commandsMetadata[commands.indexOf(selectedCommand)];
+ if (metadata['aliases'] && metadata['aliases'].map(i => i.toLowerCase()).includes(part.toLowerCase())) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ coloredParts.push(chalk.green.bgGray(part));
+ } else {
+ coloredParts.push(chalk.yellow(part));
+ }
+ } else {
+ coloredParts.push(chalk.red(part));
+ }
+ }
+ } else if (part === "--" && willColorParameters) {
+ coloredParts.push(chalk.cyan(part));
+ willColorParameters = false;
+ } else if (part.startsWith("-") && willColorParameters) {
+ if (part.includes("=")) {
+ coloredParts.push(chalk.magentaBright.underline(part.split("=")[0]) + chalk.magenta.bgGray("=") + chalk.magenta(part.substring(part.split("=")[0].length + 1)));
+ } else {
+ coloredParts.push(chalk.magenta(part));
+ }
+ } else if (cmdMetadata && cmdMetadata['manual']['final'] && cmdMetadata['manual']['final']['command']) {
+ if (commands.map(i => i.toLowerCase()).includes(part.toLowerCase())) {
+ coloredParts.push(chalk.yellow(part));
+ } else {
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ let metadata = commandsMetadata[commands.indexOf(selectedCommand)];
+ if (metadata['aliases'] && metadata['aliases'].map(i => i.toLowerCase()).includes(part.toLowerCase())) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ coloredParts.push(chalk.yellow(part));
+ } else {
+ coloredParts.push(chalk.red(part));
+ }
+ }
+ } else if (cmdMetadata && cmdMetadata['manual']['final'] && cmdMetadata['manual']['final']['daemon']) {
+ if (daemons.map(i => i.toLowerCase()).includes(part.toLowerCase())) {
+ coloredParts.push(chalk.yellow(part));
+ } else {
+ coloredParts.push(chalk.red(part));
+ }
+ } else {
+ coloredParts.push(part);
+ }
+ }
+
+ return coloredParts.join(" ");
+}
+
+function autoComplete(text) {
+ if (text.trim() === "") return "";
+
+ let parts = text.split(" ");
+ let command = parts[0];
+
+ if (commands.includes(command)) {
+ if (parts.filter(i => i.trim() !== "").length > 1) {
+ let metadata = commandsMetadata[commands.indexOf(command)];
+
+ let arguments = {
+ _finals: []
+ };
+ let willAddParameters = true;
+
+ for (let index in parts) {
+ if (index > 0) {
+ let part = parts[index];
+ let originalPart = part;
+
+ if (originalPart === "--") {
+ willAddParameters = false;
+ continue;
+ }
+
+ if (part.startsWith("--") && willAddParameters) part = part.substring(2);
+ if (part.startsWith("-") && willAddParameters) part = part.substring(1);
+
+ if (part.includes("=") && willAddParameters) {
+ let value = part.substring(part.split("=")[0].length + 1);
+
+ if (!isNaN(parseFloat(value))) {
+ value = parseFloat(value);
+ } else if (!isNaN(parseInt(value))) {
+ value = parseInt(value);
+ }
+
+ arguments[part.split("=")[0].toLowerCase()] = value;
+ } else {
+ if (originalPart.startsWith("-") && willAddParameters) {
+ arguments[part.toLowerCase()] = true;
+ } else {
+ if (part.trim() !== "") arguments["_finals"].push(part);
+ }
+ }
+ }
+ }
+
+ if (arguments["_finals"].length > 0) {
+ let lastFinal = arguments["_finals"][arguments["_finals"].length - 1];
+
+ if (metadata && metadata['manual']['final'] && metadata['manual']['final']['command']) {
+ command = lastFinal;
+
+ if (commands.includes(command)) {
+ let metadata = commandsMetadata[commands.indexOf(command)];
+ return " " + chalk.gray("- " + (metadata.description ?? "<no description>"));
+ } else {
+ let inputLowerCase = command.toLowerCase();
+ let match = commands.filter(i => i.toLowerCase().startsWith(inputLowerCase))[0];
+
+ if (match) {
+ return chalk.gray(match.substring(command.length));
+ } else {
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ let metadata = commandsMetadata[commands.indexOf(selectedCommand)];
+ if (metadata['aliases'] && metadata['aliases'].map(i => i.toLowerCase()).includes(command.toLowerCase())) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ let metadata = commandsMetadata[commands.indexOf(alias)];
+ return " " + chalk.gray(" (-> " + alias + ") - " + (metadata.description ?? "<no description>"));
+ } else {
+ return "";
+ }
+ }
+ }
+ } else if (metadata && metadata['manual']['final'] && metadata['manual']['final']['daemon']) {
+ command = lastFinal;
+
+ if (daemons.includes(command)) {
+ return "";
+ } else {
+ let inputLowerCase = command.toLowerCase();
+ let match = daemons.filter(i => i.toLowerCase().startsWith(inputLowerCase))[0];
+
+ if (match) {
+ return chalk.gray(match.substring(command.length));
+ } else {
+ return "";
+ }
+ }
+ } else {
+ return "";
+ }
+ } else {
+ return "";
+ }
+ } else {
+ let metadata = commandsMetadata[commands.indexOf(command)];
+ return " " + chalk.gray("- " + (metadata.description ?? "<no description>"));
+ }
+ } else {
+ let inputLowerCase = command.toLowerCase();
+ let match = commands.filter(i => i.toLowerCase().startsWith(inputLowerCase))[0];
+
+ if (match) {
+ return chalk.gray(match.substring(command.length));
+ } else {
+ let alias = null;
+
+ for (let selectedCommand of commands) {
+ let metadata = commandsMetadata[commands.indexOf(selectedCommand)];
+ if (metadata['aliases'] && metadata['aliases'].map(i => i.toLowerCase()).includes(command.toLowerCase())) {
+ alias = selectedCommand;
+ }
+ }
+
+ if (alias) {
+ let metadata = commandsMetadata[commands.indexOf(alias)];
+ return " " + chalk.gray(" (-> " + alias + ") - " + (metadata.description ?? "<no description>"));
+ } else {
+ return "";
+ }
+ }
+ }
+}
+
+function autoCompleteIfPossible() {
+ let text = currentInput;
+ if (text.trim() === "") return;
+
+ let parts = text.split(" ");
+ let command = parts[0];
+
+ if (!commands.includes(command)) {
+ let inputLowerCase = command.toLowerCase();
+ let match = commands.filter(i => i.toLowerCase().startsWith(inputLowerCase))[0];
+
+ if (match) {
+ global.currentInput += match.substring(command.length);
+ global.currentInput = global.currentInput.trim() + " ";
+ global.inputPosition = currentInput.length - 1;
+ replaceWithAliasIfPossible();
+ }
+ } else if (commands.includes(command)) {
+ let metadata = commandsMetadata[commands.indexOf(command)];
+
+ let arguments = {
+ _finals: []
+ };
+ let willAddParameters = true;
+
+ for (let index in parts) {
+ if (index > 0) {
+ let part = parts[index];
+ let originalPart = part;
+
+ if (originalPart === "--") {
+ willAddParameters = false;
+ continue;
+ }
+
+ if (part.startsWith("--") && willAddParameters) part = part.substring(2);
+ if (part.startsWith("-") && willAddParameters) part = part.substring(1);
+
+ if (part.includes("=") && willAddParameters) {
+ let value = part.substring(part.split("=")[0].length + 1);
+
+ if (!isNaN(parseFloat(value))) {
+ value = parseFloat(value);
+ } else if (!isNaN(parseInt(value))) {
+ value = parseInt(value);
+ }
+
+ arguments[part.split("=")[0].toLowerCase()] = value;
+ } else {
+ if (originalPart.startsWith("-") && willAddParameters) {
+ arguments[part.toLowerCase()] = true;
+ } else {
+ if (part.trim() !== "") arguments["_finals"].push(part);
+ }
+ }
+ }
+ }
+
+ if (arguments["_finals"].length > 0) {
+ let lastFinal = arguments["_finals"][arguments["_finals"].length - 1];
+
+ if (metadata && metadata['manual']['final'] && metadata['manual']['final']['command']) {
+ command = lastFinal;
+ if (!commands.includes(command)) {
+ let inputLowerCase = command.toLowerCase();
+ let match = commands.filter(i => i.toLowerCase().startsWith(inputLowerCase))[0];
+
+ if (match) {
+ global.currentInput += match.substring(command.length);
+ global.currentInput = global.currentInput.trim() + " ";
+ global.inputPosition = currentInput.length;
+ replaceWithAliasIfPossible();
+ }
+ }
+ }
+ }
+ }
+}
+
+function updateInput() {
+ if (global.inputPosition < global.currentInput.length) {
+ global.currentInput = global.currentInput.trim();
+ }
+
+ process.stdout.clearLine(0, () => {
+ process.stdout.cursorTo(0);
+ process.stdout.write(prompt() + syntaxHighlighting(currentInput) + autoComplete(currentInput), () => {
+ process.stdout.cursorTo(promptNoColor().length + inputPosition);
+ });
+ });
+}
+
+main();
+log("Shell", "Shell successfully loaded."); \ No newline at end of file
diff --git a/MistyCore/socket.js b/MistyCore/socket.js
new file mode 100644
index 0000000..0db4f5b
--- /dev/null
+++ b/MistyCore/socket.js
@@ -0,0 +1,68 @@
+log("MistyCore-Socket", "Installing socket...");
+const net = require('net');
+const fs = require('fs');
+const unixSocketServer = net.createServer();
+
+if (fs.existsSync(systemRoot + "/../Volumes/VM/MistyCore-Socket")) fs.unlinkSync(systemRoot + "/../Volumes/VM/MistyCore-Socket");
+
+unixSocketServer.listen(systemRoot + "/../Volumes/VM/MistyCore-Socket", () => {
+ log("MistyCore-Socket", "Socket ready");
+});
+
+unixSocketServer.on('connection', (s) => {
+ s.on('data', function (msg) {
+ try {
+ let data = JSON.parse(msg.toString());
+
+ if (!data.action || !data.payload) {
+ log("MistyCore-Socket", "Received data but it is not correctly formatted:\n" + e.stack);
+ } else {
+ switch (data.action) {
+ case "LOG":
+ log(data.payload.service ?? "<unknown>", data.payload.text ?? "<unknown>");
+ break;
+
+ case "SHUTDOWN":
+ require('./power')(false);
+ break;
+
+ case "REBOOT":
+ require('./power')(true);
+ break;
+
+ case "SERVICE":
+ switch (data.payload.option) {
+ case "restart":
+ services.restart(data.payload.service);
+ break;
+
+ case "stop":
+ services.stop(data.payload.service);
+ break;
+
+ case "forcestop":
+ services.stop(data.payload.service, true);
+ break;
+
+ case "start":
+ services.start(data.payload.service, true);
+ break;
+
+ default:
+ log("MistyCore-Socket", "Received unrecognized launch daemon command: " + data.payload.option);
+ break;
+ }
+ break;
+
+ default:
+ log("MistyCore-Socket", "Received data but the action is not recognized:\n" + data.action);
+ break;
+ }
+ }
+ } catch (e) {
+ log("MistyCore-Socket", "Received data but unable to decode it:\n" + e.stack);
+ }
+ });
+
+ s.end();
+}); \ No newline at end of file
diff --git a/MistyCore/test.js b/MistyCore/test.js
new file mode 100644
index 0000000..ca588f4
--- /dev/null
+++ b/MistyCore/test.js
@@ -0,0 +1,7 @@
+let error = require('./error');
+
+try {
+ dfsisd();
+} catch (e) {
+ error(e, 9, "1.2.3");
+} \ No newline at end of file
diff --git a/MistyOSVersion b/MistyOSVersion
new file mode 100644
index 0000000..590d65d
--- /dev/null
+++ b/MistyOSVersion
@@ -0,0 +1 @@
+1.3.12 ("Alicorn" Milestone 4J) \ No newline at end of file
diff --git a/ROADMAP.md b/ROADMAP.md
new file mode 100644
index 0000000..cde55af
--- /dev/null
+++ b/ROADMAP.md
@@ -0,0 +1,17 @@
+# MistyOS Roadmap
+
+- [x] Power-off/restart options
+- [x] Services management
+- [ ] Fully working shell
+- [ ] Filesystem commands
+- [ ] System management commands
+- [ ] Other CLI utilities (e.g. text editor)
+- [ ] Networking
+- [ ] Linux subsystem
+- [ ] X11/Desktop
+- [ ] Sound (PulseAudio/ALSA/PipeWire)
+- [ ] System updates
+- [ ] Package management
+- [ ] Multiuser (?)
+- [ ] Installer
+- [ ] Software Development Kit (for Linux, and potentially macOS) \ No newline at end of file
diff --git a/StartupItems/001--MistyOSRoot.js b/StartupItems/001--MistyOSRoot.js
new file mode 100644
index 0000000..2e000b3
--- /dev/null
+++ b/StartupItems/001--MistyOSRoot.js
@@ -0,0 +1,3 @@
+log("MistyCore-Startup-MistyOSRoot", "Attempting to mount root read-write...");
+require('child_process').execFileSync("/System/Binaries/mount", [ "-o", "remount,rw", "/" ]);
+log("MistyCore-Startup-MistyOSRoot", "Mounted root read-write"); \ No newline at end of file
diff --git a/StartupItems/002--Logs.js b/StartupItems/002--Logs.js
new file mode 100644
index 0000000..fccd1d5
--- /dev/null
+++ b/StartupItems/002--Logs.js
@@ -0,0 +1,13 @@
+log("MistyCore-Startup-Logs", "Rotating journal...");
+const fs = require('fs');
+
+let date = new Date().toISOString().replaceAll(":", "-");
+if (!fs.existsSync(systemRoot + "/Logs")) fs.mkdirSync(systemRoot + "/Logs");
+if (!fs.existsSync(systemRoot + "/Logs/LaunchDaemons")) fs.mkdirSync(systemRoot + "/Logs/LaunchDaemons");
+_originalSystemLog = systemLog;
+if (fs.existsSync(systemLog)) fs.copyFileSync(systemLog, systemRoot + "/Logs/" + date + ".log");
+global.systemLog = systemRoot + "/Logs/" + date + ".log";
+if (!fs.existsSync(systemLog)) fs.writeFileSync(systemLog, "");
+fs.writeFileSync(systemRoot + "/../Volumes/VM/SystemLog", systemLog);
+
+log("MistyCore-Startup-Logs", "Done rotating journal"); \ No newline at end of file
diff --git a/StartupItems/100--Preferences.js b/StartupItems/100--Preferences.js
new file mode 100644
index 0000000..3c8a79b
--- /dev/null
+++ b/StartupItems/100--Preferences.js
@@ -0,0 +1,15 @@
+log("MistyCore-Startup-Preferences", "Verifying system preferences...");
+const fs = require('fs');
+
+if (!fs.existsSync(systemRoot + "/Preferences")) fs.mkdirSync(systemRoot + "/Preferences");
+if (!fs.existsSync(systemRoot + "/Preferences/Hostname")) fs.writeFileSync(systemRoot + "/Preferences/Hostname", "MistyOS");
+if (!fs.existsSync(systemRoot + "/Preferences/Keyboard")) fs.writeFileSync(systemRoot + "/Preferences/Keyboard", "qwerty");
+fs.writeFileSync(systemRoot + "/Preferences/os-release", `
+NAME="MistyOS"
+VERSION="${fs.readFileSync(systemRoot + "/MistyOSVersion").toString().trim()}"
+PRETTY_NAME="MistyOS ${fs.readFileSync(systemRoot + "/MistyOSVersion").toString().trim()}"
+ID=mistyos
+LOGO=mistyos-icon
+`);
+
+log("MistyCore-Startup-Preferences", "System preferences are OK"); \ No newline at end of file
diff --git a/StartupItems/200--Hostname.js b/StartupItems/200--Hostname.js
new file mode 100644
index 0000000..9148c7d
--- /dev/null
+++ b/StartupItems/200--Hostname.js
@@ -0,0 +1,6 @@
+const fs = require("fs");
+log("MistyCore-Startup-Hostname", "Setting hostname to " + require('fs').readFileSync(systemRoot + "/Preferences/Hostname").toString().trim());
+require('child_process').execFileSync("/System/Binaries/hostname", [ "--", require('fs').readFileSync(systemRoot + "/Preferences/Hostname").toString().trim() ]);
+global.hostname = require('fs').readFileSync(systemRoot + "/Preferences/Hostname").toString().trim();
+fs.writeFileSync(systemRoot + "/../Volumes/VM/Hostname", hostname);
+log("MistyCore-Startup-Hostname", "Set hostname successfully"); \ No newline at end of file
diff --git a/StartupItems/201--Keyboard.js b/StartupItems/201--Keyboard.js
new file mode 100644
index 0000000..7e3dbcd
--- /dev/null
+++ b/StartupItems/201--Keyboard.js
@@ -0,0 +1,3 @@
+log("MistyCore-Startup-Keyboard", "Installing keyboard layout...");
+require('child_process').execFileSync("/System/Binaries/sh", [ "-c", "loadkeys < /System/Library/Keyboards/" + require('fs').readFileSync(systemRoot + "/Preferences/Keyboard").toString().trim().replace(/[^a-z\d]/gm, "") + ".kmap" ]);
+log("MistyCore-Startup-Keyboard", "Installed keyboard layout: " + require('fs').readFileSync(systemRoot + "/Preferences/Keyboard").toString().trim().replace(/[^a-z\d]/gm, "")); \ No newline at end of file
diff --git a/StartupItems/999--Shell.js b/StartupItems/999--Shell.js
new file mode 100644
index 0000000..ee33c6a
--- /dev/null
+++ b/StartupItems/999--Shell.js
@@ -0,0 +1,8 @@
+const fs = require('fs');
+
+log("MistyCore-Startup-Shell", "Starting user interface...");
+if (!fs.existsSync("/User")) fs.mkdirSync("/User");
+process.env.HOME = "/User";
+global.uiProcess = require('child_process').spawn("/System/Library/Frameworks/NodeJS/MistyRuntime", [ "/System/Library/MistyCore/shell.js" ], { stdio: "inherit", cwd: "/User" });
+
+log("MistyCore-Startup-Shell", "Started user interface"); \ No newline at end of file