diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dcf4c49
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.luau text eol=lf
diff --git a/.github/ISSUE_TEMPLATE/BUG-REPORT.md b/.github/ISSUE_TEMPLATE/BUG-REPORT.md
index 7ab58bd..92bf500 100644
--- a/.github/ISSUE_TEMPLATE/BUG-REPORT.md
+++ b/.github/ISSUE_TEMPLATE/BUG-REPORT.md
@@ -1,22 +1,25 @@
----
-name: Bug report
-about: File a bug report for any behavior that you believe is unintentional or problematic
-title: "[BUG]"
-labels: bug
-assignees: ''
-
----
-
-## Describe the bug
-Put a clear and concise description of what the bug is. This should be short and to the point, not to exceed more than a paragraph. Put the details inside your reproduction steps.
-
-## Reproduction
-Make an easy-to-follow guide on how to reproduce it. Does it happen all the time? Will specific features affect reproduction? All these questions should be answered for a good issue.
-
-This is a good place to put rbxl files or scripts that help explain your reproduction steps.
-
-## Expected Behavior
-What you expect to happen
-
-## Actual Behavior
-What actually happens
\ No newline at end of file
+---
+name: Bug report
+about: File a bug report for any behavior that you believe is unintentional or problematic
+title: ""
+labels: bug
+assignees: ""
+---
+
+## Describe the bug
+
+Put a clear and concise description of what the bug is. This should be short and to the point, not to exceed more than a paragraph. Put the details inside your reproduction steps.
+
+## Reproduction
+
+Make an easy-to-follow guide on how to reproduce it. Does it happen all the time? Will specific features affect reproduction? All these questions should be answered for a good issue.
+
+This is a good place to put rbxl files or scripts that help explain your reproduction steps.
+
+## Expected Behavior
+
+What you expect to happen
+
+## Actual Behavior
+
+What actually happens
diff --git a/.github/ISSUE_TEMPLATE/DOCUMENTATION.md b/.github/ISSUE_TEMPLATE/DOCUMENTATION.md
index 0fbfcf4..6c80bd2 100644
--- a/.github/ISSUE_TEMPLATE/DOCUMENTATION.md
+++ b/.github/ISSUE_TEMPLATE/DOCUMENTATION.md
@@ -1,14 +1,15 @@
---
name: Documentation
about: Open an issue to add, change, or otherwise modify any part of the documentation.
-title: "[DOCS]"
+title: ""
labels: documentation
-assignees: ''
-
+assignees: ""
---
## Which Sections Does This Issue Cover?
+
[Put sections (e.g. Query Concepts), page links, etc as necessary]
## What Needs To Change?
-What specifically needs to change and what suggestions do you have to change it?
\ No newline at end of file
+
+What specifically needs to change and what suggestions do you have to change it?
diff --git a/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.md b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.md
index 6a63ee2..3a511c2 100644
--- a/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.md
+++ b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.md
@@ -1,27 +1,27 @@
----
-name: Feature Request
-about: File a feature request for something you believe should be added to Jecs
-title: "[FEATURE]"
-labels: enhancement
-assignees: ''
-
----
-
-## Describe your Feature
-
-You should explain your feature here, and the motivation for why you want it.
-
-## Implementation
-
-Explain how you would implement your feature here. Provide relevant API examples and such here (if applicable).
-
-## Alternatives
-
-What other alternative implementations or otherwise relevant information is important to why you decided to go with this specific implementation?
-
-## Considerations
-
-Some questions that need to be answered include the following:
-- Will old code break in response to this feature?
-- What are the performance impacts with this feature (if any)?
-- How is it useful to include?
+---
+name: Feature Request
+about: File a feature request for something you believe should be added to Jecs
+title: ""
+labels: enhancement
+assignees: ""
+---
+
+## Describe your Feature
+
+You should explain your feature here, and the motivation for why you want it.
+
+## Implementation
+
+Explain how you would implement your feature here. Provide relevant API examples and such here (if applicable).
+
+## Alternatives
+
+What other alternative implementations or otherwise relevant information is important to why you decided to go with this specific implementation?
+
+## Considerations
+
+Some questions that need to be answered include the following:
+
+- Will old code break in response to this feature?
+- What are the performance impacts with this feature (if any)?
+- How is it useful to include?
diff --git a/stylua.toml b/.stylua.toml
similarity index 62%
rename from stylua.toml
rename to .stylua.toml
index 6cd1ce7..554fc2f 100644
--- a/stylua.toml
+++ b/.stylua.toml
@@ -1,11 +1,9 @@
+syntax = "All"
column_width = 120
line_endings = "Unix"
indent_type = "Tabs"
indent_width = 4
-quote_style = "ForceDouble"
+quote_style = "AutoPreferDouble"
call_parentheses = "Always"
+space_after_function_names = "Never"
collapse_simple_statement = "Never"
-syntax = "Luau"
-
-[sort_requires]
-enabled = true
diff --git a/benches/cached.luau b/benches/cached.luau
index bdac689..df8ff38 100644
--- a/benches/cached.luau
+++ b/benches/cached.luau
@@ -1,5 +1,5 @@
local jecs = require("@jecs")
-local mirror = require("../mirror/init")
+local mirror = require("@mirror")
type i53 = number
diff --git a/benches/visual/remove.bench.luau b/benches/visual/remove.bench.luau
index a7082a8..5af2a17 100644
--- a/benches/visual/remove.bench.luau
+++ b/benches/visual/remove.bench.luau
@@ -1,49 +1,49 @@
---!optimize 2
---!native
-
-local ReplicatedStorage = game:GetService("ReplicatedStorage")
-local Matter = require(ReplicatedStorage.DevPackages.Matter)
-local ecr = require(ReplicatedStorage.DevPackages.ecr)
-local jecs = require(ReplicatedStorage.Lib)
-local pair = jecs.pair
-local ecs = jecs.World.new()
-local mirror = require(ReplicatedStorage.mirror)
-local mcs = mirror.World.new()
-
-local C1 = ecs:component()
-local C2 = ecs:entity()
-ecs:add(C2, pair(jecs.OnDeleteTarget, jecs.Delete))
-local C3 = ecs:entity()
-ecs:add(C3, pair(jecs.OnDeleteTarget, jecs.Delete))
-local C4 = ecs:entity()
-ecs:add(C4, pair(jecs.OnDeleteTarget, jecs.Delete))
-local E1 = mcs:component()
-local E2 = mcs:entity()
-mcs:add(E2, pair(jecs.OnDeleteTarget, jecs.Delete))
-local E3 = mcs:entity()
-mcs:add(E3, pair(jecs.OnDeleteTarget, jecs.Delete))
-local E4 = mcs:entity()
-mcs:add(E4, pair(jecs.OnDeleteTarget, jecs.Delete))
-
-return {
- ParameterGenerator = function()
- end,
-
- Functions = {
- Mirror = function()
- local m = mcs:entity()
- for i = 1, 100 do
- mcs:add(m, E3)
- mcs:remove(m, E3)
- end
- end,
-
- Jecs = function()
- local j = ecs:entity()
- for i = 1, 100 do
- ecs:add(j, C3)
- ecs:remove(j, C3)
- end
- end,
- },
-}
+--!optimize 2
+--!native
+
+local ReplicatedStorage = game:GetService("ReplicatedStorage")
+local Matter = require(ReplicatedStorage.DevPackages.Matter)
+local ecr = require(ReplicatedStorage.DevPackages.ecr)
+local jecs = require(ReplicatedStorage.Lib)
+local pair = jecs.pair
+local ecs = jecs.World.new()
+local mirror = require(ReplicatedStorage.mirror)
+local mcs = mirror.World.new()
+
+local C1 = ecs:component()
+local C2 = ecs:entity()
+ecs:add(C2, pair(jecs.OnDeleteTarget, jecs.Delete))
+local C3 = ecs:entity()
+ecs:add(C3, pair(jecs.OnDeleteTarget, jecs.Delete))
+local C4 = ecs:entity()
+ecs:add(C4, pair(jecs.OnDeleteTarget, jecs.Delete))
+local E1 = mcs:component()
+local E2 = mcs:entity()
+mcs:add(E2, pair(jecs.OnDeleteTarget, jecs.Delete))
+local E3 = mcs:entity()
+mcs:add(E3, pair(jecs.OnDeleteTarget, jecs.Delete))
+local E4 = mcs:entity()
+mcs:add(E4, pair(jecs.OnDeleteTarget, jecs.Delete))
+
+return {
+ ParameterGenerator = function()
+ end,
+
+ Functions = {
+ Mirror = function()
+ local m = mcs:entity()
+ for i = 1, 100 do
+ mcs:add(m, E3)
+ mcs:remove(m, E3)
+ end
+ end,
+
+ Jecs = function()
+ local j = ecs:entity()
+ for i = 1, 100 do
+ ecs:add(j, C3)
+ ecs:remove(j, C3)
+ end
+ end,
+ },
+}
diff --git a/coverage/amber.png b/coverage/amber.png
new file mode 100644
index 0000000..2cab170
Binary files /dev/null and b/coverage/amber.png differ
diff --git a/coverage/cmd_line b/coverage/cmd_line
new file mode 100644
index 0000000..7919d74
--- /dev/null
+++ b/coverage/cmd_line
@@ -0,0 +1 @@
+genhtml coverage.out --output-directory=coverage --synthesize-missing --ignore-errors source
diff --git a/coverage/emerald.png b/coverage/emerald.png
new file mode 100644
index 0000000..38ad4f4
Binary files /dev/null and b/coverage/emerald.png differ
diff --git a/coverage/gcov.css b/coverage/gcov.css
new file mode 100644
index 0000000..f329042
--- /dev/null
+++ b/coverage/gcov.css
@@ -0,0 +1,1073 @@
+/* All views: initial background and text color */
+body
+{
+ color: #000000;
+ background-color: #ffffff;
+}
+
+/* All views: standard link format*/
+a:link
+{
+ color: #284fa8;
+ text-decoration: underline;
+}
+
+/* All views: standard link - visited format */
+a:visited
+{
+ color: #00cb40;
+ text-decoration: underline;
+}
+
+/* All views: standard link - activated format */
+a:active
+{
+ color: #ff0040;
+ text-decoration: underline;
+}
+
+/* All views: main title format */
+td.title
+{
+ text-align: center;
+ padding-bottom: 10px;
+ font-family: sans-serif;
+ font-size: 20pt;
+ font-style: italic;
+ font-weight: bold;
+}
+/* "Line coverage date bins" leader */
+td.subTableHeader
+{
+ text-align: center;
+ padding-bottom: 6px;
+ font-family: sans-serif;
+ font-weight: bold;
+ vertical-align: center;
+}
+
+/* All views: header item format */
+td.headerItem
+{
+ text-align: right;
+ padding-right: 6px;
+ font-family: sans-serif;
+ font-weight: bold;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+/* All views: header item value format */
+td.headerValue
+{
+ text-align: left;
+ color: #284fa8;
+ font-family: sans-serif;
+ font-weight: bold;
+ white-space: nowrap;
+}
+
+/* All views: header item coverage table heading */
+td.headerCovTableHead
+{
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+}
+
+/* All views: header item coverage table entry */
+td.headerCovTableEntry
+{
+ text-align: right;
+ color: #284fa8;
+ font-family: sans-serif;
+ font-weight: bold;
+ white-space: nowrap;
+ padding-left: 12px;
+ padding-right: 4px;
+ background-color: #dae7fe;
+}
+
+/* All views: header item coverage table entry for high coverage rate */
+td.headerCovTableEntryHi
+{
+ text-align: right;
+ color: #000000;
+ font-family: sans-serif;
+ font-weight: bold;
+ white-space: nowrap;
+ padding-left: 12px;
+ padding-right: 4px;
+ background-color: #a7fc9d;
+}
+
+/* All views: header item coverage table entry for medium coverage rate */
+td.headerCovTableEntryMed
+{
+ text-align: right;
+ color: #000000;
+ font-family: sans-serif;
+ font-weight: bold;
+ white-space: nowrap;
+ padding-left: 12px;
+ padding-right: 4px;
+ background-color: #ffea20;
+}
+
+/* All views: header item coverage table entry for ow coverage rate */
+td.headerCovTableEntryLo
+{
+ text-align: right;
+ color: #000000;
+ font-family: sans-serif;
+ font-weight: bold;
+ white-space: nowrap;
+ padding-left: 12px;
+ padding-right: 4px;
+ background-color: #ff0000;
+}
+
+/* All views: header legend value for legend entry */
+td.headerValueLeg
+{
+ text-align: left;
+ color: #000000;
+ font-family: sans-serif;
+ font-size: 80%;
+ white-space: nowrap;
+ padding-top: 4px;
+}
+
+/* All views: color of horizontal ruler */
+td.ruler
+{
+ background-color: #6688d4;
+}
+
+/* All views: version string format */
+td.versionInfo
+{
+ text-align: center;
+ padding-top: 2px;
+ font-family: sans-serif;
+ font-style: italic;
+}
+
+/* Directory view/File view (all)/Test case descriptions:
+ table headline format */
+td.tableHead
+{
+ text-align: center;
+ color: #ffffff;
+ background-color: #6688d4;
+ font-family: sans-serif;
+ font-size: 120%;
+ font-weight: bold;
+ white-space: nowrap;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
+span.tableHeadSort
+{
+ padding-right: 4px;
+}
+
+/* Directory view/File view (all): filename entry format */
+td.coverFile
+{
+ text-align: left;
+ padding-left: 10px;
+ padding-right: 20px;
+ color: #284fa8;
+ background-color: #dae7fe;
+ font-family: monospace;
+}
+
+/* Directory view/File view (all): filename entry format */
+td.overallOwner
+{
+ text-align: center;
+ font-weight: bold;
+ font-family: sans-serif;
+ background-color: #dae7fe;
+ padding-right: 10px;
+ padding-left: 10px;
+}
+
+/* Directory view/File view (all): filename entry format */
+td.ownerName
+{
+ text-align: right;
+ font-style: italic;
+ font-family: sans-serif;
+ background-color: #E5DBDB;
+ padding-right: 10px;
+ padding-left: 20px;
+}
+
+/* Directory view/File view (all): bar-graph entry format*/
+td.coverBar
+{
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #dae7fe;
+}
+
+/* Directory view/File view (all): bar-graph entry format*/
+td.owner_coverBar
+{
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #E5DBDB;
+}
+
+/* Directory view/File view (all): bar-graph outline color */
+td.coverBarOutline
+{
+ background-color: #000000;
+}
+
+/* Directory view/File view (all): percentage entry for files with
+ high coverage rate */
+td.coverPerHi
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #a7fc9d;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+/* 'owner' entry: slightly lighter color than 'coverPerHi' */
+td.owner_coverPerHi
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #82E0AA;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+/* Directory view/File view (all): line count entry */
+td.coverNumDflt
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #dae7fe;
+ white-space: nowrap;
+ font-family: sans-serif;
+}
+
+/* td background color and font for the 'owner' section of the table */
+td.ownerTla
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #E5DBDB;
+ white-space: nowrap;
+ font-family: sans-serif;
+ font-style: italic;
+}
+
+/* Directory view/File view (all): line count entry for files with
+ high coverage rate */
+td.coverNumHi
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #a7fc9d;
+ white-space: nowrap;
+ font-family: sans-serif;
+}
+
+td.owner_coverNumHi
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #82E0AA;
+ white-space: nowrap;
+ font-family: sans-serif;
+}
+
+/* Directory view/File view (all): percentage entry for files with
+ medium coverage rate */
+td.coverPerMed
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #ffea20;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+td.owner_coverPerMed
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #F9E79F;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+/* Directory view/File view (all): line count entry for files with
+ medium coverage rate */
+td.coverNumMed
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #ffea20;
+ white-space: nowrap;
+ font-family: sans-serif;
+}
+
+td.owner_coverNumMed
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #F9E79F;
+ white-space: nowrap;
+ font-family: sans-serif;
+}
+
+/* Directory view/File view (all): percentage entry for files with
+ low coverage rate */
+td.coverPerLo
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #ff0000;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+td.owner_coverPerLo
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #EC7063;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+/* Directory view/File view (all): line count entry for files with
+ low coverage rate */
+td.coverNumLo
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #ff0000;
+ white-space: nowrap;
+ font-family: sans-serif;
+}
+
+td.owner_coverNumLo
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #EC7063;
+ white-space: nowrap;
+ font-family: sans-serif;
+}
+
+/* File view (all): "show/hide details" link format */
+a.detail:link
+{
+ color: #b8d0ff;
+ font-size:80%;
+}
+
+/* File view (all): "show/hide details" link - visited format */
+a.detail:visited
+{
+ color: #b8d0ff;
+ font-size:80%;
+}
+
+/* File view (all): "show/hide details" link - activated format */
+a.detail:active
+{
+ color: #ffffff;
+ font-size:80%;
+}
+
+/* File view (detail): test name entry */
+td.testName
+{
+ text-align: right;
+ padding-right: 10px;
+ background-color: #dae7fe;
+ font-family: sans-serif;
+}
+
+/* File view (detail): test percentage entry */
+td.testPer
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #dae7fe;
+ font-family: sans-serif;
+}
+
+/* File view (detail): test lines count entry */
+td.testNum
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #dae7fe;
+ font-family: sans-serif;
+}
+
+/* Test case descriptions: test name format*/
+dt
+{
+ font-family: sans-serif;
+ font-weight: bold;
+}
+
+/* Test case descriptions: description table body */
+td.testDescription
+{
+ padding-top: 10px;
+ padding-left: 30px;
+ padding-bottom: 10px;
+ padding-right: 30px;
+ background-color: #dae7fe;
+}
+
+/* Source code view: function entry */
+td.coverFn
+{
+ text-align: left;
+ padding-left: 10px;
+ padding-right: 20px;
+ color: #284fa8;
+ background-color: #dae7fe;
+ font-family: monospace;
+}
+
+/* Source code view: function entry zero count*/
+td.coverFnLo
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #ff0000;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+/* Source code view: function entry nonzero count*/
+td.coverFnHi
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #dae7fe;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+td.coverFnAlias
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 20px;
+ color: #284fa8;
+ /* make this a slightly different color than the leader - otherwise,
+ otherwise the alias is hard to distinguish in the table */
+ background-color: #E5DBDB; /* very light pale grey/blue */
+ font-family: monospace;
+}
+
+/* Source code view: function entry zero count*/
+td.coverFnAliasLo
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #EC7063; /* lighter red */
+ font-family: sans-serif;
+}
+
+/* Source code view: function entry nonzero count*/
+td.coverFnAliasHi
+{
+ text-align: right;
+ padding-left: 10px;
+ padding-right: 10px;
+ background-color: #dae7fe;
+ font-weight: bold;
+ font-family: sans-serif;
+}
+
+/* Source code view: source code format */
+pre.source
+{
+ font-family: monospace;
+ white-space: pre;
+ margin-top: 2px;
+}
+
+/* Source code view: line number format */
+span.lineNum
+{
+ background-color: #efe383;
+}
+
+/* Source code view: format for Cov legend */
+span.coverLegendCov
+{
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-bottom: 2px;
+ background-color: #cad7fe;
+}
+
+/* Source code view: format for NoCov legend */
+span.coverLegendNoCov
+{
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-bottom: 2px;
+ background-color: #ff6230;
+}
+
+/* Source code view: format for the source code heading line */
+pre.sourceHeading
+{
+ white-space: pre;
+ font-family: monospace;
+ font-weight: bold;
+ margin: 0px;
+}
+
+/* All views: header legend value for low rate */
+td.headerValueLegL
+{
+ font-family: sans-serif;
+ text-align: center;
+ white-space: nowrap;
+ padding-left: 4px;
+ padding-right: 2px;
+ background-color: #ff0000;
+ font-size: 80%;
+}
+
+/* All views: header legend value for med rate */
+td.headerValueLegM
+{
+ font-family: sans-serif;
+ text-align: center;
+ white-space: nowrap;
+ padding-left: 2px;
+ padding-right: 2px;
+ background-color: #ffea20;
+ font-size: 80%;
+}
+
+/* All views: header legend value for hi rate */
+td.headerValueLegH
+{
+ font-family: sans-serif;
+ text-align: center;
+ white-space: nowrap;
+ padding-left: 2px;
+ padding-right: 4px;
+ background-color: #a7fc9d;
+ font-size: 80%;
+}
+
+/* All views except source code view: legend format for low coverage */
+span.coverLegendCovLo
+{
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 2px;
+ background-color: #ff0000;
+}
+
+/* All views except source code view: legend format for med coverage */
+span.coverLegendCovMed
+{
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 2px;
+ background-color: #ffea20;
+}
+
+/* All views except source code view: legend format for hi coverage */
+span.coverLegendCovHi
+{
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 2px;
+ background-color: #a7fc9d;
+}
+
+a.branchTla:link
+{
+ color: #000000;
+}
+
+a.branchTla:visited
+{
+ color: #000000;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Uncovered New Code (+ => 0):
+Newly added code is not tested" */
+td.tlaUNC
+{
+ text-align: right;
+ background-color: #FF6230;
+}
+td.tlaBgUNC {
+ background-color: #FF6230;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Uncovered New Code (+ => 0):
+Newly added code is not tested" */
+span.tlaUNC
+{
+ text-align: left;
+ background-color: #FF6230;
+}
+span.tlaBgUNC {
+ background-color: #FF6230;
+}
+a.tlaBgUNC {
+ background-color: #FF6230;
+ color: #000000;
+}
+
+td.headerCovTableHeadUNC {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #FF6230;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Lost Baseline Coverage (1 => 0):
+Unchanged code is no longer tested" */
+td.tlaLBC
+{
+ text-align: right;
+ background-color: #FF6230;
+}
+td.tlaBgLBC {
+ background-color: #FF6230;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Lost Baseline Coverage (1 => 0):
+Unchanged code is no longer tested" */
+span.tlaLBC
+{
+ text-align: left;
+ background-color: #FF6230;
+}
+span.tlaBgLBC {
+ background-color: #FF6230;
+}
+a.tlaBgLBC {
+ background-color: #FF6230;
+ color: #000000;
+}
+
+td.headerCovTableHeadLBC {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #FF6230;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Uncovered Included Code (# => 0):
+Previously unused code is untested" */
+td.tlaUIC
+{
+ text-align: right;
+ background-color: #FF6230;
+}
+td.tlaBgUIC {
+ background-color: #FF6230;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Uncovered Included Code (# => 0):
+Previously unused code is untested" */
+span.tlaUIC
+{
+ text-align: left;
+ background-color: #FF6230;
+}
+span.tlaBgUIC {
+ background-color: #FF6230;
+}
+a.tlaBgUIC {
+ background-color: #FF6230;
+ color: #000000;
+}
+
+td.headerCovTableHeadUIC {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #FF6230;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Uncovered Baseline Code (0 => 0):
+Unchanged code was untested before, is untested now" */
+td.tlaUBC
+{
+ text-align: right;
+ background-color: #FF6230;
+}
+td.tlaBgUBC {
+ background-color: #FF6230;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Uncovered Baseline Code (0 => 0):
+Unchanged code was untested before, is untested now" */
+span.tlaUBC
+{
+ text-align: left;
+ background-color: #FF6230;
+}
+span.tlaBgUBC {
+ background-color: #FF6230;
+}
+a.tlaBgUBC {
+ background-color: #FF6230;
+ color: #000000;
+}
+
+td.headerCovTableHeadUBC {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #FF6230;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Gained Baseline Coverage (0 => 1):
+Unchanged code is tested now" */
+td.tlaGBC
+{
+ text-align: right;
+ background-color: #CAD7FE;
+}
+td.tlaBgGBC {
+ background-color: #CAD7FE;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Gained Baseline Coverage (0 => 1):
+Unchanged code is tested now" */
+span.tlaGBC
+{
+ text-align: left;
+ background-color: #CAD7FE;
+}
+span.tlaBgGBC {
+ background-color: #CAD7FE;
+}
+a.tlaBgGBC {
+ background-color: #CAD7FE;
+ color: #000000;
+}
+
+td.headerCovTableHeadGBC {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #CAD7FE;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Gained Included Coverage (# => 1):
+Previously unused code is tested now" */
+td.tlaGIC
+{
+ text-align: right;
+ background-color: #CAD7FE;
+}
+td.tlaBgGIC {
+ background-color: #CAD7FE;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Gained Included Coverage (# => 1):
+Previously unused code is tested now" */
+span.tlaGIC
+{
+ text-align: left;
+ background-color: #CAD7FE;
+}
+span.tlaBgGIC {
+ background-color: #CAD7FE;
+}
+a.tlaBgGIC {
+ background-color: #CAD7FE;
+ color: #000000;
+}
+
+td.headerCovTableHeadGIC {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #CAD7FE;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Gained New Coverage (+ => 1):
+Newly added code is tested" */
+td.tlaGNC
+{
+ text-align: right;
+ background-color: #CAD7FE;
+}
+td.tlaBgGNC {
+ background-color: #CAD7FE;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Gained New Coverage (+ => 1):
+Newly added code is tested" */
+span.tlaGNC
+{
+ text-align: left;
+ background-color: #CAD7FE;
+}
+span.tlaBgGNC {
+ background-color: #CAD7FE;
+}
+a.tlaBgGNC {
+ background-color: #CAD7FE;
+ color: #000000;
+}
+
+td.headerCovTableHeadGNC {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #CAD7FE;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Covered Baseline Code (1 => 1):
+Unchanged code was tested before and is still tested" */
+td.tlaCBC
+{
+ text-align: right;
+ background-color: #CAD7FE;
+}
+td.tlaBgCBC {
+ background-color: #CAD7FE;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Covered Baseline Code (1 => 1):
+Unchanged code was tested before and is still tested" */
+span.tlaCBC
+{
+ text-align: left;
+ background-color: #CAD7FE;
+}
+span.tlaBgCBC {
+ background-color: #CAD7FE;
+}
+a.tlaBgCBC {
+ background-color: #CAD7FE;
+ color: #000000;
+}
+
+td.headerCovTableHeadCBC {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #CAD7FE;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Excluded Uncovered Baseline (0 => #):
+Previously untested code is unused now" */
+td.tlaEUB
+{
+ text-align: right;
+ background-color: #FFFFFF;
+}
+td.tlaBgEUB {
+ background-color: #FFFFFF;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Excluded Uncovered Baseline (0 => #):
+Previously untested code is unused now" */
+span.tlaEUB
+{
+ text-align: left;
+ background-color: #FFFFFF;
+}
+span.tlaBgEUB {
+ background-color: #FFFFFF;
+}
+a.tlaBgEUB {
+ background-color: #FFFFFF;
+ color: #000000;
+}
+
+td.headerCovTableHeadEUB {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #FFFFFF;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Excluded Covered Baseline (1 => #):
+Previously tested code is unused now" */
+td.tlaECB
+{
+ text-align: right;
+ background-color: #FFFFFF;
+}
+td.tlaBgECB {
+ background-color: #FFFFFF;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Excluded Covered Baseline (1 => #):
+Previously tested code is unused now" */
+span.tlaECB
+{
+ text-align: left;
+ background-color: #FFFFFF;
+}
+span.tlaBgECB {
+ background-color: #FFFFFF;
+}
+a.tlaBgECB {
+ background-color: #FFFFFF;
+ color: #000000;
+}
+
+td.headerCovTableHeadECB {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #FFFFFF;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Deleted Uncovered Baseline (0 => -):
+Previously untested code has been deleted" */
+td.tlaDUB
+{
+ text-align: right;
+ background-color: #FFFFFF;
+}
+td.tlaBgDUB {
+ background-color: #FFFFFF;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Deleted Uncovered Baseline (0 => -):
+Previously untested code has been deleted" */
+span.tlaDUB
+{
+ text-align: left;
+ background-color: #FFFFFF;
+}
+span.tlaBgDUB {
+ background-color: #FFFFFF;
+}
+a.tlaBgDUB {
+ background-color: #FFFFFF;
+ color: #000000;
+}
+
+td.headerCovTableHeadDUB {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #FFFFFF;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Deleted Covered Baseline (1 => -):
+Previously tested code has been deleted" */
+td.tlaDCB
+{
+ text-align: right;
+ background-color: #FFFFFF;
+}
+td.tlaBgDCB {
+ background-color: #FFFFFF;
+}
+
+/* Source code view/table entry backround: format for lines classified as "Deleted Covered Baseline (1 => -):
+Previously tested code has been deleted" */
+span.tlaDCB
+{
+ text-align: left;
+ background-color: #FFFFFF;
+}
+span.tlaBgDCB {
+ background-color: #FFFFFF;
+}
+a.tlaBgDCB {
+ background-color: #FFFFFF;
+ color: #000000;
+}
+
+td.headerCovTableHeadDCB {
+ text-align: center;
+ padding-right: 6px;
+ padding-left: 6px;
+ padding-bottom: 0px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ background-color: #FFFFFF;
+}
+
+/* Source code view: format for date/owner bin that is not hit */
+span.missBins
+{
+ background-color: #ff0000 /* red */
+}
diff --git a/coverage/glass.png b/coverage/glass.png
new file mode 100644
index 0000000..e1abc00
Binary files /dev/null and b/coverage/glass.png differ
diff --git a/coverage/index-sort-f.html b/coverage/index-sort-f.html
new file mode 100644
index 0000000..c786517
--- /dev/null
+++ b/coverage/index-sort-f.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - coverage.out
+
+
+
+
+
+
+ LCOV - code coverage report |
+  |
+
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+  |
+
+ |
+
+
+  |
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/coverage/index-sort-l.html b/coverage/index-sort-l.html
new file mode 100644
index 0000000..80f3232
--- /dev/null
+++ b/coverage/index-sort-l.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - coverage.out
+
+
+
+
+
+
+ LCOV - code coverage report |
+  |
+
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+  |
+
+ |
+
+
+  |
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/coverage/index.html b/coverage/index.html
new file mode 100644
index 0000000..cfcf830
--- /dev/null
+++ b/coverage/index.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - coverage.out
+
+
+
+
+
+
+ LCOV - code coverage report |
+  |
+
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+  |
+
+ |
+
+
+  |
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/coverage/ruby.png b/coverage/ruby.png
new file mode 100644
index 0000000..991b6d4
Binary files /dev/null and b/coverage/ruby.png differ
diff --git a/coverage/snow.png b/coverage/snow.png
new file mode 100644
index 0000000..2cdae10
Binary files /dev/null and b/coverage/snow.png differ
diff --git a/coverage/updown.png b/coverage/updown.png
new file mode 100644
index 0000000..aa56a23
Binary files /dev/null and b/coverage/updown.png differ
diff --git a/demo.rbxl b/demo.rbxl
deleted file mode 100644
index a2ac526..0000000
Binary files a/demo.rbxl and /dev/null differ
diff --git a/demo/src/ReplicatedStorage/track.luau b/demo/src/ReplicatedStorage/track.luau
index 1214a78..79c4006 100644
--- a/demo/src/ReplicatedStorage/track.luau
+++ b/demo/src/ReplicatedStorage/track.luau
@@ -1,48 +1,48 @@
-local events = {}
-
-local function trackers_invoke(event, component, entity, ...)
- local trackers = events[event][component]
- if not trackers then
- return
- end
-
- for _, tracker in trackers do
- tracker(entity, data)
- end
-end
-
-local function trackers_init(event, component, fn)
- local ob = events[event]
-
- return {
- connect = function(component, fn)
- local trackers = ob[component]
- if not trackers then
- trackers = {}
- ob[component] = trackers
- end
-
- table.insert(trackers, fn)
- end,
- invoke = function(component, ...)
- trackers_invoke(event, component, ...)
- end
- }
- return function(component, fn)
- local trackers = ob[component]
- if not trackers then
- trackers = {}
- ob[component] = trackers
- end
-
- table.insert(trackers, fn)
- end
-end
-
-local trackers = {
- emplace = trackers_init("emplace"),
- add = trackers_init("added"),
- remove = trackers_init("removed")
-}
-
-return trackers
+local events = {}
+
+local function trackers_invoke(event, component, entity, ...)
+ local trackers = events[event][component]
+ if not trackers then
+ return
+ end
+
+ for _, tracker in trackers do
+ tracker(entity, data)
+ end
+end
+
+local function trackers_init(event, component, fn)
+ local ob = events[event]
+
+ return {
+ connect = function(component, fn)
+ local trackers = ob[component]
+ if not trackers then
+ trackers = {}
+ ob[component] = trackers
+ end
+
+ table.insert(trackers, fn)
+ end,
+ invoke = function(component, ...)
+ trackers_invoke(event, component, ...)
+ end
+ }
+ return function(component, fn)
+ local trackers = ob[component]
+ if not trackers then
+ trackers = {}
+ ob[component] = trackers
+ end
+
+ table.insert(trackers, fn)
+ end
+end
+
+local trackers = {
+ emplace = trackers_init("emplace"),
+ add = trackers_init("added"),
+ remove = trackers_init("removed")
+}
+
+return trackers
diff --git a/demo/src/StarterPlayer/StarterPlayerScripts/systems/lol.luau b/demo/src/StarterPlayer/StarterPlayerScripts/systems/lol.luau
index 75f9fa4..6e09edb 100644
--- a/demo/src/StarterPlayer/StarterPlayerScripts/systems/lol.luau
+++ b/demo/src/StarterPlayer/StarterPlayerScripts/systems/lol.luau
@@ -1,67 +1,67 @@
---!optimize 2
---!native
---!strict
-
-local ReplicatedStorage = game:GetService("ReplicatedStorage")
-local jecs = require(ReplicatedStorage.ecs)
-local __ = jecs.Wildcard
-local std = ReplicatedStorage.std
-
-local world = require(std.world)
-
-local Position = world:component() :: jecs.Entity
-local Previous = jecs.Rest
-local pre = jecs.pair(Position, Previous)
-
-local added = world
- :query(Position)
- :without(pre)
- :cached()
-local changed = world
- :query(Position, pre)
- :cached()
-local removed = world
- :query(pre)
- :without(Position)
- :cached()
-
-local children = {}
-for i = 1, 10 do
- local e = world:entity()
- world:set(e, Position, vector.create(i, i, i))
- table.insert(children, e)
-end
-local function flip()
- return math.random() > 0.5
-end
-local function system()
- for i, child in children do
- world:set(child, Position, vector.create(i,i,i))
- end
- for e, p in added:iter() do
- world:set(e, pre, p)
- end
- for i, child in children do
- if flip() then
- world:set(child, Position, vector.create(i + 1, i + 1, i + 1))
- end
- end
- for e, new, old in changed:iter() do
- if new ~= old then
- world:set(e, pre, new)
- end
- end
-
- for i, child in children do
- world:remove(child, Position)
- end
-
- for e in removed:iter() do
- world:remove(e, pre)
- end
-end
-local scheduler = require(std.scheduler)
-
-scheduler.SYSTEM(system)
-
-return 0
+--!optimize 2
+--!native
+--!strict
+
+local ReplicatedStorage = game:GetService("ReplicatedStorage")
+local jecs = require(ReplicatedStorage.ecs)
+local __ = jecs.Wildcard
+local std = ReplicatedStorage.std
+
+local world = require(std.world)
+
+local Position = world:component() :: jecs.Entity
+local Previous = jecs.Rest
+local pre = jecs.pair(Position, Previous)
+
+local added = world
+ :query(Position)
+ :without(pre)
+ :cached()
+local changed = world
+ :query(Position, pre)
+ :cached()
+local removed = world
+ :query(pre)
+ :without(Position)
+ :cached()
+
+local children = {}
+for i = 1, 10 do
+ local e = world:entity()
+ world:set(e, Position, vector.create(i, i, i))
+ table.insert(children, e)
+end
+local function flip()
+ return math.random() > 0.5
+end
+local function system()
+ for i, child in children do
+ world:set(child, Position, vector.create(i,i,i))
+ end
+ for e, p in added:iter() do
+ world:set(e, pre, p)
+ end
+ for i, child in children do
+ if flip() then
+ world:set(child, Position, vector.create(i + 1, i + 1, i + 1))
+ end
+ end
+ for e, new, old in changed:iter() do
+ if new ~= old then
+ world:set(e, pre, new)
+ end
+ end
+
+ for i, child in children do
+ world:remove(child, Position)
+ end
+
+ for e in removed:iter() do
+ world:remove(e, pre)
+ end
+end
+local scheduler = require(std.scheduler)
+
+scheduler.SYSTEM(system)
+
+return 0
diff --git a/demo/src/StarterPlayer/StarterPlayerScripts/systems/lol2.luau b/demo/src/StarterPlayer/StarterPlayerScripts/systems/lol2.luau
index 3b40d08..dcb695a 100644
--- a/demo/src/StarterPlayer/StarterPlayerScripts/systems/lol2.luau
+++ b/demo/src/StarterPlayer/StarterPlayerScripts/systems/lol2.luau
@@ -1,90 +1,90 @@
---!optimize 2
---!native
---!strict
-
-local ReplicatedStorage = game:GetService("ReplicatedStorage")
-local jecs = require(ReplicatedStorage.ecs)
-local __ = jecs.Wildcard
-local std = ReplicatedStorage.std
-
-local world = require(std.world)
-
-local Position = world:component() :: jecs.Entity
-local Previous = jecs.Rest
-local pre = jecs.pair(Position, Previous)
-
-local added = world
- :query(Position)
- :without(pre)
- :cached()
-local changed = world
- :query(Position, pre)
- :cached()
-local removed = world
- :query(pre)
- :without(Position)
- :cached()
-
-local children = {}
-for i = 1, 10 do
- local e = world:entity()
- world:set(e, Position, vector.create(i, i, i))
- table.insert(children, e)
-end
-local function flip()
- return math.random() > 0.5
-end
-local entity_index = world.entity_index
-local function copy(archetypes, id)
- for _, archetype in archetypes do
-
- local to = jecs.archetype_traverse_add(world, pre, archetype)
- local columns = to.columns
- local records = to.records
- local old = columns[records[pre].column]
- local new = columns[records[id].column]
-
- if to ~= archetype then
- for _, entity in archetype.entities do
- local r = jecs.entity_index_try_get_fast(entity_index, entity)
- jecs.entity_move(entity_index, entity, r, to)
- end
- end
-
- table.move(new, 1, #new, 1, old)
-
- end
-end
-local function system2()
- for i, child in children do
- world:set(child, Position, vector.create(i,i,i))
- end
- for e, p in added:iter() do
- end
- copy(added:archetypes(), Position)
- for i, child in children do
- if flip() then
- world:set(child, Position, vector.create(i + 1, i + 1, i + 1))
- end
- end
-
- for e, new, old in changed:iter() do
- if new ~= old then
- end
- end
-
- copy(changed:archetypes(), Position)
-
- for i, child in children do
- world:remove(child, Position)
- end
-
- for e in removed:iter() do
- world:remove(e, pre)
- end
-end
-local scheduler = require(std.scheduler)
-
-scheduler.SYSTEM(system2)
-
-return 0
+--!optimize 2
+--!native
+--!strict
+
+local ReplicatedStorage = game:GetService("ReplicatedStorage")
+local jecs = require(ReplicatedStorage.ecs)
+local __ = jecs.Wildcard
+local std = ReplicatedStorage.std
+
+local world = require(std.world)
+
+local Position = world:component() :: jecs.Entity
+local Previous = jecs.Rest
+local pre = jecs.pair(Position, Previous)
+
+local added = world
+ :query(Position)
+ :without(pre)
+ :cached()
+local changed = world
+ :query(Position, pre)
+ :cached()
+local removed = world
+ :query(pre)
+ :without(Position)
+ :cached()
+
+local children = {}
+for i = 1, 10 do
+ local e = world:entity()
+ world:set(e, Position, vector.create(i, i, i))
+ table.insert(children, e)
+end
+local function flip()
+ return math.random() > 0.5
+end
+local entity_index = world.entity_index
+local function copy(archetypes, id)
+ for _, archetype in archetypes do
+
+ local to = jecs.archetype_traverse_add(world, pre, archetype)
+ local columns = to.columns
+ local records = to.records
+ local old = columns[records[pre].column]
+ local new = columns[records[id].column]
+
+ if to ~= archetype then
+ for _, entity in archetype.entities do
+ local r = jecs.entity_index_try_get_fast(entity_index, entity)
+ jecs.entity_move(entity_index, entity, r, to)
+ end
+ end
+
+ table.move(new, 1, #new, 1, old)
+
+ end
+end
+local function system2()
+ for i, child in children do
+ world:set(child, Position, vector.create(i,i,i))
+ end
+ for e, p in added:iter() do
+ end
+ copy(added:archetypes(), Position)
+ for i, child in children do
+ if flip() then
+ world:set(child, Position, vector.create(i + 1, i + 1, i + 1))
+ end
+ end
+
+ for e, new, old in changed:iter() do
+ if new ~= old then
+ end
+ end
+
+ copy(changed:archetypes(), Position)
+
+ for i, child in children do
+ world:remove(child, Position)
+ end
+
+ for e in removed:iter() do
+ world:remove(e, pre)
+ end
+end
+local scheduler = require(std.scheduler)
+
+scheduler.SYSTEM(system2)
+
+return 0
diff --git a/jecs.luau b/jecs.luau
index 39fa865..0dadaec 100644
--- a/jecs.luau
+++ b/jecs.luau
@@ -52,7 +52,7 @@ export type Archetype = {
type ecs_record_t = {
archetype: ecs_archetype_t,
row: number,
- dense: i24
+ dense: i24,
}
type ecs_id_record_t = {
@@ -90,8 +90,8 @@ type ecs_query_data_t = {
}
type ecs_observer_t = {
- callback: (archetype: ecs_archetype_t) -> (),
- query: ecs_query_data_t,
+ callback: (archetype: ecs_archetype_t) -> (),
+ query: ecs_query_data_t,
}
type ecs_observable_t = Map>
@@ -295,10 +295,6 @@ local function ecs_pair_second(world: ecs_world_t, e: i53)
return ecs_get_alive(world, obj)
end
-local function ecs_component_record(world: ecs_world_t, component: i53)
- return world.component_index[component]
-end
-
local function query_match(query: ecs_query_data_t,
archetype: ecs_archetype_t)
local records = archetype.records
@@ -559,10 +555,10 @@ local function id_record_ensure(world: ecs_world_t, id: number): ecs_id_record_t
local target = 0
local is_pair = ECS_IS_PAIR(id)
if is_pair then
- relation = entity_index_get_alive(entity_index, ECS_PAIR_FIRST(id))
+ relation = entity_index_get_alive(entity_index, ECS_PAIR_FIRST(id)) :: i53
assert(relation and entity_index_is_alive(
entity_index, relation), ECS_INTERNAL_ERROR)
- target = entity_index_get_alive(entity_index, ECS_PAIR_SECOND(id))
+ target = entity_index_get_alive(entity_index, ECS_PAIR_SECOND(id)) :: i53
assert(target and entity_index_is_alive(
entity_index, target), ECS_INTERNAL_ERROR)
end
@@ -646,7 +642,6 @@ local function archetype_create(world: ecs_world_t, id_types: { i24 }, ty, prev:
local records: { number } = {}
local counts: {number} = {}
- local entity_index = world.entity_index
local archetype: ecs_archetype_t = {
columns = columns,
entities = {},
diff --git a/mkdocs.yml b/mkdocs.yml
deleted file mode 100644
index 1a47333..0000000
--- a/mkdocs.yml
+++ /dev/null
@@ -1,186 +0,0 @@
-site_name: Jecs
-site_url: jecs.github.io/jecs
-repo_name: ukendio/jecs
-repo_url: https://github.com/ukendio/jecs
-
-extra:
- version:
- provider: mike
-
-theme:
- name: material
- custom_dir: docs/assets/overrides
- logo: assets/logo
- favicon: assets/logo-dark.svg
- palette:
- - media: "(prefers-color-scheme: dark)"
- scheme: fusiondoc-dark
- toggle:
- icon: octicons/sun-24
- title: Switch to light theme
- - media: "(prefers-color-scheme: light)"
- scheme: fusiondoc-light
- toggle:
- icon: octicons/moon-24
- title: Switch to dark theme
- font:
- text: Plus Jakarta Sans
- code: JetBrains Mono
- features:
- - navigation.tabs
- - navigation.top
- - navigation.sections
- - navigation.instant
- - navigation.indexes
- - search.suggest
- - search.highlight
- icon:
- repo: octicons/mark-github-16
-
-extra_css:
- - assets/theme/fusiondoc.css
- - assets/theme/colours.css
- - assets/theme/code.css
- - assets/theme/paragraph.css
- - assets/theme/page.css
- - assets/theme/admonition.css
- - assets/theme/404.css
- - assets/theme/api-reference.css
- - assets/theme/dev-tools.css
-
-extra_javascript:
- - assets/scripts/smooth-scroll.js
-
-nav:
- - Home: index.md
- - Tutorials:
- - Get Started: tutorials/index.md
- - Installing Fusion: tutorials/get-started/installing-fusion.md
- - Developer Tools: tutorials/get-started/developer-tools.md
- - Getting Help: tutorials/get-started/getting-help.md
- - Fundamentals:
- - Scopes: tutorials/fundamentals/scopes.md
- - Values: tutorials/fundamentals/values.md
- - Observers: tutorials/fundamentals/observers.md
- - Computeds: tutorials/fundamentals/computeds.md
- - Tables:
- - ForValues: tutorials/tables/forvalues.md
- - ForKeys: tutorials/tables/forkeys.md
- - ForPairs: tutorials/tables/forpairs.md
- - Animation:
- - Tweens: tutorials/animation/tweens.md
- - Springs: tutorials/animation/springs.md
- - Roblox:
- - Hydration: tutorials/roblox/hydration.md
- - New Instances: tutorials/roblox/new-instances.md
- - Parenting: tutorials/roblox/parenting.md
- - Events: tutorials/roblox/events.md
- - Change Events: tutorials/roblox/change-events.md
- - Outputs: tutorials/roblox/outputs.md
- - References: tutorials/roblox/references.md
- - Best Practices:
- - Components: tutorials/best-practices/components.md
- - Instance Handling: tutorials/best-practices/instance-handling.md
- - Callbacks: tutorials/best-practices/callbacks.md
- - State: tutorials/best-practices/state.md
- - Sharing Values: tutorials/best-practices/sharing-values.md
- - Error Safety: tutorials/best-practices/error-safety.md
- - Optimisation: tutorials/best-practices/optimisation.md
-
- - Examples:
- - Home: examples/index.md
- - Cookbook:
- - examples/cookbook/index.md
- - Player List: examples/cookbook/player-list.md
- - Animated Computed: examples/cookbook/animated-computed.md
- - Fetch Data From Server: examples/cookbook/fetch-data-from-server.md
- - Light & Dark Theme: examples/cookbook/light-and-dark-theme.md
- - Button Component: examples/cookbook/button-component.md
- - Loading Spinner: examples/cookbook/loading-spinner.md
- - Drag & Drop: examples/cookbook/drag-and-drop.md
- - API Reference:
- - api-reference/index.md
- - General:
- - Errors: api-reference/general/errors.md
- - Types:
- - Contextual: api-reference/general/types/contextual.md
- - Version: api-reference/general/types/version.md
- - Members:
- - Contextual: api-reference/general/members/contextual.md
- - Safe: api-reference/general/members/safe.md
- - version: api-reference/general/members/version.md
- - Memory:
- - Types:
- - Scope: api-reference/memory/types/scope.md
- - ScopedObject: api-reference/memory/types/scopedobject.md
- - Task: api-reference/memory/types/task.md
- - Members:
- - deriveScope: api-reference/memory/members/derivescope.md
- - doCleanup: api-reference/memory/members/docleanup.md
- - scoped: api-reference/memory/members/scoped.md
- - State:
- - Types:
- - UsedAs: api-reference/state/types/usedas.md
- - Computed: api-reference/state/types/computed.md
- - Dependency: api-reference/state/types/dependency.md
- - Dependent: api-reference/state/types/dependent.md
- - For: api-reference/state/types/for.md
- - Observer: api-reference/state/types/observer.md
- - StateObject: api-reference/state/types/stateobject.md
- - Use: api-reference/state/types/use.md
- - Value: api-reference/state/types/value.md
- - Members:
- - Computed: api-reference/state/members/computed.md
- - ForKeys: api-reference/state/members/forkeys.md
- - ForPairs: api-reference/state/members/forpairs.md
- - ForValues: api-reference/state/members/forvalues.md
- - Observer: api-reference/state/members/observer.md
- - peek: api-reference/state/members/peek.md
- - Value: api-reference/state/members/value.md
- - Roblox:
- - Types:
- - Child: api-reference/roblox/types/child.md
- - PropertyTable: api-reference/roblox/types/propertytable.md
- - SpecialKey: api-reference/roblox/types/specialkey.md
- - Members:
- - Attribute: api-reference/roblox/members/attribute.md
- - AttributeChange: api-reference/roblox/members/attributechange.md
- - AttributeOut: api-reference/roblox/members/attributeout.md
- - Children: api-reference/roblox/members/children.md
- - Hydrate: api-reference/roblox/members/hydrate.md
- - New: api-reference/roblox/members/new.md
- - OnChange: api-reference/roblox/members/onchange.md
- - OnEvent: api-reference/roblox/members/onevent.md
- - Out: api-reference/roblox/members/out.md
- - Ref: api-reference/roblox/members/ref.md
- - Animation:
- - Types:
- - Animatable: api-reference/animation/types/animatable.md
- - Spring: api-reference/animation/types/spring.md
- - Tween: api-reference/animation/types/tween.md
- - Members:
- - Tween: api-reference/animation/members/tween.md
- - Spring: api-reference/animation/members/spring.md
- - Extras:
- - Home: extras/index.md
- - Backgrounds: extras/backgrounds.md
- - Brand Guidelines: extras/brand-guidelines.md
-
-markdown_extensions:
- - admonition
- - attr_list
- - meta
- - md_in_html
- - pymdownx.superfences
- - pymdownx.betterem
- - pymdownx.details
- - pymdownx.tabbed:
- alternate_style: true
- - pymdownx.inlinehilite
- - toc:
- permalink: true
- - pymdownx.highlight:
- guess_lang: false
- - pymdownx.emoji:
- emoji_index: !!python/name:materialx.emoji.twemoji
- emoji_generator: !!python/name:materialx.emoji.to_svg
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..1bb8abc
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,4464 @@
+{
+ "name": "@rbxts/jecs",
+ "version": "0.5.5",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@rbxts/jecs",
+ "version": "0.5.5",
+ "license": "MIT",
+ "devDependencies": {
+ "@rbxts/compiler-types": "^2.3.0-types.1",
+ "@rbxts/types": "^1.0.781",
+ "@typescript-eslint/eslint-plugin": "^5.8.0",
+ "@typescript-eslint/parser": "^5.8.0",
+ "eslint": "^8.5.0",
+ "eslint-config-prettier": "^8.3.0",
+ "eslint-plugin-prettier": "^4.0.0",
+ "eslint-plugin-roblox-ts": "^0.0.32",
+ "prettier": "^2.5.1",
+ "roblox-ts": "^3.0.0",
+ "typescript": "^5.4.2",
+ "vitepress": "^1.3.0"
+ }
+ },
+ "node_modules/@algolia/autocomplete-core": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz",
+ "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/autocomplete-plugin-algolia-insights": "1.17.7",
+ "@algolia/autocomplete-shared": "1.17.7"
+ }
+ },
+ "node_modules/@algolia/autocomplete-plugin-algolia-insights": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz",
+ "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/autocomplete-shared": "1.17.7"
+ },
+ "peerDependencies": {
+ "search-insights": ">= 1 < 3"
+ }
+ },
+ "node_modules/@algolia/autocomplete-preset-algolia": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz",
+ "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/autocomplete-shared": "1.17.7"
+ },
+ "peerDependencies": {
+ "@algolia/client-search": ">= 4.9.1 < 6",
+ "algoliasearch": ">= 4.9.1 < 6"
+ }
+ },
+ "node_modules/@algolia/autocomplete-shared": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz",
+ "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==",
+ "dev": true,
+ "peerDependencies": {
+ "@algolia/client-search": ">= 4.9.1 < 6",
+ "algoliasearch": ">= 4.9.1 < 6"
+ }
+ },
+ "node_modules/@algolia/client-abtesting": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.23.0.tgz",
+ "integrity": "sha512-AyZ+9CUgWXwaaJ2lSwOJSy+/w0MFBPFqLrjWYs/HEpYMzBuFfGNZ7gEM9a7h4j7jY8hSBARBl8qdvInmj5vOEQ==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-analytics": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.23.0.tgz",
+ "integrity": "sha512-oeKCPwLBnTEPF/RWr0aaJnrfRDfFRLT5O7KV0OF1NmpEXvmzLmN7RwnwDKsNtPUHNfpJ6esP9xzkPEtJabrZ2w==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-common": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.23.0.tgz",
+ "integrity": "sha512-9jacdC44vXLSaYKNLkFpbU1J4BbBPi/N7uoPhcGO//8ubRuVzigH6+RfK5FbudmQlqFt0J5DGUCVeTlHtgyUeg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-insights": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.23.0.tgz",
+ "integrity": "sha512-/Gw5UitweRsnyb24Td4XhjXmsx8PxFzCI0oW6FZZvyr4kjzB9ECP2IjO+PdDq1A2fzDl/LXQ+u8ROudoVnXnQg==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-personalization": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.23.0.tgz",
+ "integrity": "sha512-ivrEZBoXfDatpqpifgHauydxHEe4udNqJ0gy7adR2KODeQ+39MQeaT10I24mu+eylIuiQKJRqORgEdLZycq2qQ==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-query-suggestions": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.23.0.tgz",
+ "integrity": "sha512-DjSgJWqTcsnlXEKqDsU7Y2vB/W/VYLlr6UfkzJkMuKB554Ia7IJr4keP2AlHVjjbBG62IDpdh5OkEs/+fbWsOA==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-search": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.23.0.tgz",
+ "integrity": "sha512-XAYWUYUhEG4OIdo/N7H/OFFRD9fokfv3bBTky+4Y4/q07bxhnrGSUvcrU6JQ2jJTQyg6kv0ke1EIfiTO/Xxb+g==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/ingestion": {
+ "version": "1.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.23.0.tgz",
+ "integrity": "sha512-ULbykzzhhLVofCDU1m/CqSzTyKmjaxA/z1d6o6hgUuR6X7/dll9/G0lu0e4vmWIOItklWWrhU2V8sXD0YGBIHg==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/monitoring": {
+ "version": "1.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.23.0.tgz",
+ "integrity": "sha512-oB3wG7CgQJQr+uoijV7bWBphiSHkvGX43At8RGgkDyc7Aeabcp9ik5HgLC1YDgbHVOlQI+tce5HIbDCifzQCIg==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/recommend": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.23.0.tgz",
+ "integrity": "sha512-4PWvCV6VGhnCMAbv2zfQUAlc3ofMs6ovqKlC/xcp7tWaucYd//piHg9CcCM4S0p9OZznEGQMRYPt2uqbk6V9vg==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-browser-xhr": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.23.0.tgz",
+ "integrity": "sha512-bacOsX41pnsupNB0k0Ny+1JDchQxIsZIcp69GKDBT0NgTHG8OayEO141eFalNmGil+GXPY0NUPRpx+5s4RdhGA==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-fetch": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.23.0.tgz",
+ "integrity": "sha512-tVNFREexJWDrvc23evmRgAcb2KLZuVilOIB/rVnQCl0GDbqIWJuQ1lG22HKqvCEQFthHkgVFGLYE74wQ96768g==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-node-http": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.23.0.tgz",
+ "integrity": "sha512-XXHbq2heOZc9EFCc4z+uyHS9YRBygZbYQVsWjWZWx8hdAz+tkBX/jLHM9Xg+3zO0/v8JN6pcZzqYEVsdrLeNLg==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-common": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
+ "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.27.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
+ "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@docsearch/css": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz",
+ "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==",
+ "dev": true
+ },
+ "node_modules/@docsearch/js": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz",
+ "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==",
+ "dev": true,
+ "dependencies": {
+ "@docsearch/react": "3.8.2",
+ "preact": "^10.0.0"
+ }
+ },
+ "node_modules/@docsearch/react": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz",
+ "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/autocomplete-core": "1.17.7",
+ "@algolia/autocomplete-preset-algolia": "1.17.7",
+ "@docsearch/css": "3.8.2",
+ "algoliasearch": "^5.14.2"
+ },
+ "peerDependencies": {
+ "@types/react": ">= 16.8.0 < 19.0.0",
+ "react": ">= 16.8.0 < 19.0.0",
+ "react-dom": ">= 16.8.0 < 19.0.0",
+ "search-insights": ">= 1 < 3"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "search-insights": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz",
+ "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.3",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true
+ },
+ "node_modules/@iconify-json/simple-icons": {
+ "version": "1.2.29",
+ "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.29.tgz",
+ "integrity": "sha512-KYrxmxtRz6iOAulRiUsIBMUuXek+H+Evwf8UvYPIkbQ+KDoOqTegHx3q/w3GDDVC0qJYB+D3hXPMZcpm78qIuA==",
+ "dev": true,
+ "dependencies": {
+ "@iconify/types": "*"
+ }
+ },
+ "node_modules/@iconify/types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
+ "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@rbxts/compiler-types": {
+ "version": "2.3.0-types.2",
+ "resolved": "https://registry.npmjs.org/@rbxts/compiler-types/-/compiler-types-2.3.0-types.2.tgz",
+ "integrity": "sha512-ZfCn1LNrfMS0GCfnXvLVOPE9oNNBf5851JRBGy0ptuuOK1bDvV0fljP0Xx9w6LcLFb+NLTM2GKXX+gkoCh7CvA==",
+ "dev": true
+ },
+ "node_modules/@rbxts/types": {
+ "version": "1.0.844",
+ "resolved": "https://registry.npmjs.org/@rbxts/types/-/types-1.0.844.tgz",
+ "integrity": "sha512-qiUe7FDF8hyY2oxD+MgShgw4irAGethZWxy3APll4xd4IA9RuPo/shJknYoHvTA8XRXgxlKdT6wV1D3hek0YcQ==",
+ "dev": true
+ },
+ "node_modules/@roblox-ts/luau-ast": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@roblox-ts/luau-ast/-/luau-ast-2.0.0.tgz",
+ "integrity": "sha512-cmMi093IdwBOLVxwuordhM8AmtbyTIyRpsTbB0D/JauidW4SXsQRQowSwWjHo4QP0DRJBXvOIlxtqEQi50uNzQ==",
+ "dev": true
+ },
+ "node_modules/@roblox-ts/path-translator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@roblox-ts/path-translator/-/path-translator-1.1.0.tgz",
+ "integrity": "sha512-D0akTmnNYqBw+ZIek5JxocT3BjmbgGOuOy0x1nIIxHBPNLGCpzseToY8jyYs/0mlvnN2xnSP/k8Tv+jvGOQSwQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.12.0",
+ "fs-extra": "^11.2.0"
+ }
+ },
+ "node_modules/@roblox-ts/path-translator/node_modules/ajv": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
+ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@roblox-ts/path-translator/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/@roblox-ts/rojo-resolver": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@roblox-ts/rojo-resolver/-/rojo-resolver-1.1.0.tgz",
+ "integrity": "sha512-QmvVryu1EeME+3QUoG5j/gHGJoJUaffCgZ92mhlG7cJSd1uyhgpY4CNWriZAwZJYkTlzd5Htkpn+18yDFbOFXA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.17.1",
+ "fs-extra": "^11.2.0"
+ }
+ },
+ "node_modules/@roblox-ts/rojo-resolver/node_modules/ajv": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
+ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@roblox-ts/rojo-resolver/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz",
+ "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz",
+ "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz",
+ "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz",
+ "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz",
+ "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz",
+ "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz",
+ "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz",
+ "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz",
+ "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz",
+ "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz",
+ "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz",
+ "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz",
+ "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz",
+ "integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz",
+ "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz",
+ "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz",
+ "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz",
+ "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz",
+ "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz",
+ "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@shikijs/core": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz",
+ "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==",
+ "dev": true,
+ "dependencies": {
+ "@shikijs/engine-javascript": "2.5.0",
+ "@shikijs/engine-oniguruma": "2.5.0",
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4",
+ "hast-util-to-html": "^9.0.4"
+ }
+ },
+ "node_modules/@shikijs/engine-javascript": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz",
+ "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==",
+ "dev": true,
+ "dependencies": {
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "oniguruma-to-es": "^3.1.0"
+ }
+ },
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz",
+ "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==",
+ "dev": true,
+ "dependencies": {
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz",
+ "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==",
+ "dev": true,
+ "dependencies": {
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz",
+ "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==",
+ "dev": true,
+ "dependencies": {
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/transformers": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz",
+ "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==",
+ "dev": true,
+ "dependencies": {
+ "@shikijs/core": "2.5.0",
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz",
+ "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==",
+ "dev": true,
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
+ "dev": true
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true
+ },
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
+ "node_modules/@types/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
+ "dev": true
+ },
+ "node_modules/@types/markdown-it": {
+ "version": "14.1.2",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
+ "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
+ "dev": true,
+ "dependencies": {
+ "@types/linkify-it": "^5",
+ "@types/mdurl": "^2"
+ }
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "16.18.126",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz",
+ "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==",
+ "dev": true
+ },
+ "node_modules/@types/semver": {
+ "version": "7.7.0",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz",
+ "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==",
+ "dev": true
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true
+ },
+ "node_modules/@types/web-bluetooth": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
+ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
+ "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.4.0",
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/type-utils": "5.62.0",
+ "@typescript-eslint/utils": "5.62.0",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/experimental-utils": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz",
+ "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/utils": "5.62.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
+ "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
+ "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz",
+ "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "@typescript-eslint/utils": "5.62.0",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
+ "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
+ "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
+ "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
+ "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
+ "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.25.3",
+ "@vue/shared": "3.5.13",
+ "entities": "^4.5.0",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.0"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
+ "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
+ "dev": true,
+ "dependencies": {
+ "@vue/compiler-core": "3.5.13",
+ "@vue/shared": "3.5.13"
+ }
+ },
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
+ "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.25.3",
+ "@vue/compiler-core": "3.5.13",
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/compiler-ssr": "3.5.13",
+ "@vue/shared": "3.5.13",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.11",
+ "postcss": "^8.4.48",
+ "source-map-js": "^1.2.0"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
+ "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
+ "dev": true,
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/shared": "3.5.13"
+ }
+ },
+ "node_modules/@vue/devtools-api": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.2.tgz",
+ "integrity": "sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==",
+ "dev": true,
+ "dependencies": {
+ "@vue/devtools-kit": "^7.7.2"
+ }
+ },
+ "node_modules/@vue/devtools-kit": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz",
+ "integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==",
+ "dev": true,
+ "dependencies": {
+ "@vue/devtools-shared": "^7.7.2",
+ "birpc": "^0.2.19",
+ "hookable": "^5.5.3",
+ "mitt": "^3.0.1",
+ "perfect-debounce": "^1.0.0",
+ "speakingurl": "^14.0.1",
+ "superjson": "^2.2.1"
+ }
+ },
+ "node_modules/@vue/devtools-shared": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz",
+ "integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==",
+ "dev": true,
+ "dependencies": {
+ "rfdc": "^1.4.1"
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz",
+ "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
+ "dev": true,
+ "dependencies": {
+ "@vue/shared": "3.5.13"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
+ "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
+ "dev": true,
+ "dependencies": {
+ "@vue/reactivity": "3.5.13",
+ "@vue/shared": "3.5.13"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
+ "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
+ "dev": true,
+ "dependencies": {
+ "@vue/reactivity": "3.5.13",
+ "@vue/runtime-core": "3.5.13",
+ "@vue/shared": "3.5.13",
+ "csstype": "^3.1.3"
+ }
+ },
+ "node_modules/@vue/server-renderer": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
+ "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
+ "dev": true,
+ "dependencies": {
+ "@vue/compiler-ssr": "3.5.13",
+ "@vue/shared": "3.5.13"
+ },
+ "peerDependencies": {
+ "vue": "3.5.13"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz",
+ "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==",
+ "dev": true
+ },
+ "node_modules/@vueuse/core": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz",
+ "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/web-bluetooth": "^0.0.21",
+ "@vueuse/metadata": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/integrations": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz",
+ "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==",
+ "dev": true,
+ "dependencies": {
+ "@vueuse/core": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "async-validator": "^4",
+ "axios": "^1",
+ "change-case": "^5",
+ "drauu": "^0.4",
+ "focus-trap": "^7",
+ "fuse.js": "^7",
+ "idb-keyval": "^6",
+ "jwt-decode": "^4",
+ "nprogress": "^0.2",
+ "qrcode": "^1.5",
+ "sortablejs": "^1",
+ "universal-cookie": "^7"
+ },
+ "peerDependenciesMeta": {
+ "async-validator": {
+ "optional": true
+ },
+ "axios": {
+ "optional": true
+ },
+ "change-case": {
+ "optional": true
+ },
+ "drauu": {
+ "optional": true
+ },
+ "focus-trap": {
+ "optional": true
+ },
+ "fuse.js": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "jwt-decode": {
+ "optional": true
+ },
+ "nprogress": {
+ "optional": true
+ },
+ "qrcode": {
+ "optional": true
+ },
+ "sortablejs": {
+ "optional": true
+ },
+ "universal-cookie": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vueuse/metadata": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz",
+ "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/shared": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz",
+ "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==",
+ "dev": true,
+ "dependencies": {
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.14.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
+ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/algoliasearch": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.23.0.tgz",
+ "integrity": "sha512-7TCj+hLx6fZKppLL74lYGDEltSBNSu4vqRwgqeIKZ3VQ0q3aOrdEN0f1sDWcvU1b+psn2wnl7aHt9hWtYatUUA==",
+ "dev": true,
+ "dependencies": {
+ "@algolia/client-abtesting": "5.23.0",
+ "@algolia/client-analytics": "5.23.0",
+ "@algolia/client-common": "5.23.0",
+ "@algolia/client-insights": "5.23.0",
+ "@algolia/client-personalization": "5.23.0",
+ "@algolia/client-query-suggestions": "5.23.0",
+ "@algolia/client-search": "5.23.0",
+ "@algolia/ingestion": "1.23.0",
+ "@algolia/monitoring": "1.23.0",
+ "@algolia/recommend": "5.23.0",
+ "@algolia/requester-browser-xhr": "5.23.0",
+ "@algolia/requester-fetch": "5.23.0",
+ "@algolia/requester-node-http": "5.23.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/birpc": {
+ "version": "0.2.19",
+ "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.19.tgz",
+ "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "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/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/copy-anything": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
+ "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
+ "dev": true,
+ "dependencies": {
+ "is-what": "^4.1.8"
+ },
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/emoji-regex-xs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz",
+ "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==",
+ "dev": true
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
+ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.1",
+ "@humanwhocodes/config-array": "^0.13.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
+ "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
+ "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.28.0",
+ "prettier": ">=2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-roblox-ts": {
+ "version": "0.0.32",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-roblox-ts/-/eslint-plugin-roblox-ts-0.0.32.tgz",
+ "integrity": "sha512-zbwahPiQha5KGwY/J3pVXtyR4ORBSP8qouc4DGfnyGcdz0HOFFu+sACWX2u7/c4HVymtZlKRkTL4uR5qZ+THgg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "^16.10.4",
+ "@typescript-eslint/experimental-utils": "^5.0.0",
+ "typescript": "^4.4.4"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-roblox-ts/node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fast-uri": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
+ "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ]
+ },
+ "node_modules/fastq": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
+ "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true
+ },
+ "node_modules/focus-trap": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.4.tgz",
+ "integrity": "sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==",
+ "dev": true,
+ "dependencies": {
+ "tabbable": "^6.2.0"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "11.3.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
+ "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hast-util-to-html": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz",
+ "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==",
+ "dev": true,
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "stringify-entities": "^4.0.0",
+ "zwitch": "^2.0.4"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+ "dev": true,
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hookable": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
+ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
+ "dev": true
+ },
+ "node_modules/html-void-elements": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
+ "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-what": {
+ "version": "4.1.16",
+ "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
+ "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0"
+ }
+ },
+ "node_modules/mark.js": {
+ "version": "8.11.1",
+ "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz",
+ "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==",
+ "dev": true
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz",
+ "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==",
+ "dev": true,
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ]
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ]
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+ "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ]
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minisearch": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.1.2.tgz",
+ "integrity": "sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA==",
+ "dev": true
+ },
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "dev": true
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/oniguruma-to-es": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz",
+ "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex-xs": "^1.0.0",
+ "regex": "^6.0.1",
+ "regex-recursion": "^6.0.2"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/perfect-debounce": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+ "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
+ "dev": true
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.3",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
+ "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.8",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/preact": {
+ "version": "10.26.4",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.26.4.tgz",
+ "integrity": "sha512-KJhO7LBFTjP71d83trW+Ilnjbo+ySsaAgCfXOXUlmGzJ4ygYPWmysm77yg4emwfmoz3b22yvH5IsVFHbhUaH5w==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/property-information": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz",
+ "integrity": "sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz",
+ "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==",
+ "dev": true,
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-recursion": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz",
+ "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==",
+ "dev": true,
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-utilities": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz",
+ "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==",
+ "dev": true
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.10",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
+ "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.16.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "dev": true
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/roblox-ts": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/roblox-ts/-/roblox-ts-3.0.0.tgz",
+ "integrity": "sha512-hwAC2frIFlLJOtHd6F+5opMEhBgfAMK9z5l1mP+bykLBbMO5cn1q5lIwhhXbeh9Pq07rlhF8uGHlmeRLPd/3AA==",
+ "dev": true,
+ "dependencies": {
+ "@roblox-ts/luau-ast": "=2.0.0",
+ "@roblox-ts/path-translator": "=1.1.0",
+ "@roblox-ts/rojo-resolver": "=1.1.0",
+ "chokidar": "^3.6.0",
+ "fs-extra": "^11.2.0",
+ "kleur": "^4.1.5",
+ "resolve": "^1.22.6",
+ "typescript": "=5.5.3",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "rbxtsc": "out/CLI/cli.js"
+ }
+ },
+ "node_modules/roblox-ts/node_modules/typescript": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
+ "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz",
+ "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "1.0.6"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.37.0",
+ "@rollup/rollup-android-arm64": "4.37.0",
+ "@rollup/rollup-darwin-arm64": "4.37.0",
+ "@rollup/rollup-darwin-x64": "4.37.0",
+ "@rollup/rollup-freebsd-arm64": "4.37.0",
+ "@rollup/rollup-freebsd-x64": "4.37.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.37.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.37.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.37.0",
+ "@rollup/rollup-linux-arm64-musl": "4.37.0",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.37.0",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.37.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.37.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.37.0",
+ "@rollup/rollup-linux-x64-gnu": "4.37.0",
+ "@rollup/rollup-linux-x64-musl": "4.37.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.37.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.37.0",
+ "@rollup/rollup-win32-x64-msvc": "4.37.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/search-insights": {
+ "version": "2.17.3",
+ "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz",
+ "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shiki": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz",
+ "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==",
+ "dev": true,
+ "dependencies": {
+ "@shikijs/core": "2.5.0",
+ "@shikijs/engine-javascript": "2.5.0",
+ "@shikijs/engine-oniguruma": "2.5.0",
+ "@shikijs/langs": "2.5.0",
+ "@shikijs/themes": "2.5.0",
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/speakingurl": {
+ "version": "14.0.1",
+ "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
+ "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "dev": true,
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/superjson": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz",
+ "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
+ "dev": true,
+ "dependencies": {
+ "copy-anything": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
+ "dev": true
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.8.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
+ "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
+ "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
+ "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz",
+ "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz",
+ "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vitepress": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.3.tgz",
+ "integrity": "sha512-fCkfdOk8yRZT8GD9BFqusW3+GggWYZ/rYncOfmgcDtP3ualNHCAg+Robxp2/6xfH1WwPHtGpPwv7mbA3qomtBw==",
+ "dev": true,
+ "dependencies": {
+ "@docsearch/css": "3.8.2",
+ "@docsearch/js": "3.8.2",
+ "@iconify-json/simple-icons": "^1.2.21",
+ "@shikijs/core": "^2.1.0",
+ "@shikijs/transformers": "^2.1.0",
+ "@shikijs/types": "^2.1.0",
+ "@types/markdown-it": "^14.1.2",
+ "@vitejs/plugin-vue": "^5.2.1",
+ "@vue/devtools-api": "^7.7.0",
+ "@vue/shared": "^3.5.13",
+ "@vueuse/core": "^12.4.0",
+ "@vueuse/integrations": "^12.4.0",
+ "focus-trap": "^7.6.4",
+ "mark.js": "8.11.1",
+ "minisearch": "^7.1.1",
+ "shiki": "^2.1.0",
+ "vite": "^5.4.14",
+ "vue": "^3.5.13"
+ },
+ "bin": {
+ "vitepress": "bin/vitepress.js"
+ },
+ "peerDependencies": {
+ "markdown-it-mathjax3": "^4",
+ "postcss": "^8"
+ },
+ "peerDependenciesMeta": {
+ "markdown-it-mathjax3": {
+ "optional": true
+ },
+ "postcss": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitepress/node_modules/@types/node": {
+ "version": "22.13.13",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.13.tgz",
+ "integrity": "sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
+ "node_modules/vitepress/node_modules/@vitejs/plugin-vue": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.3.tgz",
+ "integrity": "sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg==",
+ "dev": true,
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^5.0.0 || ^6.0.0",
+ "vue": "^3.2.25"
+ }
+ },
+ "node_modules/vitepress/node_modules/vite": {
+ "version": "5.4.15",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.15.tgz",
+ "integrity": "sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz",
+ "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
+ "dev": true,
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.13",
+ "@vue/compiler-sfc": "3.5.13",
+ "@vue/runtime-dom": "3.5.13",
+ "@vue/server-renderer": "3.5.13",
+ "@vue/shared": "3.5.13"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ }
+}
diff --git a/rokit.toml b/rokit.toml
index 919ae66..0f38210 100644
--- a/rokit.toml
+++ b/rokit.toml
@@ -2,5 +2,4 @@
wally = "upliftgames/wally@0.3.2"
rojo = "rojo-rbx/rojo@7.4.4"
stylua = "johnnymorganz/stylua@2.0.1"
-selene = "kampfkarren/selene@0.27.1"
Blink = "1Axen/Blink@0.14.1"
diff --git a/selene.toml b/selene.toml
deleted file mode 100644
index 54227d9..0000000
--- a/selene.toml
+++ /dev/null
@@ -1,4 +0,0 @@
-std = "roblox"
-
-[lints]
-global_usage = "allow"
diff --git a/test/devtools_test.luau b/test/devtools_test.luau
index 2baa0c5..31ed1df 100644
--- a/test/devtools_test.luau
+++ b/test/devtools_test.luau
@@ -1,25 +1,25 @@
-local jecs = require("@jecs")
-local pair = jecs.pair
-local ChildOf = jecs.ChildOf
-local lifetime_tracker_add = require("@tools/lifetime_tracker")
-local pe = require("@tools/entity_visualiser").prettify
-local world = lifetime_tracker_add(jecs.world(), {padding_enabled=false})
-local FriendsWith = world:component()
-world:print_snapshot()
-local e1 = world:entity()
-local e2 = world:entity()
-world:delete(e2)
-
-world:print_snapshot()
-local e3 = world:entity()
-world:add(e3, pair(ChildOf, e1))
-local e4 = world:entity()
-world:add(e4, pair(FriendsWith, e3))
-world:print_snapshot()
-world:delete(e1)
-world:delete(e3)
-world:print_snapshot()
-world:print_entity_index()
-world:entity()
-world:entity()
-world:print_snapshot()
+local jecs = require("@jecs")
+local pair = jecs.pair
+local ChildOf = jecs.ChildOf
+local lifetime_tracker_add = require("@tools/lifetime_tracker")
+local pe = require("@tools/entity_visualiser").prettify
+local world = lifetime_tracker_add(jecs.world(), {padding_enabled=false})
+local FriendsWith = world:component()
+world:print_snapshot()
+local e1 = world:entity()
+local e2 = world:entity()
+world:delete(e2)
+
+world:print_snapshot()
+local e3 = world:entity()
+world:add(e3, pair(ChildOf, e1))
+local e4 = world:entity()
+world:add(e4, pair(FriendsWith, e3))
+world:print_snapshot()
+world:delete(e1)
+world:delete(e3)
+world:print_snapshot()
+world:print_entity_index()
+world:entity()
+world:entity()
+world:print_snapshot()
diff --git a/test/examples/README.md b/test/examples/README.md
deleted file mode 100644
index 68b04aa..0000000
--- a/test/examples/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Examples
-
-This folder contains code examples for the Luau/Typescript APIs.
-
-## Run with Luau
-To run the examples with Luau, run the following commands from the root of the repository:
-
-```sh
-cd examples/luau
-luau path/to/file.luau
-```
diff --git a/test/examples/luau/entities/basics.luau b/test/examples/luau/entities/basics.luau
deleted file mode 100644
index 170431e..0000000
--- a/test/examples/luau/entities/basics.luau
+++ /dev/null
@@ -1,43 +0,0 @@
-local jecs = require("@jecs")
-local world = jecs.World.new()
-
-local Position = world:component()
-local Walking = world:component()
-local Name = world:component()
-
--- Create an entity with name Bob
-local bob = world:entity()
-
--- The set operation finds or creates a component, and sets it.
-world:set(bob, Position, Vector3.new(10, 20, 30))
--- Name the entity Bob
-world:set(bob, Name, "Bob")
--- The add operation adds a component without setting a value. This is
--- useful for tags, or when adding a component with its default value.
-world:add(bob, Walking)
-
--- Get the value for the Position component
-local pos = world:get(bob, Position)
-print(`\{{pos.X}, {pos.Y}, {pos.Z}\}`)
-
--- Overwrite the value of the Position component
-world:set(bob, Position, Vector3.new(40, 50, 60))
-
-local alice = world:entity()
--- Create another named entity
-world:set(alice, Name, "Alice")
-world:set(alice, Position, Vector3.new(10, 20, 30))
-world:add(alice, Walking)
-
--- Remove tag
-world:remove(alice, Walking)
-
--- Iterate all entities with Position
-for entity, p in world:query(Position) do
- print(`{entity}: \{{p.X}, {p.Y}, {p.Z}\}`)
-end
-
--- Output:
--- {10, 20, 30}
--- Alice: {10, 20, 30}
--- Bob: {40, 50, 60}
diff --git a/test/examples/luau/entities/hierarchy.luau b/test/examples/luau/entities/hierarchy.luau
deleted file mode 100644
index 40e3727..0000000
--- a/test/examples/luau/entities/hierarchy.luau
+++ /dev/null
@@ -1,112 +0,0 @@
-local jecs = require("@jecs")
-local pair = jecs.pair
-local ChildOf = jecs.ChildOf
-local world = jecs.World.new()
-
-local Name = world:component()
-local Position = world:component()
-local Star = world:component()
-local Planet = world:component()
-local Moon = world:component()
-
-local Vector3
-do
- Vector3 = {}
- Vector3.__index = Vector3
-
- function Vector3.new(x, y, z)
- x = x or 0
- y = y or 0
- z = z or 0
- return setmetatable({ X = x, Y = y, Z = z }, Vector3)
- end
-
- function Vector3.__add(left, right)
- return Vector3.new(left.X + right.X, left.Y + right.Y, left.Z + right.Z)
- end
-
- function Vector3.__mul(left, right)
- if typeof(right) == "number" then
- return Vector3.new(left.X * right, left.Y * right, left.Z * right)
- end
- return Vector3.new(left.X * right.X, left.Y * right.Y, left.Z * right.Z)
- end
-
- Vector3.one = Vector3.new(1, 1, 1)
- Vector3.zero = Vector3.new()
-end
-
-local function path(entity)
- local str = world:get(entity, Name)
- local parent
- while true do
- parent = world:parent(entity)
- if not parent then
- break
- end
- entity = parent
- str = world:get(parent, Name) .. "/" .. str
- end
- return str
-end
-
-local function iterate(entity, parent)
- local p = world:get(entity, Position)
- local actual = p + parent
- print(path(entity))
- print(`\{{actual.X}, {actual.Y}, {actual.Z}}`)
-
- for child in world:query(pair(ChildOf, entity)) do
- --print(world:get(child, Name))
- iterate(child, actual)
- end
-end
-
-local sun = world:entity()
-world:add(sun, Star)
-world:set(sun, Position, Vector3.one)
-world:set(sun, Name, "Sun")
-do
- local earth = world:entity()
- world:set(earth, Name, "Earth")
- world:add(earth, pair(ChildOf, sun))
- world:add(earth, Planet)
- world:set(earth, Position, Vector3.one * 3)
-
- do
- local moon = world:entity()
- world:set(moon, Name, "Moon")
- world:add(moon, pair(ChildOf, earth))
- world:add(moon, Moon)
- world:set(moon, Position, Vector3.one * 0.1)
-
- print(`Child of Earth? {world:has(moon, pair(ChildOf, earth))}`)
- end
-
- local venus = world:entity()
- world:set(venus, Name, "Venus")
- world:add(venus, pair(ChildOf, sun))
- world:add(venus, Planet)
- world:set(venus, Position, Vector3.one * 2)
-
- local mercury = world:entity()
- world:set(mercury, Name, "Mercury")
- world:add(mercury, pair(ChildOf, sun))
- world:add(mercury, Planet)
- world:set(mercury, Position, Vector3.one)
-
- iterate(sun, Vector3.zero)
-end
-
--- Output:
--- Child of Earth? true
--- Sun
--- {1, 1, 1}
--- Sun/Mercury
--- {2, 2, 2}
--- Sun/Venus
--- {3, 3, 3}
--- Sun/Earth
--- {4, 4, 4}
--- Sun/Earth/Moon
--- {4.1, 4.1, 4.1}
diff --git a/test/examples/luau/hooks/cleanup.luau b/test/examples/luau/hooks/cleanup.luau
deleted file mode 100644
index 9088ad2..0000000
--- a/test/examples/luau/hooks/cleanup.luau
+++ /dev/null
@@ -1,21 +0,0 @@
-local jecs = require("@jecs")
-local world = jecs.World.new()
-
-local Model = world:component()
-
--- It is important to define hooks for the component before the component is ever used
--- otherwise the hooks will never invoke!
-world:set(Model, jecs.OnRemove, function(entity)
- -- OnRemove is invoked before the component and its value is removed
- -- which provides a stable reference to the entity at deletion.
- -- This means that it is safe to retrieve the data inside of a hook
- local model = world:get(entity, Model)
- model:Destroy()
-end)
-
-world:set(Model, jecs.OnSet, function(entity, model)
- -- OnSet is invoked after the data has been assigned.
- -- It also returns the data for faster access.
- -- There may be some logic to do some side effects on reassignments
- model:SetAttribute("entityId", entity)
-end)
diff --git a/test/examples/luau/queries/basics.luau b/test/examples/luau/queries/basics.luau
deleted file mode 100644
index 21e7cae..0000000
--- a/test/examples/luau/queries/basics.luau
+++ /dev/null
@@ -1,63 +0,0 @@
-local jecs = require("@jecs")
-local world = jecs.World.new()
-
-local Position = world:component()
-local Velocity = world:component()
-local Name = world:component()
-
-local Vector3
-do
- Vector3 = {}
- Vector3.__index = Vector3
-
- function Vector3.new(x, y, z)
- x = x or 0
- y = y or 0
- z = z or 0
- return setmetatable({ X = x, Y = y, Z = z }, Vector3)
- end
-
- function Vector3.__add(left, right)
- return Vector3.new(left.X + right.X, left.Y + right.Y, left.Z + right.Z)
- end
-
- function Vector3.__mul(left, right)
- if typeof(right) == "number" then
- return Vector3.new(left.X * right, left.Y * right, left.Z * right)
- end
- return Vector3.new(left.X * right.X, left.Y * right.Y, left.Z * right.Z)
- end
-
- Vector3.one = Vector3.new(1, 1, 1)
- Vector3.zero = Vector3.new()
-end
-
--- Create a few test entities for a Position, Velocity query
-local e1 = world:entity()
-world:set(e1, Name, "e1")
-world:set(e1, Position, Vector3.new(10, 20, 30))
-world:set(e1, Velocity, Vector3.new(1, 2, 3))
-
-local e2 = world:entity()
-world:set(e2, Name, "e2")
-world:set(e2, Position, Vector3.new(10, 20, 30))
-world:set(e2, Velocity, Vector3.new(4, 5, 6))
-
--- This entity will not match as it does not have Position, Velocity
-local e3 = world:entity()
-world:set(e3, Name, "e3")
-world:set(e3, Position, Vector3.new(10, 20, 30))
-
--- Create an uncached query for Position, Velocity.
-for entity, p, v in world:query(Position, Velocity) do
- -- Iterate entities matching the query
- p.X += v.X
- p.Y += v.Y
- p.Z += v.Z
-
- print(`{world:get(entity, Name)}: \{{p.X}, {p.Y}, {p.Z}}`)
-end
-
--- Output:
--- e2: {14, 25, 36}
--- e1: {11, 22, 33}
diff --git a/test/examples/luau/queries/changetracking.luau b/test/examples/luau/queries/changetracking.luau
deleted file mode 100644
index bcaa032..0000000
--- a/test/examples/luau/queries/changetracking.luau
+++ /dev/null
@@ -1,61 +0,0 @@
-local jecs = require("@jecs")
-
-local world = jecs.World.new()
-local Name = world:component()
-
-local function named(ctr, name)
- local e = ctr(world)
- world:set(e, Name, name)
- return e
-end
-local function name(e)
- return world:get(e, Name)
-end
-
-local Position = named(world.component, "Position") :: jecs.Entity
-local Previous = jecs.Rest
-local PreviousPosition = jecs.pair(Previous, Position)
-
-local added = world
- :query(Position)
- :without(PreviousPosition)
- :cached()
-local changed = world
- :query(Position, PreviousPosition)
- :cached()
-local removed = world
- :query(PreviousPosition)
- :without(Position)
- :cached()
-
-local e1 = named(world.entity, "e1")
-world:set(e1, Position, Vector3.new(10, 20, 30))
-
-local e2 = named(world.entity, "e2")
-world:set(e2, Position, Vector3.new(10, 20, 30))
-
-for e, p in added:iter() do
- print(`Added {e}: \{{p.X}, {p.Y}, {p.Z}}`)
- world:set(e, PreviousPosition, p)
-end
-
-world:set(e1, Position, "")
-
-for e, new, old in changed:iter() do
- if new ~= old then
- print(`{name(new)}'s Position changed from \{{old.X}, {old.Y}, {old.Z}\} to \{{new.X}, {new.Y}, {new.Z}\}`)
- world:set(e, PreviousPosition, new)
- end
-end
-
-world:remove(e2, Position)
-
-for e in removed:iter() do
- print(`Position was removed from {name(e)}`)
-end
-
--- Output:
--- Added 265: {10, 20, 30}
--- Added 264: {10, 20, 30}
--- e1's Position changed from {10, 20, 30} to {999, 999, 1998}
--- Position was removed from e2
diff --git a/test/examples/luau/queries/spatial_grids.luau b/test/examples/luau/queries/spatial_grids.luau
deleted file mode 100644
index 6dcf72f..0000000
--- a/test/examples/luau/queries/spatial_grids.luau
+++ /dev/null
@@ -1,125 +0,0 @@
-local jecs = require("@jecs")
-local pair = jecs.pair
-local ChildOf = jecs.ChildOf
-local __ = jecs.Wildcard
-local Name = jecs.Name
-local world = jecs.World.new()
-
-type Id = number & { __T: T }
-local Voxel = world:component() :: Id
-local Position = world:component() :: Id
-local Perception = world:component() :: Id<{
- range: number,
- fov: number,
- dir: Vector3,
-}>
-local PrimaryPart = world:component() :: Id
-
-local local_player = game:GetService("Players").LocalPlayer
-
-local function distance(a: Vector3, b: Vector3)
- return (b - a).Magnitude
-end
-
-local function is_in_fov(a: Vector3, b: Vector3, forward_dir: Vector3, fov_angle: number)
- local to_target = b - a
-
- local forward_xz = Vector3.new(forward_dir.X, 0, forward_dir.Z).Unit
- local to_target_xz = Vector3.new(to_target.X, 0, to_target.Z).Unit
-
- local angle_to_target = math.deg(math.atan2(to_target_xz.Z, to_target_xz.X))
- local forward_angle = math.deg(math.atan2(forward_xz.Z, forward_xz.X))
-
- local angle_difference = math.abs(forward_angle - angle_to_target)
-
- if angle_difference > 180 then
- angle_difference = 360 - angle_difference
- end
-
- return angle_difference <= (fov_angle / 2)
-end
-
-local map = {}
-local grid = 50
-
-local function add_to_voxel(source: number, position: Vector3, prev_voxel_id: number?)
- local hash = position // grid
- local voxel_id = map[hash]
- if not voxel_id then
- voxel_id = world:entity()
- world:add(voxel_id, Voxel)
- world:set(voxel_id, Position, hash)
- map[hash] = voxel_id
- end
- if prev_voxel_id ~= nil then
- world:remove(source, pair(ChildOf, prev_voxel_id))
- end
- world:add(source, pair(ChildOf, voxel_id))
-end
-
-local function reconcile_client_owned_assembly_to_voxel(dt: number)
- for e, part, position in world:query(PrimaryPart, Position) do
- local p = part.Position
- if p ~= position then
- world:set(e, Position, p)
- local voxel_id = world:target(e, ChildOf, 0)
- if map[p // grid] == voxel_id then
- continue
- end
-
- add_to_voxel(e, p, voxel_id)
- end
- end
-end
-
-local function update_camera_direction(dt: number)
- for _, perception in world:query(Perception) do
- perception.dir = workspace.CurrentCamera.CFrame.LookVector
- end
-end
-
-local function perceive_enemies(dt: number)
- local it = world:query(Perception, Position, PrimaryPart)
- -- There is only going to be one entity matching the query
- local e, self_perception, self_position, self_primary_part = it()
-
- local voxel_id = map[self_primary_part.Position // grid]
- local nearby_entities_query = world:query(Position, pair(ChildOf, voxel_id))
-
- for enemy, target_position in nearby_entities_query do
- if distance(self_position, target_position) > self_perception.range then
- continue
- end
-
- if is_in_fov(self_position, target_position, self_perception.dir, self_perception.fov) then
- local p = target_position
- print(`Entity {world:get(e, Name)} can see target {world:get(enemy, Name)} at ({p.X}, {p.Y}, {p.Z})`)
- end
- end
-end
-
-local player = world:entity()
-world:set(player, Perception, {
- range = 100,
- fov = 90,
- dir = Vector3.new(1, 0, 0),
-})
-world:set(player, Name, "LocalPlayer")
-local primary_part = (local_player.Character :: Model).PrimaryPart :: Part
-world:set(player, PrimaryPart, primary_part)
-world:set(player, Position, Vector3.zero)
-
-local enemy = world:entity()
-world:set(enemy, Name, "Enemy $1")
-world:set(enemy, Position, Vector3.new(50, 0, 20))
-
-add_to_voxel(player, primary_part.Position)
-add_to_voxel(enemy, world)
-
-local dt = 1 / 60
-reconcile_client_owned_assembly_to_voxel(dt)
-update_camera_direction(dt)
-perceive_enemies(dt)
-
--- Output:
--- LocalPlayer can see target Enemy $1
diff --git a/test/examples/luau/queries/wildcards.luau b/test/examples/luau/queries/wildcards.luau
deleted file mode 100644
index 5d33e3d..0000000
--- a/test/examples/luau/queries/wildcards.luau
+++ /dev/null
@@ -1,37 +0,0 @@
-local jecs = require("@jecs")
-local pair = jecs.pair
-local world = jecs.World.new()
-local Name = world:component()
-
-local function named(ctr, name)
- local e = ctr(world)
- world:set(e, Name, name)
- return e
-end
-local function name(e)
- return world:get(e, Name)
-end
-
-local Eats = world:component()
-local Apples = named(world.entity, "Apples")
-local Oranges = named(world.entity, "Oranges")
-
-local bob = named(world.entity, "Bob")
-world:set(bob, pair(Eats, Apples), 10)
-
-local alice = named(world.entity, "Alice")
-world:set(alice, pair(Eats, Oranges), 5)
-
--- Aliasing the wildcard to symbols improves readability and ease of writing
-local __ = jecs.Wildcard
-
--- Create a query that matches edible components
-for entity, amount in world:query(pair(Eats, __)) do
- -- Iterate the query
- local food = world:target(entity, Eats)
- print(`{name(entity)} eats {amount} {name(food)}`)
-end
-
--- Output:
--- Alice eats 5 Oranges
--- Bob eats 10 Apples
diff --git a/test/lol.luau b/test/lol.luau
index 0be2c57..0749543 100644
--- a/test/lol.luau
+++ b/test/lol.luau
@@ -1,158 +1,158 @@
-local c = {
- white_underline = function(s: any)
- return `\27[1;4m{s}\27[0m`
- end,
-
- white = function(s: any)
- return `\27[37;1m{s}\27[0m`
- end,
-
- green = function(s: any)
- return `\27[32;1m{s}\27[0m`
- end,
-
- red = function(s: any)
- return `\27[31;1m{s}\27[0m`
- end,
-
- yellow = function(s: any)
- return `\27[33;1m{s}\27[0m`
- end,
-
- red_highlight = function(s: any)
- return `\27[41;1;30m{s}\27[0m`
- end,
-
- green_highlight = function(s: any)
- return `\27[42;1;30m{s}\27[0m`
- end,
-
- gray = function(s: any)
- return `\27[30;1m{s}\27[0m`
- end,
-}
-
-
-local ECS_PAIR_FLAG = 0x8
-local ECS_ID_FLAGS_MASK = 0x10
-local ECS_ENTITY_MASK = bit32.lshift(1, 24)
-local ECS_GENERATION_MASK = bit32.lshift(1, 16)
-
-type i53 = number
-type i24 = number
-
-local function ECS_ENTITY_T_LO(e: i53): i24
- return if e > ECS_ENTITY_MASK then (e // ECS_ID_FLAGS_MASK) // ECS_ENTITY_MASK else e
-end
-
-local function ECS_GENERATION(e: i53): i24
- return if e > ECS_ENTITY_MASK then (e // ECS_ID_FLAGS_MASK) % ECS_GENERATION_MASK else 0
-end
-
-local ECS_ID = ECS_ENTITY_T_LO
-
-local function ECS_COMBINE(source: number, target: number): i53
- return (source * 268435456) + (target * ECS_ID_FLAGS_MASK)
-end
-
-local function ECS_GENERATION_INC(e: i53)
- if e > ECS_ENTITY_MASK then
- local flags = e // ECS_ID_FLAGS_MASK
- local id = flags // ECS_ENTITY_MASK
- local generation = flags % ECS_GENERATION_MASK
-
- local next_gen = generation + 1
- if next_gen > ECS_GENERATION_MASK then
- return id
- end
-
- return ECS_COMBINE(id, next_gen) + flags
- end
- return ECS_COMBINE(e, 1)
-end
-
-local function bl()
- print("")
-end
-
-local function pe(e)
- local gen = ECS_GENERATION(e)
- return c.green(`e{ECS_ID(e)}`)..c.yellow(`v{gen}`)
-end
-
-local function dprint(tbl: { [number]: number })
- bl()
- print("--------")
- for i, e in tbl do
- print("| "..pe(e).." |")
- print("--------")
- end
- bl()
-end
-
-local max_id = 0
-local alive_count = 0
-local dense = {}
-local sparse = {}
-local function alloc()
- if alive_count ~= #dense then
- alive_count += 1
- print("*recycled", pe(dense[alive_count]))
- return dense[alive_count]
- end
- max_id += 1
- local id = max_id
- alive_count += 1
- dense[alive_count] = id
- sparse[id] = {
- dense = alive_count
- }
- print("*allocated", pe(id))
- return id
-end
-
-local function remove(entity)
- local id = ECS_ID(entity)
- local r = sparse[id]
- local index_of_deleted_entity = r.dense
- local last_entity_alive_at_index = alive_count -- last entity alive
- alive_count -= 1
- local last_alive_entity = dense[last_entity_alive_at_index]
- local r_swap = sparse[ECS_ID(last_alive_entity)]
- r_swap.dense = r.dense
- r.dense = last_entity_alive_at_index
- dense[index_of_deleted_entity] = last_alive_entity
- dense[last_entity_alive_at_index] = ECS_GENERATION_INC(entity)
- print("*dellocated", pe(id))
-end
-
-local function alive(e)
- local r = sparse[ECS_ID(e)]
-
- return dense[r.dense] == e
-end
-
-local function pa(e)
- print(`{pe(e)} is {if alive(e) then "alive" else "not alive"}`)
-end
-
-local tprint = require("@testkit").print
-local e1v0 = alloc()
-local e2v0 = alloc()
-local e3v0 = alloc()
-local e4v0 = alloc()
-local e5v0 = alloc()
-pa(e1v0)
-pa(e4v0)
-remove(e5v0)
-pa(e5v0)
-
-local e5v1 = alloc()
-pa(e5v0)
-pa(e5v1)
-pa(e2v0)
-print(ECS_ID(e2v0))
-
-dprint(dense)
-remove(e2v0)
-dprint(dense)
+local c = {
+ white_underline = function(s: any)
+ return `\27[1;4m{s}\27[0m`
+ end,
+
+ white = function(s: any)
+ return `\27[37;1m{s}\27[0m`
+ end,
+
+ green = function(s: any)
+ return `\27[32;1m{s}\27[0m`
+ end,
+
+ red = function(s: any)
+ return `\27[31;1m{s}\27[0m`
+ end,
+
+ yellow = function(s: any)
+ return `\27[33;1m{s}\27[0m`
+ end,
+
+ red_highlight = function(s: any)
+ return `\27[41;1;30m{s}\27[0m`
+ end,
+
+ green_highlight = function(s: any)
+ return `\27[42;1;30m{s}\27[0m`
+ end,
+
+ gray = function(s: any)
+ return `\27[30;1m{s}\27[0m`
+ end,
+}
+
+
+local ECS_PAIR_FLAG = 0x8
+local ECS_ID_FLAGS_MASK = 0x10
+local ECS_ENTITY_MASK = bit32.lshift(1, 24)
+local ECS_GENERATION_MASK = bit32.lshift(1, 16)
+
+type i53 = number
+type i24 = number
+
+local function ECS_ENTITY_T_LO(e: i53): i24
+ return if e > ECS_ENTITY_MASK then (e // ECS_ID_FLAGS_MASK) // ECS_ENTITY_MASK else e
+end
+
+local function ECS_GENERATION(e: i53): i24
+ return if e > ECS_ENTITY_MASK then (e // ECS_ID_FLAGS_MASK) % ECS_GENERATION_MASK else 0
+end
+
+local ECS_ID = ECS_ENTITY_T_LO
+
+local function ECS_COMBINE(source: number, target: number): i53
+ return (source * 268435456) + (target * ECS_ID_FLAGS_MASK)
+end
+
+local function ECS_GENERATION_INC(e: i53)
+ if e > ECS_ENTITY_MASK then
+ local flags = e // ECS_ID_FLAGS_MASK
+ local id = flags // ECS_ENTITY_MASK
+ local generation = flags % ECS_GENERATION_MASK
+
+ local next_gen = generation + 1
+ if next_gen > ECS_GENERATION_MASK then
+ return id
+ end
+
+ return ECS_COMBINE(id, next_gen) + flags
+ end
+ return ECS_COMBINE(e, 1)
+end
+
+local function bl()
+ print("")
+end
+
+local function pe(e)
+ local gen = ECS_GENERATION(e)
+ return c.green(`e{ECS_ID(e)}`)..c.yellow(`v{gen}`)
+end
+
+local function dprint(tbl: { [number]: number })
+ bl()
+ print("--------")
+ for i, e in tbl do
+ print("| "..pe(e).." |")
+ print("--------")
+ end
+ bl()
+end
+
+local max_id = 0
+local alive_count = 0
+local dense = {}
+local sparse = {}
+local function alloc()
+ if alive_count ~= #dense then
+ alive_count += 1
+ print("*recycled", pe(dense[alive_count]))
+ return dense[alive_count]
+ end
+ max_id += 1
+ local id = max_id
+ alive_count += 1
+ dense[alive_count] = id
+ sparse[id] = {
+ dense = alive_count
+ }
+ print("*allocated", pe(id))
+ return id
+end
+
+local function remove(entity)
+ local id = ECS_ID(entity)
+ local r = sparse[id]
+ local index_of_deleted_entity = r.dense
+ local last_entity_alive_at_index = alive_count -- last entity alive
+ alive_count -= 1
+ local last_alive_entity = dense[last_entity_alive_at_index]
+ local r_swap = sparse[ECS_ID(last_alive_entity)]
+ r_swap.dense = r.dense
+ r.dense = last_entity_alive_at_index
+ dense[index_of_deleted_entity] = last_alive_entity
+ dense[last_entity_alive_at_index] = ECS_GENERATION_INC(entity)
+ print("*dellocated", pe(id))
+end
+
+local function alive(e)
+ local r = sparse[ECS_ID(e)]
+
+ return dense[r.dense] == e
+end
+
+local function pa(e)
+ print(`{pe(e)} is {if alive(e) then "alive" else "not alive"}`)
+end
+
+local tprint = require("@testkit").print
+local e1v0 = alloc()
+local e2v0 = alloc()
+local e3v0 = alloc()
+local e4v0 = alloc()
+local e5v0 = alloc()
+pa(e1v0)
+pa(e4v0)
+remove(e5v0)
+pa(e5v0)
+
+local e5v1 = alloc()
+pa(e5v0)
+pa(e5v1)
+pa(e2v0)
+print(ECS_ID(e2v0))
+
+dprint(dense)
+remove(e2v0)
+dprint(dense)
diff --git a/test/stress.client.luau b/test/stress.client.luau
index 13b5e86..9bc7775 100644
--- a/test/stress.client.luau
+++ b/test/stress.client.luau
@@ -1,122 +1,122 @@
-local RunService = game:GetService("RunService")
-local ReplicatedStorage = game:GetService("ReplicatedStorage")
-_G.__JECS_HI_COMPONENT_ID = 300
-local ecs = require(ReplicatedStorage.ecs)
-
--- 500 entities
--- 2-30 components on each entity
--- 300 unique components
--- 200 systems
--- 1-10 components to query per system
-
-local startTime = os.clock()
-
-local world = ecs.World.new()
-
-local components = {}
-
-for i = 1, 300 do -- 300 components
- components[i] = world:component()
-end
-
-local archetypes = {}
-for i = 1, 50 do -- 50 archetypes
- local archetype = {}
-
- for _ = 1, math.random(2, 30) do
- local componentId = math.random(1, #components)
-
- table.insert(archetype, components[componentId])
- end
-
- archetypes[i] = archetype
-end
-
-for _ = 1, 1000 do -- 1000 entities in the world
- local componentsToAdd = {}
-
- local archetypeId = math.random(1, #archetypes)
- local e = world:entity()
- for _, component in ipairs(archetypes[archetypeId]) do
- world:set(e, component, {
- DummyData = math.random(1, 5000),
- })
- end
-end
-
-local function values(t)
- local array = {}
- for _, v in t do
- table.insert(array, v)
- end
- return array
-end
-
-local contiguousComponents = values(components)
-local systemComponentsToQuery = {}
-
-for _ = 1, 200 do -- 200 systems
- local numComponentsToQuery = math.random(1, 10)
- local componentsToQuery = {}
-
- for _ = 1, numComponentsToQuery do
- table.insert(componentsToQuery, contiguousComponents[math.random(1, #contiguousComponents)])
- end
-
- table.insert(systemComponentsToQuery, componentsToQuery)
-end
-
-local worldCreateTime = os.clock() - startTime
-local results = {}
-startTime = os.clock()
-
-RunService.Heartbeat:Connect(function()
- local added = 0
- local systemStartTime = os.clock()
- debug.profilebegin("systems")
- for _, componentsToQuery in ipairs(systemComponentsToQuery) do
- debug.profilebegin("system")
- for entityId, firstComponent in world:query(unpack(componentsToQuery)) do
- world:set(
- entityId,
- {
- DummyData = firstComponent.DummyData + 1,
- }
- )
- added += 1
- end
- debug.profileend()
- end
- debug.profileend()
-
- if os.clock() - startTime < 4 then
- -- discard first 4 seconds
- return
- end
-
- if results == nil then
- return
- elseif #results < 1000 then
- table.insert(results, os.clock() - systemStartTime)
- else
- print("added", added)
- print("World created in", worldCreateTime * 1000, "ms")
- local sum = 0
- for _, result in ipairs(results) do
- sum += result
- end
- print(("Average frame time: %fms"):format((sum / #results) * 1000))
-
- results = nil
-
- local n = #world.archetypes
-
- print(
- ("X entities\n%d components\n%d systems\n%d archetypes"):format(
- #components,
- #systemComponentsToQuery,
- n
- )
- )
- end
-end)
+local RunService = game:GetService("RunService")
+local ReplicatedStorage = game:GetService("ReplicatedStorage")
+_G.__JECS_HI_COMPONENT_ID = 300
+local ecs = require(ReplicatedStorage.ecs)
+
+-- 500 entities
+-- 2-30 components on each entity
+-- 300 unique components
+-- 200 systems
+-- 1-10 components to query per system
+
+local startTime = os.clock()
+
+local world = ecs.World.new()
+
+local components = {}
+
+for i = 1, 300 do -- 300 components
+ components[i] = world:component()
+end
+
+local archetypes = {}
+for i = 1, 50 do -- 50 archetypes
+ local archetype = {}
+
+ for _ = 1, math.random(2, 30) do
+ local componentId = math.random(1, #components)
+
+ table.insert(archetype, components[componentId])
+ end
+
+ archetypes[i] = archetype
+end
+
+for _ = 1, 1000 do -- 1000 entities in the world
+ local componentsToAdd = {}
+
+ local archetypeId = math.random(1, #archetypes)
+ local e = world:entity()
+ for _, component in ipairs(archetypes[archetypeId]) do
+ world:set(e, component, {
+ DummyData = math.random(1, 5000),
+ })
+ end
+end
+
+local function values(t)
+ local array = {}
+ for _, v in t do
+ table.insert(array, v)
+ end
+ return array
+end
+
+local contiguousComponents = values(components)
+local systemComponentsToQuery = {}
+
+for _ = 1, 200 do -- 200 systems
+ local numComponentsToQuery = math.random(1, 10)
+ local componentsToQuery = {}
+
+ for _ = 1, numComponentsToQuery do
+ table.insert(componentsToQuery, contiguousComponents[math.random(1, #contiguousComponents)])
+ end
+
+ table.insert(systemComponentsToQuery, componentsToQuery)
+end
+
+local worldCreateTime = os.clock() - startTime
+local results = {}
+startTime = os.clock()
+
+RunService.Heartbeat:Connect(function()
+ local added = 0
+ local systemStartTime = os.clock()
+ debug.profilebegin("systems")
+ for _, componentsToQuery in ipairs(systemComponentsToQuery) do
+ debug.profilebegin("system")
+ for entityId, firstComponent in world:query(unpack(componentsToQuery)) do
+ world:set(
+ entityId,
+ {
+ DummyData = firstComponent.DummyData + 1,
+ }
+ )
+ added += 1
+ end
+ debug.profileend()
+ end
+ debug.profileend()
+
+ if os.clock() - startTime < 4 then
+ -- discard first 4 seconds
+ return
+ end
+
+ if results == nil then
+ return
+ elseif #results < 1000 then
+ table.insert(results, os.clock() - systemStartTime)
+ else
+ print("added", added)
+ print("World created in", worldCreateTime * 1000, "ms")
+ local sum = 0
+ for _, result in ipairs(results) do
+ sum += result
+ end
+ print(("Average frame time: %fms"):format((sum / #results) * 1000))
+
+ results = nil
+
+ local n = #world.archetypes
+
+ print(
+ ("X entities\n%d components\n%d systems\n%d archetypes"):format(
+ #components,
+ #systemComponentsToQuery,
+ n
+ )
+ )
+ end
+end)
diff --git a/stress.project.json b/test/stress.project.json
similarity index 100%
rename from stress.project.json
rename to test/stress.project.json
diff --git a/test/thesis/images/archetype_graph.png b/test/thesis/images/archetype_graph.png
deleted file mode 100644
index 140def3..0000000
Binary files a/test/thesis/images/archetype_graph.png and /dev/null differ
diff --git a/test/thesis/images/chrome_IdcpbCveiD.png b/test/thesis/images/chrome_IdcpbCveiD.png
deleted file mode 100644
index 0bf4848..0000000
Binary files a/test/thesis/images/chrome_IdcpbCveiD.png and /dev/null differ
diff --git a/test/thesis/images/chrome_f5DTavXIka.png b/test/thesis/images/chrome_f5DTavXIka.png
deleted file mode 100644
index 935489f..0000000
Binary files a/test/thesis/images/chrome_f5DTavXIka.png and /dev/null differ
diff --git a/test/thesis/images/chrome_giChmd5W4Z.png b/test/thesis/images/chrome_giChmd5W4Z.png
deleted file mode 100644
index 254871b..0000000
Binary files a/test/thesis/images/chrome_giChmd5W4Z.png and /dev/null differ
diff --git a/test/thesis/images/insertion.png b/test/thesis/images/insertion.png
deleted file mode 100644
index f6facf6..0000000
Binary files a/test/thesis/images/insertion.png and /dev/null differ
diff --git a/test/thesis/images/queries.png b/test/thesis/images/queries.png
deleted file mode 100644
index a511784..0000000
Binary files a/test/thesis/images/queries.png and /dev/null differ
diff --git a/test/thesis/images/random_access.png b/test/thesis/images/random_access.png
deleted file mode 100644
index 6b122af..0000000
Binary files a/test/thesis/images/random_access.png and /dev/null differ
diff --git a/test/thesis/images/removed.png b/test/thesis/images/removed.png
deleted file mode 100644
index 03cc9b6..0000000
Binary files a/test/thesis/images/removed.png and /dev/null differ
diff --git a/test/thesis/images/sparseset.png b/test/thesis/images/sparseset.png
deleted file mode 100644
index 0cdea79..0000000
Binary files a/test/thesis/images/sparseset.png and /dev/null differ
diff --git a/testez.d.luau b/testez.d.luau
deleted file mode 100644
index 349ea08..0000000
--- a/testez.d.luau
+++ /dev/null
@@ -1,24 +0,0 @@
-declare function afterAll(callback: () -> ()): ()
-declare function afterEach(callback: () -> ()): ()
-
-declare function beforeAll(callback: () -> ()): ()
-declare function beforeEach(callback: () -> ()): ()
-
-declare function describe(phrase: string, callback: () -> ()): ()
-declare function describeFOCUS(phrase: string, callback: () -> ()): ()
-declare function fdescribe(phrase: string, callback: () -> ()): ()
-declare function describeSKIP(phrase: string, callback: () -> ()): ()
-declare function xdescribe(phrase: string, callback: () -> ()): ()
-
-declare function expect(value: any): any
-
-declare function FIXME(optionalMessage: string?): ()
-declare function FOCUS(): ()
-declare function SKIP(): ()
-
-declare function it(phrase: string, callback: () -> ()): ()
-declare function itFOCUS(phrase: string, callback: () -> ()): ()
-declare function fit(phrase: string, callback: () -> ()): ()
-declare function itSKIP(phrase: string, callback: () -> ()): ()
-declare function xit(phrase: string, callback: () -> ()): ()
-declare function itFIXME(phrase: string, callback: () -> ()): ()
\ No newline at end of file
diff --git a/tools/ansi.luau b/tools/ansi.luau
index e4da53c..a391f8e 100644
--- a/tools/ansi.luau
+++ b/tools/ansi.luau
@@ -1,33 +1,33 @@
-return {
- white_underline = function(s: any)
- return `\27[1;4m{s}\27[0m`
- end,
-
- white = function(s: any)
- return `\27[37;1m{s}\27[0m`
- end,
-
- green = function(s: any)
- return `\27[32;1m{s}\27[0m`
- end,
-
- red = function(s: any)
- return `\27[31;1m{s}\27[0m`
- end,
-
- yellow = function(s: any)
- return `\27[33;1m{s}\27[0m`
- end,
-
- red_highlight = function(s: any)
- return `\27[41;1;30m{s}\27[0m`
- end,
-
- green_highlight = function(s: any)
- return `\27[42;1;30m{s}\27[0m`
- end,
-
- gray = function(s: any)
- return `\27[30;1m{s}\27[0m`
- end,
-}
+return {
+ white_underline = function(s: any)
+ return `\27[1;4m{s}\27[0m`
+ end,
+
+ white = function(s: any)
+ return `\27[37;1m{s}\27[0m`
+ end,
+
+ green = function(s: any)
+ return `\27[32;1m{s}\27[0m`
+ end,
+
+ red = function(s: any)
+ return `\27[31;1m{s}\27[0m`
+ end,
+
+ yellow = function(s: any)
+ return `\27[33;1m{s}\27[0m`
+ end,
+
+ red_highlight = function(s: any)
+ return `\27[41;1;30m{s}\27[0m`
+ end,
+
+ green_highlight = function(s: any)
+ return `\27[42;1;30m{s}\27[0m`
+ end,
+
+ gray = function(s: any)
+ return `\27[30;1m{s}\27[0m`
+ end,
+}
diff --git a/tools/entity_visualiser.luau b/tools/entity_visualiser.luau
index 6a2e41a..69dc910 100644
--- a/tools/entity_visualiser.luau
+++ b/tools/entity_visualiser.luau
@@ -1,43 +1,43 @@
-local jecs = require("@jecs")
-local ECS_GENERATION = jecs.ECS_GENERATION
-local ECS_ID = jecs.ECS_ID
-local ansi = require("@tools/ansi")
-
-local function pe(e: any)
- local gen = ECS_GENERATION(e)
- return ansi.green(`e{ECS_ID(e)}`)..ansi.yellow(`v{gen}`)
-end
-
-local function name(world: jecs.World, id: any)
- return world:get(id, jecs.Name) or `${id}`
-end
-
-local function components(world: jecs.World, entity: any)
- local r = jecs.entity_index_try_get(world.entity_index, entity)
- if not r then
- return false
- end
-
- local archetype = r.archetype
- local row = r.row
- print(`Entity {pe(entity)}`)
- print("-----------------------------------------------------")
- for i, column in archetype.columns do
- local component = archetype.types[i]
- local n
- if jecs.IS_PAIR(component) then
- n = `({name(world, jecs.pair_first(world, component))}, {name(world, jecs.pair_second(world, component))})`
- else
- n = name(world, component)
- end
- local data = column[row] or "TAG"
- print(`| {n} | {data} |`)
- end
- print("-----------------------------------------------------")
- return true
-end
-
-return {
- components = components,
- prettify = pe,
-}
+local jecs = require("@jecs")
+local ECS_GENERATION = jecs.ECS_GENERATION
+local ECS_ID = jecs.ECS_ID
+local ansi = require("@tools/ansi")
+
+local function pe(e: any)
+ local gen = ECS_GENERATION(e)
+ return ansi.green(`e{ECS_ID(e)}`) .. ansi.yellow(`v{gen}`)
+end
+
+local function name(world: jecs.World, id: any)
+ return world:get(id, jecs.Name) or `${id}`
+end
+
+local function components(world: jecs.World, entity: any)
+ local r = jecs.entity_index_try_get(world.entity_index, entity)
+ if not r then
+ return false
+ end
+
+ local archetype = r.archetype
+ local row = r.row
+ print(`Entity {pe(entity)}`)
+ print("-----------------------------------------------------")
+ for i, column in archetype.columns do
+ local component = archetype.types[i]
+ local n
+ if jecs.IS_PAIR(component) then
+ n = `({name(world, jecs.pair_first(world, component))}, {name(world, jecs.pair_second(world, component))})`
+ else
+ n = name(world, component)
+ end
+ local data = column[row] or "TAG"
+ print(`| {n} | {data} |`)
+ end
+ print("-----------------------------------------------------")
+ return true
+end
+
+return {
+ components = components,
+ prettify = pe,
+}
diff --git a/tools/lifetime_tracker.luau b/tools/lifetime_tracker.luau
index d48e689..c9abbbf 100644
--- a/tools/lifetime_tracker.luau
+++ b/tools/lifetime_tracker.luau
@@ -1,215 +1,216 @@
-local jecs = require("@jecs")
-local ECS_GENERATION = jecs.ECS_GENERATION
-local ECS_ID = jecs.ECS_ID
-local __ = jecs.Wildcard
-local pair = jecs.pair
-
-local prettify = require("@tools/entity_visualiser").prettify
-
-local pe = prettify
-local ansi = require("@tools/ansi")
-
-function print_centered_entity(entity, width: number)
- local entity_str = tostring(entity)
- local entity_length = #entity_str
-
- local padding_total = width - 2 - entity_length
-
- local padding_left = math.floor(padding_total / 2)
- local padding_right = padding_total - padding_left
-
- local centered_str = string.rep(" ", padding_left) .. entity_str .. string.rep(" ", padding_right)
-
- print("|" .. centered_str .. "|")
-end
-
-local function name(world, e)
- return world:get(world, e, jecs.Name) or pe(e)
-end
-local padding_enabled = false
-local function pad()
- if padding_enabled then
- print("")
- end
-end
-
-local function lifetime_tracker_add(world: jecs.World, opt)
- local entity_index = world.entity_index
- local dense_array = entity_index.dense_array
- local component_index = world.component_index
-
- local ENTITY_RANGE = (jecs.Rest :: any) + 1
-
- local w = setmetatable({}, { __index = world })
-
- padding_enabled = opt.padding_enabled
-
- local world_entity = world.entity
- w.entity = function(self, entity)
- if entity then
- return world_entity(world, entity)
- end
- local will_recycle = entity_index.max_id ~= entity_index.alive_count
- local e = world_entity(world)
- if will_recycle then
- print(`*recycled {pe(e)}`)
- else
- print(`*created {pe(e)}`)
- end
- pad()
- return e
- end
- w.print_entity_index = function(self)
- local max_id = entity_index.max_id
- local alive_count = entity_index.alive_count
- local alive = table.move(dense_array, 1+jecs.Rest::any, alive_count, 1, {})
- local dead = table.move(dense_array, alive_count + 1, max_id, 1, {})
-
- local sep = "|--------|"
- if #alive > 0 then
- print("|-alive--|")
- for i = 1, #alive do
- local e = pe(alive[i])
- print_centered_entity(e, 32)
- print(sep)
- end
- print("\n")
- end
-
- if #dead > 0 then
- print("|--dead--|")
- for i = 1, #dead do
- print_centered_entity(pe(dead[i]), 32)
- print(sep)
- end
- end
- pad()
- end
- local timelines = {}
- w.print_snapshot = function(self)
- local timeline = #timelines + 1
- local entity_column_width = 10
- local status_column_width = 8
-
- local header = string.format("| %-" .. entity_column_width .. "s |", "Entity")
- for i = 1, timeline do
- header = header .. string.format(" %-" .. status_column_width .. "s |", string.format("T%d", i))
- end
-
- local max_id = entity_index.max_id
- local alive_count = entity_index.alive_count
- local alive = table.move(dense_array, 1+jecs.Rest::any, alive_count, 1, {})
- local dead = table.move(dense_array, alive_count + 1, max_id, 1, {})
-
- local data = {}
- print("-------------------------------------------------------------------")
- print(header)
-
- -- Store the snapshot data for this timeline
- for i = ENTITY_RANGE, max_id do
- if dense_array[i] then
- local entity = dense_array[i]
- local id = ECS_ID(entity)
- local status = "alive"
- if not world:contains(entity) then
- status = "dead"
- end
- data[id] = status
- end
- end
-
- table.insert(timelines, data)
-
- -- Create a table to hold entity data for sorting
- local entities = {}
- for i = ENTITY_RANGE, max_id do
- if dense_array[i] then
- local entity = dense_array[i]
- local id = ECS_ID(entity)
- -- Push entity and id into the new `entities` table
- table.insert(entities, {entity = entity, id = id})
- end
- end
-
- -- Sort the entities by ECS_ID
- table.sort(entities, function(a, b)
- return a.id < b.id
- end)
-
- -- Print the sorted rows
- for _, entity_data in ipairs(entities) do
- local entity = entity_data.entity
- local id = entity_data.id
- local status = "alive"
- if id > alive_count then
- status = "dead"
- end
- local row = string.format("| %-" .. entity_column_width .. "s |", pe(entity))
- for j = 1, timeline do
- local timeline_data = timelines[j]
- local entity_data = timeline_data[id]
- if entity_data then
- row = row .. string.format(" %-" .. status_column_width .. "s |", entity_data)
- else
- row = row .. string.format(" %-" .. status_column_width .. "s |", "-")
- end
- end
- print(row)
- end
- print("-------------------------------------------------------------------")
- pad()
- end
- local world_add = world.add
- local relations = {}
- w.add = function(self, entity: any, component: any)
- world_add(world, entity, component)
- if jecs.IS_PAIR(component) then
- local relation = jecs.pair_first(world, component)
- local target = jecs.pair_second(world, component)
- print(`*added ({pe(relation)}, {pe(target)}) to {pe(entity)}`)
- pad()
- end
-
- end
-
- local world_delete = world.delete
- w.delete = function(self, e)
- world_delete(world, e)
-
- local idr_t = component_index[pair(__, e)]
- if idr_t then
- for archetype_id in idr_t.cache do
- local archetype = world.archetypes[archetype_id]
- for _, id in archetype.types do
- if not jecs.IS_PAIR(id) then
- continue
- end
- local object = jecs.pair_second(world, id)
- if object ~= e then
- continue
- end
- local id_record = component_index[id]
- local flags = id_record.flags
- local flags_delete_mask: number = bit32.band(flags, jecs.ECS_ID_DELETE)
- if flags_delete_mask ~= 0 then
- for _, entity in archetype.entities do
- print(`*deleted dependant {pe(entity)} of {pe(e)}`)
- pad()
- end
- break
- else
- for _, entity in archetype.entities do
- print(`*removed dependency ({pe(jecs.pair_first(world, id))}, {pe(object)}) from {pe(entity)}`)
- end
- end
- end
- end
- end
-
- print(`*deleted {pe(e)}`)
- pad()
- end
- return w
-end
-
-return lifetime_tracker_add
+local jecs = require("@jecs")
+local ECS_GENERATION = jecs.ECS_GENERATION
+local ECS_ID = jecs.ECS_ID
+local __ = jecs.Wildcard
+local pair = jecs.pair
+
+local prettify = require("@tools/entity_visualiser").prettify
+
+local pe = prettify
+local ansi = require("@tools/ansi")
+
+function print_centered_entity(entity, width: number)
+ local entity_str = tostring(entity)
+ local entity_length = #entity_str
+
+ local padding_total = width - 2 - entity_length
+
+ local padding_left = math.floor(padding_total / 2)
+ local padding_right = padding_total - padding_left
+
+ local centered_str = string.rep(" ", padding_left) .. entity_str .. string.rep(" ", padding_right)
+
+ print("|" .. centered_str .. "|")
+end
+
+local function name(world, e)
+ return world:get(world, e, jecs.Name) or pe(e)
+end
+local padding_enabled = false
+local function pad()
+ if padding_enabled then
+ print("")
+ end
+end
+
+local function lifetime_tracker_add(world: jecs.World, opt)
+ local entity_index = world.entity_index
+ local dense_array = entity_index.dense_array
+ local component_index = world.component_index
+
+ local ENTITY_RANGE = (jecs.Rest :: any) + 1
+
+ local w = setmetatable({}, { __index = world })
+
+ padding_enabled = opt.padding_enabled
+
+ local world_entity = world.entity
+ w.entity = function(self, entity)
+ if entity then
+ return world_entity(world, entity)
+ end
+ local will_recycle = entity_index.max_id ~= entity_index.alive_count
+ local e = world_entity(world)
+ if will_recycle then
+ print(`*recycled {pe(e)}`)
+ else
+ print(`*created {pe(e)}`)
+ end
+ pad()
+ return e
+ end
+ w.print_entity_index = function(self)
+ local max_id = entity_index.max_id
+ local alive_count = entity_index.alive_count
+ local alive = table.move(dense_array, 1 + jecs.Rest :: any, alive_count, 1, {})
+ local dead = table.move(dense_array, alive_count + 1, max_id, 1, {})
+
+ local sep = "|--------|"
+ if #alive > 0 then
+ print("|-alive--|")
+ for i = 1, #alive do
+ local e = pe(alive[i])
+ print_centered_entity(e, 32)
+ print(sep)
+ end
+ print("\n")
+ end
+
+ if #dead > 0 then
+ print("|--dead--|")
+ for i = 1, #dead do
+ print_centered_entity(pe(dead[i]), 32)
+ print(sep)
+ end
+ end
+ pad()
+ end
+ local timelines = {}
+ w.print_snapshot = function(self)
+ local timeline = #timelines + 1
+ local entity_column_width = 10
+ local status_column_width = 8
+
+ local header = string.format("| %-" .. entity_column_width .. "s |", "Entity")
+ for i = 1, timeline do
+ header = header .. string.format(" %-" .. status_column_width .. "s |", string.format("T%d", i))
+ end
+
+ local max_id = entity_index.max_id
+ local alive_count = entity_index.alive_count
+ local alive = table.move(dense_array, 1 + jecs.Rest :: any, alive_count, 1, {})
+ local dead = table.move(dense_array, alive_count + 1, max_id, 1, {})
+
+ local data = {}
+ print("-------------------------------------------------------------------")
+ print(header)
+
+ -- Store the snapshot data for this timeline
+ for i = ENTITY_RANGE, max_id do
+ if dense_array[i] then
+ local entity = dense_array[i]
+ local id = ECS_ID(entity)
+ local status = "alive"
+ if not world:contains(entity) then
+ status = "dead"
+ end
+ data[id] = status
+ end
+ end
+
+ table.insert(timelines, data)
+
+ -- Create a table to hold entity data for sorting
+ local entities = {}
+ for i = ENTITY_RANGE, max_id do
+ if dense_array[i] then
+ local entity = dense_array[i]
+ local id = ECS_ID(entity)
+ -- Push entity and id into the new `entities` table
+ table.insert(entities, { entity = entity, id = id })
+ end
+ end
+
+ -- Sort the entities by ECS_ID
+ table.sort(entities, function(a, b)
+ return a.id < b.id
+ end)
+
+ -- Print the sorted rows
+ for _, entity_data in ipairs(entities) do
+ local entity = entity_data.entity
+ local id = entity_data.id
+ local status = "alive"
+ if id > alive_count then
+ status = "dead"
+ end
+ local row = string.format("| %-" .. entity_column_width .. "s |", pe(entity))
+ for j = 1, timeline do
+ local timeline_data = timelines[j]
+ local entity_data = timeline_data[id]
+ if entity_data then
+ row = row .. string.format(" %-" .. status_column_width .. "s |", entity_data)
+ else
+ row = row .. string.format(" %-" .. status_column_width .. "s |", "-")
+ end
+ end
+ print(row)
+ end
+ print("-------------------------------------------------------------------")
+ pad()
+ end
+ local world_add = world.add
+ local relations = {}
+ w.add = function(self, entity: any, component: any)
+ world_add(world, entity, component)
+ if jecs.IS_PAIR(component) then
+ local relation = jecs.pair_first(world, component)
+ local target = jecs.pair_second(world, component)
+ print(`*added ({pe(relation)}, {pe(target)}) to {pe(entity)}`)
+ pad()
+ end
+ end
+
+ local world_delete = world.delete
+ w.delete = function(self, e)
+ world_delete(world, e)
+
+ local idr_t = component_index[pair(__, e)]
+ if idr_t then
+ for archetype_id in idr_t.cache do
+ local archetype = world.archetypes[archetype_id]
+ for _, id in archetype.types do
+ if not jecs.IS_PAIR(id) then
+ continue
+ end
+ local object = jecs.pair_second(world, id)
+ if object ~= e then
+ continue
+ end
+ local id_record = component_index[id]
+ local flags = id_record.flags
+ local flags_delete_mask: number = bit32.band(flags, jecs.ECS_ID_DELETE)
+ if flags_delete_mask ~= 0 then
+ for _, entity in archetype.entities do
+ print(`*deleted dependant {pe(entity)} of {pe(e)}`)
+ pad()
+ end
+ break
+ else
+ for _, entity in archetype.entities do
+ print(
+ `*removed dependency ({pe(jecs.pair_first(world, id))}, {pe(object)}) from {pe(entity)}`
+ )
+ end
+ end
+ end
+ end
+ end
+
+ print(`*deleted {pe(e)}`)
+ pad()
+ end
+ return w
+end
+
+return lifetime_tracker_add
diff --git a/tools/runtime_lints.luau b/tools/runtime_lints.luau
index 229d9f5..9a38bde 100644
--- a/tools/runtime_lints.luau
+++ b/tools/runtime_lints.luau
@@ -1,108 +1,108 @@
-local function dbg_info(n: number): any
- return debug.info(n, "s")
-end
-local function throw(msg: string)
- local s = 1
- local root = dbg_info(1)
- repeat
- s += 1
- until dbg_info(s) ~= root
- if warn then
- error(msg, s)
- else
- print(`[jecs] error: {msg}\n`)
- end
-end
-
-local function ASSERT(v: T, msg: string)
- if v then
- return
- end
- throw(msg)
-end
-
-local function runtime_lints_add(world)
- local function get_name(id)
- return world_get_one_inline(world, id, EcsName)
- end
-
- local function bname(id): string
- local name: string
- if ECS_IS_PAIR(id) then
- local first = get_name(world, ecs_pair_first(world, id))
- local second = get_name(world, ecs_pair_second(world, id))
- name = `pair({first}, {second})`
- else
- return get_name(world, id)
- end
- if name then
- return name
- else
- return `${id}`
- end
- end
-
- local function ID_IS_TAG(world: World, id)
- if ECS_IS_PAIR(id) then
- id = ecs_pair_first(world, id)
- end
- return not world_has_one_inline(world, id, EcsComponent)
- end
-
- World.query = function(world: World, ...)
- ASSERT((...), "Requires at least a single component")
- return world_query(world, ...)
- end
-
- World.set = function(world: World, entity: i53, id: i53, value: any): ()
- local is_tag = ID_IS_TAG(world, id)
- if is_tag and value == nil then
- local _1 = bname(world, entity)
- local _2 = bname(world, id)
- local why = "cannot set component value to nil"
- throw(why)
- return
- elseif value ~= nil and is_tag then
- local _1 = bname(world, entity)
- local _2 = bname(world, id)
- local why = `cannot set a component value because {_2} is a tag`
- why ..= `\n[jecs] note: consider using "world:add({_1}, {_2})" instead`
- throw(why)
- return
- end
-
- world_set(world, entity, id, value)
- end
-
- World.add = function(world: World, entity: i53, id: i53, value: any)
- if value ~= nil then
- local _1 = bname(world, entity)
- local _2 = bname(world, id)
- throw("You provided a value when none was expected. " .. `Did you mean to use "world:add({_1}, {_2})"`)
- end
-
- world_add(world, entity, id)
- end
-
- World.get = function(world: World, entity: i53, ...)
- local length = select("#", ...)
- ASSERT(length < 5, "world:get does not support more than 4 components")
- local _1
- for i = 1, length do
- local id = select(i, ...)
- local id_is_tag = not world_has(world, id, EcsComponent)
- if id_is_tag then
- local name = get_name(world, id)
- if not _1 then
- _1 = get_name(world, entity)
- end
- throw(
- `cannot get (#{i}) component {name} value because it is a tag.`
- .. `\n[jecs] note: If this was intentional, use "world:has({_1}, {name}) instead"`
- )
- end
- end
-
- return world_get(world, entity, ...)
- end
-end
+local function dbg_info(n: number): any
+ return debug.info(n, "s")
+end
+local function throw(msg: string)
+ local s = 1
+ local root = dbg_info(1)
+ repeat
+ s += 1
+ until dbg_info(s) ~= root
+ if warn then
+ error(msg, s)
+ else
+ print(`[jecs] error: {msg}\n`)
+ end
+end
+
+local function ASSERT(v: T, msg: string)
+ if v then
+ return
+ end
+ throw(msg)
+end
+
+local function runtime_lints_add(world)
+ local function get_name(id)
+ return world_get_one_inline(world, id, EcsName)
+ end
+
+ local function bname(id): string
+ local name: string
+ if ECS_IS_PAIR(id) then
+ local first = get_name(world, ecs_pair_first(world, id))
+ local second = get_name(world, ecs_pair_second(world, id))
+ name = `pair({first}, {second})`
+ else
+ return get_name(world, id)
+ end
+ if name then
+ return name
+ else
+ return `${id}`
+ end
+ end
+
+ local function ID_IS_TAG(world: World, id)
+ if ECS_IS_PAIR(id) then
+ id = ecs_pair_first(world, id)
+ end
+ return not world_has_one_inline(world, id, EcsComponent)
+ end
+
+ World.query = function(world: World, ...)
+ ASSERT((...), "Requires at least a single component")
+ return world_query(world, ...)
+ end
+
+ World.set = function(world: World, entity: i53, id: i53, value: any): ()
+ local is_tag = ID_IS_TAG(world, id)
+ if is_tag and value == nil then
+ local _1 = bname(world, entity)
+ local _2 = bname(world, id)
+ local why = "cannot set component value to nil"
+ throw(why)
+ return
+ elseif value ~= nil and is_tag then
+ local _1 = bname(world, entity)
+ local _2 = bname(world, id)
+ local why = `cannot set a component value because {_2} is a tag`
+ why ..= `\n[jecs] note: consider using "world:add({_1}, {_2})" instead`
+ throw(why)
+ return
+ end
+
+ world_set(world, entity, id, value)
+ end
+
+ World.add = function(world: World, entity: i53, id: i53, value: any)
+ if value ~= nil then
+ local _1 = bname(world, entity)
+ local _2 = bname(world, id)
+ throw("You provided a value when none was expected. " .. `Did you mean to use "world:add({_1}, {_2})"`)
+ end
+
+ world_add(world, entity, id)
+ end
+
+ World.get = function(world: World, entity: i53, ...)
+ local length = select("#", ...)
+ ASSERT(length < 5, "world:get does not support more than 4 components")
+ local _1
+ for i = 1, length do
+ local id = select(i, ...)
+ local id_is_tag = not world_has(world, id, EcsComponent)
+ if id_is_tag then
+ local name = get_name(world, id)
+ if not _1 then
+ _1 = get_name(world, entity)
+ end
+ throw(
+ `cannot get (#{i}) component {name} value because it is a tag.`
+ .. `\n[jecs] note: If this was intentional, use "world:has({_1}, {name}) instead"`
+ )
+ end
+ end
+
+ return world_get(world, entity, ...)
+ end
+end
diff --git a/tools/testkit.luau b/tools/testkit.luau
index d362114..e37da98 100644
--- a/tools/testkit.luau
+++ b/tools/testkit.luau
@@ -534,7 +534,7 @@ return {
FINISH = FINISH,
SKIP = SKIP,
FOCUS = FOCUS,
- CHECK_EXPECT_ERR = CHECK_EXPECT_ERR
+ CHECK_EXPECT_ERR = CHECK_EXPECT_ERR,
}
end,