diff --git a/package.json b/package.json
index 1d5906b..7f20bf1 100644
--- a/package.json
+++ b/package.json
@@ -42,9 +42,9 @@
},
"devDependencies": {
"@babel/core": "^7.23.6",
- "@typescript-eslint/parser": "^7.1.0",
- "@typescript-eslint/scope-manager": "^7.1.0",
- "@typescript-eslint/visitor-keys": "^7.1.0",
+ "@typescript-eslint/parser": "^8.0.0",
+ "@typescript-eslint/scope-manager": "^8.0.0",
+ "@typescript-eslint/visitor-keys": "^8.0.0",
"concurrently": "^8.2.2",
"eslint": "^8.0.1",
"eslint-config-prettier": "^9.1.0",
@@ -64,16 +64,20 @@
"vitest": "^1.2.2"
},
"peerDependencies": {
+ "@glint/ember-tsc": ">= 1.1.0",
"@typescript-eslint/parser": "*"
},
"peerDependenciesMeta": {
+ "@glint/ember-tsc": {
+ "optional": true
+ },
"@typescript-eslint/parser": {
"optional": true
}
},
"packageManager": "pnpm@10.21.0",
"engines": {
- "node": ">=16.0.0"
+ "node": ">=22.12.0"
},
"pnpm": {
"overrides": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 030b59c..dff2377 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,15 +14,18 @@ importers:
'@glimmer/syntax':
specifier: ^0.95.0
version: 0.95.0
+ '@glint/ember-tsc':
+ specifier: '>= 1.1.0'
+ version: 1.1.1(typescript@5.7.2)
'@typescript-eslint/tsconfig-utils':
specifier: ^8.57.1
- version: 8.57.1(typescript@5.7.2)
+ version: 8.58.1(typescript@5.7.2)
content-tag:
specifier: ^4.1.1
version: 4.1.1
ember-estree:
specifier: ^0.4.2
- version: 0.4.2
+ version: 0.4.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
eslint-scope:
specifier: ^9.1.2
version: 9.1.2
@@ -40,14 +43,14 @@ importers:
specifier: ^7.23.6
version: 7.26.0
'@typescript-eslint/parser':
- specifier: ^7.1.0
- version: 7.18.0(eslint@8.57.1)(typescript@5.7.2)
+ specifier: ^8.0.0
+ version: 8.46.4(eslint@8.57.1)(typescript@5.7.2)
'@typescript-eslint/scope-manager':
- specifier: ^7.1.0
- version: 7.18.0
+ specifier: ^8.0.0
+ version: 8.46.4
'@typescript-eslint/visitor-keys':
- specifier: ^7.1.0
- version: 7.18.0
+ specifier: ^8.0.0
+ version: 8.46.4
concurrently:
specifier: ^8.2.2
version: 8.2.2
@@ -59,10 +62,10 @@ importers:
version: 9.1.0(eslint@8.57.1)
eslint-config-standard:
specifier: ^17.1.0
- version: 17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint-plugin-n@16.6.2(eslint@8.57.1))(eslint-plugin-promise@6.6.0(eslint@8.57.1))(eslint@8.57.1)
+ version: 17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint-plugin-n@16.6.2(eslint@8.57.1))(eslint-plugin-promise@6.6.0(eslint@8.57.1))(eslint@8.57.1)
eslint-plugin-import:
specifier: ^2.25.2
- version: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
+ version: 2.31.0(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
eslint-plugin-n:
specifier: ^16.4.0
version: 16.6.2(eslint@8.57.1)
@@ -95,10 +98,10 @@ importers:
version: 5.7.2
vite:
specifier: ^5.0.12
- version: 5.4.11(@types/node@25.5.0)(terser@5.46.1)
+ version: 5.4.11(@types/node@25.3.3)(terser@5.46.0)
vitest:
specifier: ^1.2.2
- version: 1.6.0(@types/node@25.5.0)(terser@5.46.1)
+ version: 1.6.0(@types/node@25.3.3)(terser@5.46.0)
test-projects/configs/flat-js:
dependencies:
@@ -108,10 +111,10 @@ importers:
devDependencies:
'@babel/eslint-parser':
specifier: ^7.28.6
- version: 7.28.6(@babel/core@7.29.0)(eslint@8.57.1)
+ version: 7.28.6(@babel/core@7.26.0)(eslint@8.57.1)
'@babel/plugin-proposal-decorators':
specifier: ^7.23.9
- version: 7.25.9(@babel/core@7.29.0)
+ version: 7.25.9(@babel/core@7.26.0)
ember-eslint-parser:
specifier: workspace:*
version: link:../../..
@@ -120,7 +123,7 @@ importers:
version: 8.57.1
eslint-plugin-ember:
specifier: ^12.0.0
- version: 12.3.3(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)
+ version: 12.3.3(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
globals:
specifier: ^13.24.0
version: 13.24.0
@@ -139,12 +142,18 @@ importers:
'@eslint/js':
specifier: ^9.17.0
version: 9.17.0
+ '@glint/ember-tsc':
+ specifier: ^1.1.0
+ version: 1.1.1(typescript@5.7.2)
+ '@glint/template':
+ specifier: ^1.3.0
+ version: 1.7.4
'@tsconfig/ember':
specifier: ^3.0.8
version: 3.0.8
ember-source:
specifier: ^6.1.0
- version: 6.1.0(@glimmer/component@2.0.0)(@glint/template@1.5.0)(rsvp@4.8.5)(webpack@5.94.0)
+ version: 6.1.0(@glimmer/component@2.0.0)(@glint/template@1.7.4)(rsvp@4.8.5)(webpack@5.94.0)
eslint:
specifier: ^9.17.0
version: 9.17.0
@@ -231,7 +240,7 @@ importers:
devDependencies:
'@babel/eslint-parser':
specifier: ^7.28.6
- version: 7.28.6(@babel/core@7.29.0)(eslint@8.57.1)
+ version: 7.28.6(@babel/core@7.26.0)(eslint@8.57.1)
'@typescript-eslint/eslint-plugin':
specifier: ^8.46.4
version: 8.46.4(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
@@ -267,10 +276,13 @@ importers:
version: 3.1.0
'@glimmer/component':
specifier: ^1.1.2
- version: 1.1.2(@babel/core@7.29.0)
+ version: 1.1.2(@babel/core@7.26.0)
'@glimmer/tracking':
specifier: ^1.1.2
version: 1.1.2
+ '@glint/ember-tsc':
+ specifier: ^1.1.0
+ version: 1.1.1(typescript@5.7.2)
'@glint/template':
specifier: ^1.3.0
version: 1.5.0
@@ -285,7 +297,7 @@ importers:
version: link:../..
ember-source:
specifier: ^5.6.0
- version: 5.12.0(@glimmer/component@1.1.2(@babel/core@7.29.0))(@glint/template@1.5.0)(rsvp@4.8.5)(webpack@5.94.0)
+ version: 5.12.0(@glimmer/component@1.1.2(@babel/core@7.26.0))(@glint/template@1.5.0)(rsvp@4.8.5)(webpack@5.94.0)
eslint:
specifier: ^8.0.1
version: 8.57.1
@@ -350,6 +362,45 @@ importers:
specifier: ^8.19.1
version: 8.19.1(eslint@8.57.1)(typescript@5.7.2)
+ test-projects/gts-glint:
+ devDependencies:
+ '@ember/test-waiters':
+ specifier: ^3.1.0
+ version: 3.1.0
+ '@glimmer/component':
+ specifier: ^1.1.2
+ version: 1.1.2(@babel/core@7.26.0)
+ '@glimmer/tracking':
+ specifier: ^1.1.2
+ version: 1.1.2
+ '@glint/ember-tsc':
+ specifier: ^1.1.0
+ version: 1.1.1(typescript@5.7.2)
+ '@glint/template':
+ specifier: ^1.3.0
+ version: 1.5.0
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^8.46.4
+ version: 8.46.4(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
+ '@typescript-eslint/parser':
+ specifier: ^8.46.4
+ version: 8.46.4(eslint@8.57.1)(typescript@5.7.2)
+ ember-eslint-parser:
+ specifier: workspace:*
+ version: link:../..
+ ember-source:
+ specifier: ^5.6.0
+ version: 5.12.0(@glimmer/component@1.1.2(@babel/core@7.26.0))(@glint/template@1.5.0)(rsvp@4.8.5)(webpack@5.94.0)
+ eslint:
+ specifier: ^8.0.1
+ version: 8.57.1
+ eslint-plugin-ember:
+ specifier: ^12.0.0
+ version: 12.3.3(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
+ typescript:
+ specifier: ^5.3.3
+ version: 5.7.2
+
test-projects/hbs:
devDependencies:
ember-eslint-parser:
@@ -398,10 +449,6 @@ packages:
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
- '@babel/code-frame@7.29.0':
- resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
- engines: {node: '>=6.9.0'}
-
'@babel/compat-data@7.26.3':
resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==}
engines: {node: '>=6.9.0'}
@@ -410,18 +457,10 @@ packages:
resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==}
engines: {node: '>=6.9.0'}
- '@babel/compat-data@7.29.0':
- resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
- engines: {node: '>=6.9.0'}
-
'@babel/core@7.26.0':
resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==}
engines: {node: '>=6.9.0'}
- '@babel/core@7.29.0':
- resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==}
- engines: {node: '>=6.9.0'}
-
'@babel/eslint-parser@7.28.6':
resolution: {integrity: sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==}
engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0}
@@ -437,10 +476,6 @@ packages:
resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==}
engines: {node: '>=6.9.0'}
- '@babel/generator@7.29.1':
- resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
- engines: {node: '>=6.9.0'}
-
'@babel/helper-annotate-as-pure@7.25.9':
resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==}
engines: {node: '>=6.9.0'}
@@ -453,10 +488,6 @@ packages:
resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
engines: {node: '>=6.9.0'}
- '@babel/helper-compilation-targets@7.28.6':
- resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
- engines: {node: '>=6.9.0'}
-
'@babel/helper-create-class-features-plugin@7.25.9':
resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==}
engines: {node: '>=6.9.0'}
@@ -490,22 +521,12 @@ packages:
resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
engines: {node: '>=6.9.0'}
- '@babel/helper-module-imports@7.28.6':
- resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
- engines: {node: '>=6.9.0'}
-
'@babel/helper-module-transforms@7.26.0':
resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
- '@babel/helper-module-transforms@7.28.6':
- resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0
-
'@babel/helper-optimise-call-expression@7.25.9':
resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==}
engines: {node: '>=6.9.0'}
@@ -566,10 +587,6 @@ packages:
resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==}
engines: {node: '>=6.9.0'}
- '@babel/helpers@7.29.2':
- resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==}
- engines: {node: '>=6.9.0'}
-
'@babel/parser@7.26.3':
resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==}
engines: {node: '>=6.0.0'}
@@ -580,11 +597,6 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/parser@7.29.2':
- resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==}
- engines: {node: '>=6.0.0'}
- hasBin: true
-
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9':
resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==}
engines: {node: '>=6.9.0'}
@@ -1031,10 +1043,6 @@ packages:
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'}
- '@babel/template@7.28.6':
- resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
- engines: {node: '>=6.9.0'}
-
'@babel/traverse@7.26.4':
resolution: {integrity: sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==}
engines: {node: '>=6.9.0'}
@@ -1043,10 +1051,6 @@ packages:
resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==}
engines: {node: '>=6.9.0'}
- '@babel/traverse@7.29.0':
- resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
- engines: {node: '>=6.9.0'}
-
'@babel/types@7.26.3':
resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==}
engines: {node: '>=6.9.0'}
@@ -1055,10 +1059,6 @@ packages:
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
engines: {node: '>=6.9.0'}
- '@babel/types@7.29.0':
- resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
- engines: {node: '>=6.9.0'}
-
'@ember-data/rfc395-data@0.0.4':
resolution: {integrity: sha512-tGRdvgC9/QMQSuSuJV45xoyhI0Pzjm7A9o/MVVA3HakXIImJbbzx/k/6dO9CUEQXIyS2y0fW6C1XaYOG7rY0FQ==}
@@ -1094,14 +1094,14 @@ packages:
resolution: {integrity: sha512-/SusdG+zgosc3t+9sPFVKSFOYyiSgLfXOT6lYNWoG1YtnhWDxlK4S8leZ0jhcVjemdaHln5rTyxCnq8oFLxqpQ==}
engines: {node: 12.* || 14.* || >= 16}
- '@emnapi/core@1.9.1':
- resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==}
+ '@emnapi/core@1.9.2':
+ resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==}
- '@emnapi/runtime@1.9.1':
- resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==}
+ '@emnapi/runtime@1.9.2':
+ resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==}
- '@emnapi/wasi-threads@1.2.0':
- resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==}
+ '@emnapi/wasi-threads@1.2.1':
+ resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
'@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
@@ -1401,14 +1401,23 @@ packages:
'@glimmer/wire-format@0.94.8':
resolution: {integrity: sha512-A+Cp5m6vZMAEu0Kg/YwU2dJZXyYxVJs2zI57d3CP6NctmX7FsT8WjViiRUmt5abVmMmRH5b8BUovqY6GSMAdrw==}
+ '@glint/ember-tsc@1.1.1':
+ resolution: {integrity: sha512-SEIyDPOv9nKpoXaRWp6rXrAnZu75GXW3MVg9nmxX0bwc0s2Aydpd/T0YjZux1ZJ0v8YevmFkBjlxk3UiSU3a6g==}
+ hasBin: true
+ peerDependencies:
+ typescript: '>=5.6.0'
+
'@glint/template@1.5.0':
resolution: {integrity: sha512-KyQUCWifxl8wDxo3SXzJcGKttHbIPgFBtqsoiu13Edx/o4CgGXr5rrM64jJR7Wvunn8sRM+Rq7Y0cHoB068Wuw==}
+ '@glint/template@1.7.4':
+ resolution: {integrity: sha512-39gTESXJmiIzJhcweJQ+44eIX+n+alJpD6HKpX8nPXCggVu2Yq6KP9pA5gwUvWE1/NYZhITiOqdA7UuyVtWMww==}
+
'@handlebars/parser@2.0.0':
resolution: {integrity: sha512-EP9uEDZv/L5Qh9IWuMUGJRfwhXJ4h1dqKTT4/3+tY0eu7sPis7xh23j61SYUnNF4vqCQvvUXpDo9Bh/+q1zASA==}
- '@handlebars/parser@2.2.2':
- resolution: {integrity: sha512-n/SZW+12rwikx/f8YcSv9JCi5p9vn1Bnts9ZtVvfErG4h0gbjHI1H1ZMhVUnaOC7yzFc6PtsCKIK8XeTnL90Gw==}
+ '@handlebars/parser@2.2.1':
+ resolution: {integrity: sha512-D76vKOZFEGA9v6g0rZTYTQDUXNopCblW1Zeas3EEVrbdeh8gWrCEO9/goocKmcgtqAwv1Md76p58UQp7HeFTEw==}
engines: {node: ^18 || ^20 || ^22 || >=24}
'@humanfs/core@0.19.1':
@@ -1455,9 +1464,6 @@ packages:
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
engines: {node: '>=6.0.0'}
- '@jridgewell/remapping@2.3.5':
- resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
-
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
@@ -1490,8 +1496,11 @@ packages:
resolution: {integrity: sha512-SkAyKAByB9l93Slyg8AUHGuM2kjvWioUTCckT/03J09jYnfEzMO/wSXmEhnKGYs6qx9De8TH4yJCl0Y9lRgnyQ==}
engines: {node: '>=14.18.0'}
- '@napi-rs/wasm-runtime@1.1.1':
- resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==}
+ '@napi-rs/wasm-runtime@1.1.3':
+ resolution: {integrity: sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==}
+ peerDependencies:
+ '@emnapi/core': ^1.7.1
+ '@emnapi/runtime': ^1.7.1
'@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1':
resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==}
@@ -1882,8 +1891,8 @@ packages:
'@types/node@22.10.5':
resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==}
- '@types/node@25.5.0':
- resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==}
+ '@types/node@25.3.3':
+ resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==}
'@types/rimraf@2.0.5':
resolution: {integrity: sha512-YyP+VfeaqAyFmXoTh3HChxOQMyjByRMsHU7kc5KOJkSlXudhMhQIALbYV7rHh/l8d2lX3VUQzprrcAgWdRuU8g==}
@@ -1907,16 +1916,6 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/parser@7.18.0':
- resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==}
- engines: {node: ^18.18.0 || >=20.0.0}
- peerDependencies:
- eslint: ^8.56.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
'@typescript-eslint/parser@8.19.1':
resolution: {integrity: sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1937,10 +1936,6 @@ packages:
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/scope-manager@7.18.0':
- resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==}
- engines: {node: ^18.18.0 || >=20.0.0}
-
'@typescript-eslint/scope-manager@8.19.1':
resolution: {integrity: sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1955,11 +1950,11 @@ packages:
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/tsconfig-utils@8.57.1':
- resolution: {integrity: sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg==}
+ '@typescript-eslint/tsconfig-utils@8.58.1':
+ resolution: {integrity: sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
+ typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/type-utils@8.19.1':
resolution: {integrity: sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==}
@@ -1975,10 +1970,6 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/types@7.18.0':
- resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==}
- engines: {node: ^18.18.0 || >=20.0.0}
-
'@typescript-eslint/types@8.19.1':
resolution: {integrity: sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1987,15 +1978,6 @@ packages:
resolution: {integrity: sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@7.18.0':
- resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==}
- engines: {node: ^18.18.0 || >=20.0.0}
- peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
'@typescript-eslint/typescript-estree@8.19.1':
resolution: {integrity: sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2022,10 +2004,6 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/visitor-keys@7.18.0':
- resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==}
- engines: {node: ^18.18.0 || >=20.0.0}
-
'@typescript-eslint/visitor-keys@8.19.1':
resolution: {integrity: sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2052,6 +2030,32 @@ packages:
'@vitest/utils@1.6.0':
resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==}
+ '@volar/kit@2.4.28':
+ resolution: {integrity: sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==}
+ peerDependencies:
+ typescript: '*'
+
+ '@volar/language-core@2.4.28':
+ resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==}
+
+ '@volar/language-server@2.4.28':
+ resolution: {integrity: sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==}
+
+ '@volar/language-service@2.4.28':
+ resolution: {integrity: sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==}
+
+ '@volar/source-map@2.4.28':
+ resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==}
+
+ '@volar/test-utils@2.4.28':
+ resolution: {integrity: sha512-N7RNiHHDPtqK5B21x4W462XMQj7Z75ynN3isLP+3Rb44hbJjhxxDxzs+QqWB0sjM57EtTJga+SDd9WWy3OjMzA==}
+
+ '@volar/typescript@2.4.28':
+ resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==}
+
+ '@vscode/l10n@0.0.18':
+ resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==}
+
'@webassemblyjs/ast@1.14.1':
resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
@@ -2372,8 +2376,8 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
- baseline-browser-mapping@2.10.9:
- resolution: {integrity: sha512-OZd0e2mU11ClX8+IdXe3r0dbqMEznRiT4TfbhYIbcRPZkqJ7Qwer8ij3GZAmLsRKa+II9V1v5czCkvmHH3XZBg==}
+ baseline-browser-mapping@2.10.0:
+ resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -2551,8 +2555,8 @@ packages:
caniuse-lite@1.0.30001754:
resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==}
- caniuse-lite@1.0.30001780:
- resolution: {integrity: sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==}
+ caniuse-lite@1.0.30001775:
+ resolution: {integrity: sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==}
chai@4.5.0:
resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==}
@@ -2630,6 +2634,9 @@ packages:
config-chain@1.1.13:
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
+ content-tag@3.1.3:
+ resolution: {integrity: sha512-4Kiv9mEroxuMXfWUNUHcljVJgxThCNk7eEswdHMXdzJnkBBaYDqDwzHkoh3F74JJhfU3taJOsgpR6oEGIDg17g==}
+
content-tag@4.1.1:
resolution: {integrity: sha512-LyIbq4ZY+WbN0NoyHmg0w1kLPHyXZkZZrTDJZm/HW+MVurnKJy7U3m8WlpKm6lqbYbUSWP6ATNacE5dL2eH8+g==}
@@ -2787,8 +2794,8 @@ packages:
electron-to-chromium@1.5.250:
resolution: {integrity: sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==}
- electron-to-chromium@1.5.321:
- resolution: {integrity: sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==}
+ electron-to-chromium@1.5.302:
+ resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==}
electron-to-chromium@1.5.78:
resolution: {integrity: sha512-UmwIt7HRKN1rsJfddG5UG7rCTCTAKoS9JeOy/R0zSenAyaZ8SU3RuXlwcratxhdxGRNpk03iq8O7BA3W7ibLVw==}
@@ -2891,8 +2898,8 @@ packages:
resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==}
engines: {node: '>=10.13.0'}
- enhanced-resolve@5.20.1:
- resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==}
+ enhanced-resolve@5.20.0:
+ resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==}
engines: {node: '>=10.13.0'}
ensure-posix-path@1.1.1:
@@ -4240,9 +4247,6 @@ packages:
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
- node-releases@2.0.36:
- resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==}
-
npm-bundled@2.0.1:
resolution: {integrity: sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@@ -4433,6 +4437,9 @@ packages:
parse5@6.0.1:
resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
+ path-browserify@1.0.1:
+ resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
path-exists@3.0.0:
resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
engines: {node: '>=4'}
@@ -4627,6 +4634,9 @@ packages:
quick-temp@0.1.8:
resolution: {integrity: sha512-YsmIFfD9j2zaFwJkzI6eMG7y0lQP7YeWzgtFgNl38pGWZBSXJooZbOWwkcRot7Vt0Fg9L23pX0tqWU3VvLDsiA==}
+ randombytes@2.1.0:
+ resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
+
rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
@@ -4700,6 +4710,9 @@ packages:
remove-types@1.0.0:
resolution: {integrity: sha512-G7Hk1Q+UJ5DvlNAoJZObxANkBZGiGdp589rVcTW/tYqJWJ5rwfraSnKSQaETN8Epaytw8J40nS/zC7bcHGv36w==}
+ request-light@0.7.0:
+ resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==}
+
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@@ -4819,6 +4832,9 @@ packages:
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
engines: {node: '>=0.4'}
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
safe-push-apply@1.0.0:
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
engines: {node: '>= 0.4'}
@@ -4872,6 +4888,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ serialize-javascript@6.0.2:
+ resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
+
set-function-length@1.2.0:
resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==}
engines: {node: '>= 0.4'}
@@ -4954,10 +4973,6 @@ packages:
resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==}
engines: {node: '>= 10.13.0', npm: '>= 3.0.0'}
- source-map-js@1.0.2:
- resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
- engines: {node: '>=0.10.0'}
-
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -5125,8 +5140,8 @@ packages:
engines: {node: '>=10'}
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
- terser-webpack-plugin@5.4.0:
- resolution: {integrity: sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==}
+ terser-webpack-plugin@5.3.16:
+ resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==}
engines: {node: '>= 10.13.0'}
peerDependencies:
'@swc/core': '*'
@@ -5141,8 +5156,8 @@ packages:
uglify-js:
optional: true
- terser@5.46.1:
- resolution: {integrity: sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==}
+ terser@5.46.0:
+ resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==}
engines: {node: '>=10'}
hasBin: true
@@ -5190,12 +5205,6 @@ packages:
tree-sync@1.4.0:
resolution: {integrity: sha512-YvYllqh3qrR5TAYZZTXdspnIhlKAYezPYw11ntmweoceu4VK+keN356phHRIIo1d+RDmLpHZrUlmxga2gc9kSQ==}
- ts-api-utils@1.4.3:
- resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==}
- engines: {node: '>=16'}
- peerDependencies:
- typescript: '>=4.2.0'
-
ts-api-utils@2.1.0:
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
engines: {node: '>=18.12'}
@@ -5205,9 +5214,6 @@ packages:
tsconfig-paths@3.15.0:
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
- tslib@2.6.2:
- resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
-
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -5274,6 +5280,12 @@ packages:
resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
engines: {node: '>= 0.4'}
+ typesafe-path@0.2.2:
+ resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==}
+
+ typescript-auto-import-cache@0.3.6:
+ resolution: {integrity: sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==}
+
typescript-eslint@8.19.1:
resolution: {integrity: sha512-LKPUQpdEMVOeKluHi8md7rwLcoXHhwvWp3x+sJkMuq3gGm9yaYJtPo8sRZSblMFJ5pcOGCAak/scKf1mvZDlQw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -5289,11 +5301,6 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
- typescript@5.9.3:
- resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
- engines: {node: '>=14.17'}
- hasBin: true
-
ufo@1.5.4:
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
@@ -5450,6 +5457,48 @@ packages:
jsdom:
optional: true
+ volar-service-html@0.0.70:
+ resolution: {integrity: sha512-eR6vCgMdmYAo4n+gcT7DSyBQbwB8S3HZZvSagTf0sxNaD4WppMCFfpqWnkrlGStPKMZvMiejRRVmqsX9dYcTvQ==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-typescript@0.0.70:
+ resolution: {integrity: sha512-l46Bx4cokkUedTd74ojO5H/zqHZJ8SUuyZ0IB8JN4jfRqUM3bQFBHoOwlZCyZmOeO0A3RQNkMnFclxO4c++gsg==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ vscode-html-languageservice@5.6.2:
+ resolution: {integrity: sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==}
+
+ vscode-jsonrpc@8.2.0:
+ resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
+ engines: {node: '>=14.0.0'}
+
+ vscode-languageserver-protocol@3.17.5:
+ resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}
+
+ vscode-languageserver-textdocument@1.0.12:
+ resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==}
+
+ vscode-languageserver-types@3.17.5:
+ resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}
+
+ vscode-languageserver@9.0.1:
+ resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
+ hasBin: true
+
+ vscode-nls@5.2.0:
+ resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==}
+
+ vscode-uri@3.1.0:
+ resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
+
walk-sync@0.3.4:
resolution: {integrity: sha512-ttGcuHA/OBnN2pcM6johpYlEms7XpO5/fyKIr48541xXedan4roO8cS1Q2S/zbbjGH/BarYDAMeS2Mi9HE5Tig==}
@@ -5606,18 +5655,10 @@ snapshots:
js-tokens: 4.0.0
picocolors: 1.1.1
- '@babel/code-frame@7.29.0':
- dependencies:
- '@babel/helper-validator-identifier': 7.28.5
- js-tokens: 4.0.0
- picocolors: 1.1.1
-
'@babel/compat-data@7.26.3': {}
'@babel/compat-data@7.28.5': {}
- '@babel/compat-data@7.29.0': {}
-
'@babel/core@7.26.0':
dependencies:
'@ampproject/remapping': 2.3.0
@@ -5638,26 +5679,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/core@7.29.0':
- dependencies:
- '@babel/code-frame': 7.29.0
- '@babel/generator': 7.29.1
- '@babel/helper-compilation-targets': 7.28.6
- '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
- '@babel/helpers': 7.29.2
- '@babel/parser': 7.29.2
- '@babel/template': 7.28.6
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- '@jridgewell/remapping': 2.3.5
- convert-source-map: 2.0.0
- debug: 4.4.3
- gensync: 1.0.0-beta.2
- json5: 2.2.3
- semver: 6.3.1
- transitivePeerDependencies:
- - supports-color
-
'@babel/eslint-parser@7.28.6(@babel/core@7.26.0)(eslint@8.57.1)':
dependencies:
'@babel/core': 7.26.0
@@ -5674,14 +5695,6 @@ snapshots:
eslint-visitor-keys: 2.1.0
semver: 6.3.1
- '@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1)':
- dependencies:
- '@babel/core': 7.29.0
- '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1
- eslint: 8.57.1
- eslint-visitor-keys: 2.1.0
- semver: 6.3.1
-
'@babel/generator@7.26.3':
dependencies:
'@babel/parser': 7.26.3
@@ -5698,14 +5711,6 @@ snapshots:
'@jridgewell/trace-mapping': 0.3.31
jsesc: 3.1.0
- '@babel/generator@7.29.1':
- dependencies:
- '@babel/parser': 7.29.2
- '@babel/types': 7.29.0
- '@jridgewell/gen-mapping': 0.3.13
- '@jridgewell/trace-mapping': 0.3.31
- jsesc: 3.1.0
-
'@babel/helper-annotate-as-pure@7.25.9':
dependencies:
'@babel/types': 7.26.3
@@ -5726,14 +5731,6 @@ snapshots:
lru-cache: 5.1.1
semver: 6.3.1
- '@babel/helper-compilation-targets@7.28.6':
- dependencies:
- '@babel/compat-data': 7.29.0
- '@babel/helper-validator-option': 7.27.1
- browserslist: 4.28.1
- lru-cache: 5.1.1
- semver: 6.3.1
-
'@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -5747,19 +5744,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-annotate-as-pure': 7.25.9
- '@babel/helper-member-expression-to-functions': 7.25.9
- '@babel/helper-optimise-call-expression': 7.25.9
- '@babel/helper-replace-supers': 7.25.9(@babel/core@7.29.0)
- '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
- '@babel/traverse': 7.26.4
- semver: 6.3.1
- transitivePeerDependencies:
- - supports-color
-
'@babel/helper-create-regexp-features-plugin@7.26.3(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -5801,13 +5785,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/helper-module-imports@7.28.6':
- dependencies:
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
- transitivePeerDependencies:
- - supports-color
-
'@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -5817,15 +5794,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-module-imports': 7.28.6
- '@babel/helper-validator-identifier': 7.28.5
- '@babel/traverse': 7.29.0
- transitivePeerDependencies:
- - supports-color
-
'@babel/helper-optimise-call-expression@7.25.9':
dependencies:
'@babel/types': 7.26.3
@@ -5852,15 +5820,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/helper-replace-supers@7.25.9(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-member-expression-to-functions': 7.25.9
- '@babel/helper-optimise-call-expression': 7.25.9
- '@babel/traverse': 7.26.4
- transitivePeerDependencies:
- - supports-color
-
'@babel/helper-skip-transparent-expression-wrappers@7.25.9':
dependencies:
'@babel/traverse': 7.26.4
@@ -5893,11 +5852,6 @@ snapshots:
'@babel/template': 7.25.9
'@babel/types': 7.26.3
- '@babel/helpers@7.29.2':
- dependencies:
- '@babel/template': 7.28.6
- '@babel/types': 7.29.0
-
'@babel/parser@7.26.3':
dependencies:
'@babel/types': 7.26.3
@@ -5906,10 +5860,6 @@ snapshots:
dependencies:
'@babel/types': 7.28.5
- '@babel/parser@7.29.2':
- dependencies:
- '@babel/types': 7.29.0
-
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -5962,15 +5912,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/plugin-proposal-decorators@7.25.9(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.29.0)
- '@babel/helper-plugin-utils': 7.25.9
- '@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.29.0)
- transitivePeerDependencies:
- - supports-color
-
'@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -5998,11 +5939,6 @@ snapshots:
'@babel/core': 7.26.0
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-plugin-utils': 7.27.1
-
'@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -6023,11 +5959,6 @@ snapshots:
'@babel/core': 7.26.0
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-plugin-utils': 7.27.1
-
'@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -6362,15 +6293,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-typescript@7.5.5(@babel/core@7.29.0)':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.29.0)
- '@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.29.0)
- transitivePeerDependencies:
- - supports-color
-
'@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -6501,12 +6423,6 @@ snapshots:
'@babel/parser': 7.28.5
'@babel/types': 7.28.5
- '@babel/template@7.28.6':
- dependencies:
- '@babel/code-frame': 7.29.0
- '@babel/parser': 7.29.2
- '@babel/types': 7.29.0
-
'@babel/traverse@7.26.4':
dependencies:
'@babel/code-frame': 7.26.2
@@ -6514,7 +6430,7 @@ snapshots:
'@babel/parser': 7.26.3
'@babel/template': 7.25.9
'@babel/types': 7.26.3
- debug: 4.4.0
+ debug: 4.4.3
globals: 11.12.0
transitivePeerDependencies:
- supports-color
@@ -6531,18 +6447,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/traverse@7.29.0':
- dependencies:
- '@babel/code-frame': 7.29.0
- '@babel/generator': 7.29.1
- '@babel/helper-globals': 7.28.0
- '@babel/parser': 7.29.2
- '@babel/template': 7.28.6
- '@babel/types': 7.29.0
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
'@babel/types@7.26.3':
dependencies:
'@babel/helper-string-parser': 7.25.9
@@ -6553,11 +6457,6 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
- '@babel/types@7.29.0':
- dependencies:
- '@babel/helper-string-parser': 7.27.1
- '@babel/helper-validator-identifier': 7.28.5
-
'@ember-data/rfc395-data@0.0.4': {}
'@ember/edition-utils@1.2.0': {}
@@ -6604,6 +6503,21 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@embroider/macros@1.16.10(@glint/template@1.7.4)':
+ dependencies:
+ '@embroider/shared-internals': 2.8.1
+ assert-never: 1.4.0
+ babel-import-util: 2.1.1
+ ember-cli-babel: 7.26.11
+ find-up: 5.0.0
+ lodash: 4.17.21
+ resolve: 1.22.10
+ semver: 7.6.3
+ optionalDependencies:
+ '@glint/template': 1.7.4
+ transitivePeerDependencies:
+ - supports-color
+
'@embroider/shared-internals@2.8.1':
dependencies:
babel-import-util: 2.1.1
@@ -6639,18 +6553,18 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@emnapi/core@1.9.1':
+ '@emnapi/core@1.9.2':
dependencies:
- '@emnapi/wasi-threads': 1.2.0
+ '@emnapi/wasi-threads': 1.2.1
tslib: 2.8.1
optional: true
- '@emnapi/runtime@1.9.1':
+ '@emnapi/runtime@1.9.2':
dependencies:
tslib: 2.8.1
optional: true
- '@emnapi/wasi-threads@1.2.0':
+ '@emnapi/wasi-threads@1.2.1':
dependencies:
tslib: 2.8.1
optional: true
@@ -6826,29 +6740,9 @@ snapshots:
- '@babel/core'
- supports-color
- '@glimmer/component@1.1.2(@babel/core@7.29.0)':
+ '@glimmer/component@2.0.0':
dependencies:
- '@glimmer/di': 0.1.11
- '@glimmer/env': 0.1.7
- '@glimmer/util': 0.44.0
- broccoli-file-creator: 2.1.1
- broccoli-merge-trees: 3.0.2
- ember-cli-babel: 7.26.11
- ember-cli-get-component-path-option: 1.0.0
- ember-cli-is-package-missing: 1.0.0
- ember-cli-normalize-entity-name: 1.0.0
- ember-cli-path-utils: 1.0.0
- ember-cli-string-utils: 1.1.0
- ember-cli-typescript: 3.0.0(@babel/core@7.29.0)
- ember-cli-version-checker: 3.1.3
- ember-compatibility-helpers: 1.2.7(@babel/core@7.29.0)
- transitivePeerDependencies:
- - '@babel/core'
- - supports-color
-
- '@glimmer/component@2.0.0':
- dependencies:
- '@embroider/addon-shim': 1.10.2
+ '@embroider/addon-shim': 1.10.2
'@glimmer/env': 0.1.7
transitivePeerDependencies:
- supports-color
@@ -6980,7 +6874,7 @@ snapshots:
'@glimmer/interfaces': 0.94.6
'@glimmer/util': 0.94.8
'@glimmer/wire-format': 0.94.8
- '@handlebars/parser': 2.2.2
+ '@handlebars/parser': 2.2.1
simple-html-tokenizer: 0.5.11
'@glimmer/tracking@1.1.2':
@@ -7034,11 +6928,35 @@ snapshots:
dependencies:
'@glimmer/interfaces': 0.94.6
+ '@glint/ember-tsc@1.1.1(typescript@5.7.2)':
+ dependencies:
+ '@glimmer/syntax': 0.95.0
+ '@glint/template': 1.7.4
+ '@volar/kit': 2.4.28(typescript@5.7.2)
+ '@volar/language-core': 2.4.28
+ '@volar/language-server': 2.4.28
+ '@volar/language-service': 2.4.28
+ '@volar/source-map': 2.4.28
+ '@volar/test-utils': 2.4.28
+ '@volar/typescript': 2.4.28
+ content-tag: 3.1.3
+ silent-error: 1.1.1
+ typescript: 5.7.2
+ volar-service-html: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-typescript: 0.0.70(@volar/language-service@2.4.28)
+ vscode-languageserver-protocol: 3.17.5
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+ transitivePeerDependencies:
+ - supports-color
+
'@glint/template@1.5.0': {}
+ '@glint/template@1.7.4': {}
+
'@handlebars/parser@2.0.0': {}
- '@handlebars/parser@2.2.2': {}
+ '@handlebars/parser@2.2.1': {}
'@humanfs/core@0.19.1': {}
@@ -7087,11 +7005,6 @@ snapshots:
'@jridgewell/sourcemap-codec': 1.5.0
'@jridgewell/trace-mapping': 0.3.25
- '@jridgewell/remapping@2.3.5':
- dependencies:
- '@jridgewell/gen-mapping': 0.3.13
- '@jridgewell/trace-mapping': 0.3.31
-
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/set-array@1.2.1': {}
@@ -7131,10 +7044,10 @@ snapshots:
jju: 1.4.0
read-yaml-file: 1.1.0
- '@napi-rs/wasm-runtime@1.1.1':
+ '@napi-rs/wasm-runtime@1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
dependencies:
- '@emnapi/core': 1.9.1
- '@emnapi/runtime': 1.9.1
+ '@emnapi/core': 1.9.2
+ '@emnapi/runtime': 1.9.2
'@tybys/wasm-util': 0.10.1
optional: true
@@ -7305,9 +7218,12 @@ snapshots:
'@oxc-parser/binding-openharmony-arm64@0.119.0':
optional: true
- '@oxc-parser/binding-wasm32-wasi@0.119.0':
+ '@oxc-parser/binding-wasm32-wasi@0.119.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
dependencies:
- '@napi-rs/wasm-runtime': 1.1.1
+ '@napi-rs/wasm-runtime': 1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
optional: true
'@oxc-parser/binding-win32-arm64-msvc@0.119.0':
@@ -7445,7 +7361,7 @@ snapshots:
dependencies:
undici-types: 6.20.0
- '@types/node@25.5.0':
+ '@types/node@25.3.3':
dependencies:
undici-types: 7.18.2
@@ -7507,19 +7423,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.2)':
- dependencies:
- '@typescript-eslint/scope-manager': 7.18.0
- '@typescript-eslint/types': 7.18.0
- '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.7.2)
- '@typescript-eslint/visitor-keys': 7.18.0
- debug: 4.4.3
- eslint: 8.57.1
- optionalDependencies:
- typescript: 5.7.2
- transitivePeerDependencies:
- - supports-color
-
'@typescript-eslint/parser@8.19.1(eslint@8.57.1)(typescript@5.7.2)':
dependencies:
'@typescript-eslint/scope-manager': 8.19.1
@@ -7556,43 +7459,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/scope-manager': 8.46.4
- '@typescript-eslint/types': 8.46.4
- '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.46.4
- debug: 4.4.3
- eslint: 8.57.1
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
- optional: true
-
'@typescript-eslint/project-service@8.46.4(typescript@5.7.2)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.7.2)
+ '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.7.2)
'@typescript-eslint/types': 8.46.4
debug: 4.4.3
typescript: 5.7.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.46.4(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3)
- '@typescript-eslint/types': 8.46.4
- debug: 4.4.3
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
- optional: true
-
- '@typescript-eslint/scope-manager@7.18.0':
- dependencies:
- '@typescript-eslint/types': 7.18.0
- '@typescript-eslint/visitor-keys': 7.18.0
-
'@typescript-eslint/scope-manager@8.19.1':
dependencies:
'@typescript-eslint/types': 8.19.1
@@ -7607,12 +7482,7 @@ snapshots:
dependencies:
typescript: 5.7.2
- '@typescript-eslint/tsconfig-utils@8.46.4(typescript@5.9.3)':
- dependencies:
- typescript: 5.9.3
- optional: true
-
- '@typescript-eslint/tsconfig-utils@8.57.1(typescript@5.7.2)':
+ '@typescript-eslint/tsconfig-utils@8.58.1(typescript@5.7.2)':
dependencies:
typescript: 5.7.2
@@ -7650,27 +7520,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@7.18.0': {}
-
'@typescript-eslint/types@8.19.1': {}
'@typescript-eslint/types@8.46.4': {}
- '@typescript-eslint/typescript-estree@7.18.0(typescript@5.7.2)':
- dependencies:
- '@typescript-eslint/types': 7.18.0
- '@typescript-eslint/visitor-keys': 7.18.0
- debug: 4.4.3
- globby: 11.1.0
- is-glob: 4.0.3
- minimatch: 9.0.5
- semver: 7.6.3
- ts-api-utils: 1.4.3(typescript@5.7.2)
- optionalDependencies:
- typescript: 5.7.2
- transitivePeerDependencies:
- - supports-color
-
'@typescript-eslint/typescript-estree@8.19.1(typescript@5.7.2)':
dependencies:
'@typescript-eslint/types': 8.19.1
@@ -7701,23 +7554,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/typescript-estree@8.46.4(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/project-service': 8.46.4(typescript@5.9.3)
- '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3)
- '@typescript-eslint/types': 8.46.4
- '@typescript-eslint/visitor-keys': 8.46.4
- debug: 4.4.3
- fast-glob: 3.3.3
- is-glob: 4.0.3
- minimatch: 9.0.5
- semver: 7.6.3
- ts-api-utils: 2.1.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
- optional: true
-
'@typescript-eslint/utils@8.19.1(eslint@8.57.1)(typescript@5.7.2)':
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1)
@@ -7751,11 +7587,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/visitor-keys@7.18.0':
- dependencies:
- '@typescript-eslint/types': 7.18.0
- eslint-visitor-keys: 3.4.3
-
'@typescript-eslint/visitor-keys@8.19.1':
dependencies:
'@typescript-eslint/types': 8.19.1
@@ -7797,6 +7628,55 @@ snapshots:
loupe: 2.3.7
pretty-format: 29.7.0
+ '@volar/kit@2.4.28(typescript@5.7.2)':
+ dependencies:
+ '@volar/language-service': 2.4.28
+ '@volar/typescript': 2.4.28
+ typesafe-path: 0.2.2
+ typescript: 5.7.2
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/language-core@2.4.28':
+ dependencies:
+ '@volar/source-map': 2.4.28
+
+ '@volar/language-server@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ '@volar/language-service': 2.4.28
+ '@volar/typescript': 2.4.28
+ path-browserify: 1.0.1
+ request-light: 0.7.0
+ vscode-languageserver: 9.0.1
+ vscode-languageserver-protocol: 3.17.5
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/language-service@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ vscode-languageserver-protocol: 3.17.5
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/source-map@2.4.28': {}
+
+ '@volar/test-utils@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ '@volar/language-server': 2.4.28
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/typescript@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ path-browserify: 1.0.1
+ vscode-uri: 3.1.0
+
+ '@vscode/l10n@0.0.18': {}
+
'@webassemblyjs/ast@1.14.1':
dependencies:
'@webassemblyjs/helper-numbers': 1.13.2
@@ -8131,11 +8011,6 @@ snapshots:
'@babel/core': 7.26.0
semver: 5.7.2
- babel-plugin-debug-macros@0.2.0(@babel/core@7.29.0):
- dependencies:
- '@babel/core': 7.29.0
- semver: 5.7.2
-
babel-plugin-debug-macros@0.3.4(@babel/core@7.26.0):
dependencies:
'@babel/core': 7.26.0
@@ -8222,7 +8097,7 @@ snapshots:
balanced-match@1.0.2: {}
- baseline-browser-mapping@2.10.9: {}
+ baseline-browser-mapping@2.10.0: {}
baseline-browser-mapping@2.8.27: {}
@@ -8441,10 +8316,10 @@ snapshots:
browserslist@4.28.1:
dependencies:
- baseline-browser-mapping: 2.10.9
- caniuse-lite: 1.0.30001780
- electron-to-chromium: 1.5.321
- node-releases: 2.0.36
+ baseline-browser-mapping: 2.10.0
+ caniuse-lite: 1.0.30001775
+ electron-to-chromium: 1.5.302
+ node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
buffer-from@1.1.2: {}
@@ -8525,7 +8400,7 @@ snapshots:
caniuse-lite@1.0.30001754: {}
- caniuse-lite@1.0.30001780: {}
+ caniuse-lite@1.0.30001775: {}
chai@4.5.0:
dependencies:
@@ -8612,6 +8487,8 @@ snapshots:
ini: 1.3.8
proto-list: 1.2.4
+ content-tag@3.1.3: {}
+
content-tag@4.1.1: {}
convert-source-map@2.0.0: {}
@@ -8649,7 +8526,7 @@ snapshots:
css-tree@3.1.0:
dependencies:
mdn-data: 2.12.2
- source-map-js: 1.0.2
+ source-map-js: 1.2.1
cssesc@3.0.0: {}
@@ -8745,7 +8622,7 @@ snapshots:
dot-case@3.0.4:
dependencies:
no-case: 3.0.4
- tslib: 2.6.2
+ tslib: 2.8.1
dunder-proto@1.0.1:
dependencies:
@@ -8764,7 +8641,7 @@ snapshots:
electron-to-chromium@1.5.250: {}
- electron-to-chromium@1.5.321: {}
+ electron-to-chromium@1.5.302: {}
electron-to-chromium@1.5.78: {}
@@ -8811,6 +8688,49 @@ snapshots:
- supports-color
- webpack
+ ember-auto-import@2.10.0(@glint/template@1.7.4)(webpack@5.94.0):
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.26.0)
+ '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.26.0)
+ '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.0)
+ '@babel/preset-env': 7.26.0(@babel/core@7.26.0)
+ '@embroider/macros': 1.16.10(@glint/template@1.7.4)
+ '@embroider/shared-internals': 2.8.1
+ babel-loader: 8.4.1(@babel/core@7.26.0)(webpack@5.94.0)
+ babel-plugin-ember-modules-api-polyfill: 3.5.0
+ babel-plugin-ember-template-compilation: 2.3.0
+ babel-plugin-htmlbars-inline-precompile: 5.3.1
+ babel-plugin-syntax-dynamic-import: 6.18.0
+ broccoli-debug: 0.6.5
+ broccoli-funnel: 3.0.8
+ broccoli-merge-trees: 4.2.0
+ broccoli-plugin: 4.0.7
+ broccoli-source: 3.0.1
+ css-loader: 5.2.7(webpack@5.94.0)
+ debug: 4.4.3
+ fs-extra: 10.1.0
+ fs-tree-diff: 2.0.1
+ handlebars: 4.7.8
+ is-subdir: 1.2.0
+ js-string-escape: 1.0.1
+ lodash: 4.17.21
+ mini-css-extract-plugin: 2.9.2(webpack@5.94.0)
+ minimatch: 3.1.2
+ parse5: 6.0.1
+ pkg-entry-points: 1.1.1
+ resolve: 1.22.10
+ resolve-package-path: 4.0.3
+ semver: 7.6.3
+ style-loader: 2.0.0(webpack@5.94.0)
+ typescript-memoize: 1.1.1
+ walk-sync: 3.0.0
+ transitivePeerDependencies:
+ - '@glint/template'
+ - supports-color
+ - webpack
+
ember-cli-babel-plugin-helpers@1.1.1: {}
ember-cli-babel@7.26.11:
@@ -8919,23 +8839,6 @@ snapshots:
- '@babel/core'
- supports-color
- ember-cli-typescript@3.0.0(@babel/core@7.29.0):
- dependencies:
- '@babel/plugin-transform-typescript': 7.5.5(@babel/core@7.29.0)
- ansi-to-html: 0.6.15
- debug: 4.4.3
- ember-cli-babel-plugin-helpers: 1.1.1
- execa: 2.1.0
- fs-extra: 8.1.0
- resolve: 1.22.10
- rsvp: 4.8.5
- semver: 6.3.1
- stagehand: 1.0.1
- walk-sync: 2.2.0
- transitivePeerDependencies:
- - '@babel/core'
- - supports-color
-
ember-cli-version-checker@3.1.3:
dependencies:
resolve-package-path: 1.2.7
@@ -8968,24 +8871,16 @@ snapshots:
- '@babel/core'
- supports-color
- ember-compatibility-helpers@1.2.7(@babel/core@7.29.0):
- dependencies:
- babel-plugin-debug-macros: 0.2.0(@babel/core@7.29.0)
- ember-cli-version-checker: 5.1.2
- find-up: 5.0.0
- fs-extra: 9.1.0
- semver: 5.7.2
- transitivePeerDependencies:
- - '@babel/core'
- - supports-color
-
- ember-estree@0.4.2:
+ ember-estree@0.4.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2):
dependencies:
'@glimmer/env': 0.1.7
'@glimmer/syntax': 0.95.0
content-tag: 4.1.1
- oxc-parser: 0.119.0
+ oxc-parser: 0.119.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
zimmerframe: 1.1.4
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
ember-rfc176-data@0.3.18: {}
@@ -9047,57 +8942,7 @@ snapshots:
- supports-color
- webpack
- ember-source@5.12.0(@glimmer/component@1.1.2(@babel/core@7.29.0))(@glint/template@1.5.0)(rsvp@4.8.5)(webpack@5.94.0):
- dependencies:
- '@babel/core': 7.26.0
- '@ember/edition-utils': 1.2.0
- '@glimmer/compiler': 0.92.4
- '@glimmer/component': 1.1.2(@babel/core@7.29.0)
- '@glimmer/destroyable': 0.92.3
- '@glimmer/env': 0.1.7
- '@glimmer/global-context': 0.92.3
- '@glimmer/interfaces': 0.92.3
- '@glimmer/manager': 0.92.4
- '@glimmer/node': 0.92.4
- '@glimmer/opcode-compiler': 0.92.4
- '@glimmer/owner': 0.92.3
- '@glimmer/program': 0.92.4
- '@glimmer/reference': 0.92.3
- '@glimmer/runtime': 0.92.4
- '@glimmer/syntax': 0.92.3
- '@glimmer/util': 0.92.3
- '@glimmer/validator': 0.92.3
- '@glimmer/vm': 0.92.3
- '@glimmer/vm-babel-plugins': 0.92.3(@babel/core@7.26.0)
- '@simple-dom/interface': 1.4.0
- backburner.js: 2.8.0
- broccoli-file-creator: 2.1.1
- broccoli-funnel: 3.0.8
- broccoli-merge-trees: 4.2.0
- chalk: 4.1.2
- ember-auto-import: 2.10.0(@glint/template@1.5.0)(webpack@5.94.0)
- ember-cli-babel: 8.2.0(@babel/core@7.26.0)
- ember-cli-get-component-path-option: 1.0.0
- ember-cli-is-package-missing: 1.0.0
- ember-cli-normalize-entity-name: 1.0.0
- ember-cli-path-utils: 1.0.0
- ember-cli-string-utils: 1.1.0
- ember-cli-typescript-blueprint-polyfill: 0.1.0
- ember-cli-version-checker: 5.1.2
- ember-router-generator: 2.0.0
- inflection: 2.0.1
- route-recognizer: 0.3.4
- router_js: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5)
- semver: 7.6.3
- silent-error: 1.1.1
- simple-html-tokenizer: 0.5.11
- transitivePeerDependencies:
- - '@glint/template'
- - rsvp
- - supports-color
- - webpack
-
- ember-source@6.1.0(@glimmer/component@2.0.0)(@glint/template@1.5.0)(rsvp@4.8.5)(webpack@5.94.0):
+ ember-source@6.1.0(@glimmer/component@2.0.0)(@glint/template@1.7.4)(rsvp@4.8.5)(webpack@5.94.0):
dependencies:
'@babel/core': 7.26.0
'@ember/edition-utils': 1.2.0
@@ -9126,7 +8971,7 @@ snapshots:
broccoli-funnel: 3.0.8
broccoli-merge-trees: 4.2.0
chalk: 4.1.2
- ember-auto-import: 2.10.0(@glint/template@1.5.0)(webpack@5.94.0)
+ ember-auto-import: 2.10.0(@glint/template@1.7.4)(webpack@5.94.0)
ember-cli-babel: 8.2.0(@babel/core@7.26.0)
ember-cli-get-component-path-option: 1.0.0
ember-cli-is-package-missing: 1.0.0
@@ -9168,7 +9013,7 @@ snapshots:
graceful-fs: 4.2.11
tapable: 2.2.1
- enhanced-resolve@5.20.1:
+ enhanced-resolve@5.20.0:
dependencies:
graceful-fs: 4.2.11
tapable: 2.3.0
@@ -9418,10 +9263,10 @@ snapshots:
dependencies:
eslint: 9.17.0
- eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint-plugin-n@16.6.2(eslint@8.57.1))(eslint-plugin-promise@6.6.0(eslint@8.57.1))(eslint@8.57.1):
+ eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1))(eslint-plugin-n@16.6.2(eslint@8.57.1))(eslint-plugin-promise@6.6.0(eslint@8.57.1))(eslint@8.57.1):
dependencies:
eslint: 8.57.1
- eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
+ eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)
eslint-plugin-n: 16.6.2(eslint@8.57.1)
eslint-plugin-promise: 6.6.0(eslint@8.57.1)
@@ -9433,16 +9278,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1):
- dependencies:
- debug: 3.2.7
- optionalDependencies:
- '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.2)
- eslint: 8.57.1
- eslint-import-resolver-node: 0.3.9
- transitivePeerDependencies:
- - supports-color
-
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.19.1(eslint@9.17.0)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint@9.17.0):
dependencies:
debug: 3.2.7
@@ -9495,22 +9330,6 @@ snapshots:
optionalDependencies:
'@typescript-eslint/parser': 8.46.4(eslint@8.57.1)(typescript@5.7.2)
- eslint-plugin-ember@12.3.3(@typescript-eslint/parser@8.46.4(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1):
- dependencies:
- '@ember-data/rfc395-data': 0.0.4
- css-tree: 3.1.0
- ember-eslint-parser: 'link:'
- ember-rfc176-data: 0.3.18
- eslint: 8.57.1
- eslint-utils: 3.0.0(eslint@8.57.1)
- estraverse: 5.3.0
- lodash.camelcase: 4.3.0
- lodash.kebabcase: 4.1.1
- requireindex: 1.2.0
- snake-case: 3.0.4
- optionalDependencies:
- '@typescript-eslint/parser': 8.46.4(eslint@8.57.1)(typescript@5.9.3)
-
eslint-plugin-es-x@7.8.0(eslint@8.57.1):
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1)
@@ -9525,35 +9344,6 @@ snapshots:
eslint: 9.17.0
eslint-compat-utils: 0.5.1(eslint@9.17.0)
- eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1):
- dependencies:
- '@rtsao/scc': 1.1.0
- array-includes: 3.1.8
- array.prototype.findlastindex: 1.2.5
- array.prototype.flat: 1.3.2
- array.prototype.flatmap: 1.3.2
- debug: 3.2.7
- doctrine: 2.1.0
- eslint: 8.57.1
- eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1)
- hasown: 2.0.2
- is-core-module: 2.16.1
- is-glob: 4.0.3
- minimatch: 3.1.2
- object.fromentries: 2.0.8
- object.groupby: 1.0.3
- object.values: 1.2.1
- semver: 6.3.1
- string.prototype.trimend: 1.0.9
- tsconfig-paths: 3.15.0
- optionalDependencies:
- '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.2)
- transitivePeerDependencies:
- - eslint-import-resolver-typescript
- - eslint-import-resolver-webpack
- - supports-color
-
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0):
dependencies:
'@rtsao/scc': 1.1.0
@@ -9802,7 +9592,7 @@ snapshots:
estree-walker@3.0.3:
dependencies:
- '@types/estree': 1.0.6
+ '@types/estree': 1.0.8
esutils@2.0.3: {}
@@ -10656,7 +10446,7 @@ snapshots:
jest-worker@27.5.1:
dependencies:
- '@types/node': 25.5.0
+ '@types/node': 25.3.3
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -10982,14 +10772,12 @@ snapshots:
no-case@3.0.4:
dependencies:
lower-case: 2.0.2
- tslib: 2.6.2
+ tslib: 2.8.1
node-releases@2.0.19: {}
node-releases@2.0.27: {}
- node-releases@2.0.36: {}
-
npm-bundled@2.0.1:
dependencies:
npm-normalize-package-bin: 2.0.0
@@ -11115,7 +10903,7 @@ snapshots:
object-keys: 1.1.1
safe-push-apply: 1.0.0
- oxc-parser@0.119.0:
+ oxc-parser@0.119.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2):
dependencies:
'@oxc-project/types': 0.119.0
optionalDependencies:
@@ -11135,10 +10923,13 @@ snapshots:
'@oxc-parser/binding-linux-x64-gnu': 0.119.0
'@oxc-parser/binding-linux-x64-musl': 0.119.0
'@oxc-parser/binding-openharmony-arm64': 0.119.0
- '@oxc-parser/binding-wasm32-wasi': 0.119.0
+ '@oxc-parser/binding-wasm32-wasi': 0.119.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
'@oxc-parser/binding-win32-arm64-msvc': 0.119.0
'@oxc-parser/binding-win32-ia32-msvc': 0.119.0
'@oxc-parser/binding-win32-x64-msvc': 0.119.0
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
p-finally@2.0.1: {}
@@ -11211,6 +11002,8 @@ snapshots:
parse5@6.0.1: {}
+ path-browserify@1.0.1: {}
+
path-exists@3.0.0: {}
path-exists@4.0.0: {}
@@ -11366,6 +11159,10 @@ snapshots:
rimraf: 2.7.1
underscore.string: 3.3.6
+ randombytes@2.1.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
rc@1.2.8:
dependencies:
deep-extend: 0.6.0
@@ -11488,6 +11285,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ request-light@0.7.0: {}
+
require-directory@2.1.1: {}
require-from-string@2.0.2: {}
@@ -11620,6 +11419,8 @@ snapshots:
has-symbols: 1.1.0
isarray: 2.0.5
+ safe-buffer@5.2.1: {}
+
safe-push-apply@1.0.0:
dependencies:
es-errors: 1.3.0
@@ -11680,6 +11481,10 @@ snapshots:
semver@7.7.4: {}
+ serialize-javascript@6.0.2:
+ dependencies:
+ randombytes: 2.1.0
+
set-function-length@1.2.0:
dependencies:
define-data-property: 1.1.4
@@ -11774,7 +11579,7 @@ snapshots:
snake-case@3.0.4:
dependencies:
dot-case: 3.0.4
- tslib: 2.6.2
+ tslib: 2.8.1
socks-proxy-agent@6.2.1:
dependencies:
@@ -11789,8 +11594,6 @@ snapshots:
ip: 2.0.0
smart-buffer: 4.2.0
- source-map-js@1.0.2: {}
-
source-map-js@1.2.1: {}
source-map-support@0.5.21:
@@ -11987,15 +11790,16 @@ snapshots:
mkdirp: 1.0.4
yallist: 4.0.0
- terser-webpack-plugin@5.4.0(webpack@5.94.0):
+ terser-webpack-plugin@5.3.16(webpack@5.94.0):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
jest-worker: 27.5.1
schema-utils: 4.3.3
- terser: 5.46.1
+ serialize-javascript: 6.0.2
+ terser: 5.46.0
webpack: 5.94.0
- terser@5.46.1:
+ terser@5.46.0:
dependencies:
'@jridgewell/source-map': 0.3.11
acorn: 8.16.0
@@ -12044,19 +11848,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
- ts-api-utils@1.4.3(typescript@5.7.2):
- dependencies:
- typescript: 5.7.2
-
ts-api-utils@2.1.0(typescript@5.7.2):
dependencies:
typescript: 5.7.2
- ts-api-utils@2.1.0(typescript@5.9.3):
- dependencies:
- typescript: 5.9.3
- optional: true
-
tsconfig-paths@3.15.0:
dependencies:
'@types/json5': 0.0.29
@@ -12064,8 +11859,6 @@ snapshots:
minimist: 1.2.8
strip-bom: 3.0.0
- tslib@2.6.2: {}
-
tslib@2.8.1: {}
type-check@0.4.0:
@@ -12170,6 +11963,12 @@ snapshots:
possible-typed-array-names: 1.0.0
reflect.getprototypeof: 1.0.10
+ typesafe-path@0.2.2: {}
+
+ typescript-auto-import-cache@0.3.6:
+ dependencies:
+ semver: 7.6.3
+
typescript-eslint@8.19.1(eslint@8.57.1)(typescript@5.7.2):
dependencies:
'@typescript-eslint/eslint-plugin': 8.19.1(@typescript-eslint/parser@8.19.1(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
@@ -12194,9 +11993,6 @@ snapshots:
typescript@5.7.2: {}
- typescript@5.9.3:
- optional: true
-
ufo@1.5.4: {}
uglify-js@3.19.3:
@@ -12285,13 +12081,13 @@ snapshots:
validate-npm-package-name@6.0.2: {}
- vite-node@1.6.0(@types/node@25.5.0)(terser@5.46.1):
+ vite-node@1.6.0(@types/node@25.3.3)(terser@5.46.0):
dependencies:
cac: 6.7.14
debug: 4.4.3
pathe: 1.1.2
picocolors: 1.1.1
- vite: 5.4.11(@types/node@25.5.0)(terser@5.46.1)
+ vite: 5.4.11(@types/node@25.3.3)(terser@5.46.0)
transitivePeerDependencies:
- '@types/node'
- less
@@ -12303,17 +12099,17 @@ snapshots:
- supports-color
- terser
- vite@5.4.11(@types/node@25.5.0)(terser@5.46.1):
+ vite@5.4.11(@types/node@25.3.3)(terser@5.46.0):
dependencies:
esbuild: 0.21.5
postcss: 8.4.49
rollup: 4.30.1
optionalDependencies:
- '@types/node': 25.5.0
+ '@types/node': 25.3.3
fsevents: 2.3.3
- terser: 5.46.1
+ terser: 5.46.0
- vitest@1.6.0(@types/node@25.5.0)(terser@5.46.1):
+ vitest@1.6.0(@types/node@25.3.3)(terser@5.46.0):
dependencies:
'@vitest/expect': 1.6.0
'@vitest/runner': 1.6.0
@@ -12332,11 +12128,11 @@ snapshots:
strip-literal: 2.1.1
tinybench: 2.9.0
tinypool: 0.8.4
- vite: 5.4.11(@types/node@25.5.0)(terser@5.46.1)
- vite-node: 1.6.0(@types/node@25.5.0)(terser@5.46.1)
+ vite: 5.4.11(@types/node@25.3.3)(terser@5.46.0)
+ vite-node: 1.6.0(@types/node@25.3.3)(terser@5.46.0)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 25.5.0
+ '@types/node': 25.3.3
transitivePeerDependencies:
- less
- lightningcss
@@ -12347,6 +12143,51 @@ snapshots:
- supports-color
- terser
+ volar-service-html@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-html-languageservice: 5.6.2
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-typescript@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ path-browserify: 1.0.1
+ semver: 7.6.3
+ typescript-auto-import-cache: 0.3.6
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-nls: 5.2.0
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ vscode-html-languageservice@5.6.2:
+ dependencies:
+ '@vscode/l10n': 0.0.18
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+
+ vscode-jsonrpc@8.2.0: {}
+
+ vscode-languageserver-protocol@3.17.5:
+ dependencies:
+ vscode-jsonrpc: 8.2.0
+ vscode-languageserver-types: 3.17.5
+
+ vscode-languageserver-textdocument@1.0.12: {}
+
+ vscode-languageserver-types@3.17.5: {}
+
+ vscode-languageserver@9.0.1:
+ dependencies:
+ vscode-languageserver-protocol: 3.17.5
+
+ vscode-nls@5.2.0: {}
+
+ vscode-uri@3.1.0: {}
+
walk-sync@0.3.4:
dependencies:
ensure-posix-path: 1.1.1
@@ -12389,7 +12230,7 @@ snapshots:
acorn-import-attributes: 1.9.5(acorn@8.16.0)
browserslist: 4.28.1
chrome-trace-event: 1.0.4
- enhanced-resolve: 5.20.1
+ enhanced-resolve: 5.20.0
es-module-lexer: 1.7.0
eslint-scope: 5.1.1
events: 3.3.0
@@ -12401,7 +12242,7 @@ snapshots:
neo-async: 2.6.2
schema-utils: 3.3.0
tapable: 2.3.0
- terser-webpack-plugin: 5.4.0(webpack@5.94.0)
+ terser-webpack-plugin: 5.3.16(webpack@5.94.0)
watchpack: 2.5.1
webpack-sources: 3.3.4
transitivePeerDependencies:
diff --git a/src/parser/gjs-gts-parser.js b/src/parser/gjs-gts-parser.js
index b5e16e3..992ae89 100644
--- a/src/parser/gjs-gts-parser.js
+++ b/src/parser/gjs-gts-parser.js
@@ -1,8 +1,25 @@
import { createRequire } from 'node:module';
import tsconfigUtils from '@typescript-eslint/tsconfig-utils';
import { registerParsedFile } from '../preprocessor/noop.js';
-import { patchTs, replaceExtensions, syncMtsGtsSourceFiles, typescriptParser } from './ts-patch.js';
-import { buildGlimmerVisitors } from './transforms.js';
+import {
+ patchTs,
+ replaceExtensions,
+ syncMtsGtsSourceFiles,
+ typescriptParser,
+ ts,
+} from './ts-patch.js';
+import {
+ buildGlimmerVisitors,
+ preprocessGlimmerTemplatesFromCharOffsets,
+ convertAst,
+} from './transforms.js';
+import {
+ isGlintAvailable,
+ getGlintConfig,
+ glintRewriteModule,
+ buildTemplateInfoFromGlint,
+} from './glint-utils.js';
+import { remapAstPositions, remapTokens } from './remap.js';
import { toTree } from 'ember-estree';
import * as eslintScope from 'eslint-scope';
@@ -128,6 +145,102 @@ function getAllowJs(options) {
return false;
}
+/**
+ * Parse using Glint's transform for full type-aware template support.
+ * Glint transforms templates into __glintDSL__ calls that TS understands,
+ * then we remap AST positions back to original source and splice in Glimmer AST.
+ */
+function parseWithGlint(code, options, transformedModule) {
+ const filePath = options.filePath;
+
+ // Get transformed TS code and replace .gts→.mts imports
+ let tsCode = transformedModule.transformedContents;
+ if (options.project || options.projectService) {
+ tsCode = replaceExtensions(tsCode);
+ }
+
+ // Parse the transformed code with TS parser (positions in transformed-space)
+ const result = typescriptParser.parseForESLint(tsCode, {
+ ...options,
+ ranges: true,
+ extraFileExtensions: ['.gts', '.gjs'],
+ filePath,
+ });
+
+ // Build template infos from Glint's correlatedSpans
+ const glintTemplateInfos = buildTemplateInfoFromGlint(transformedModule);
+
+ // Always remap positions even if no templates — Glint may have changed code length
+ // for non-template spans (e.g., directive placeholders)
+ const { templateSpans } = remapAstPositions(
+ result.ast,
+ result.visitorKeys,
+ transformedModule.correlatedSpans,
+ code
+ );
+
+ // Remap tokens
+ result.ast.tokens = remapTokens(
+ result.ast.tokens,
+ transformedModule.correlatedSpans,
+ templateSpans,
+ code
+ );
+
+ if (!glintTemplateInfos.length) {
+ return result;
+ }
+
+ // Preprocess Glimmer templates (parse to Glimmer AST with correct positions)
+ const preprocessedResult = preprocessGlimmerTemplatesFromCharOffsets(glintTemplateInfos, code);
+ const { templateVisitorKeys } = preprocessedResult;
+ const visitorKeys = { ...result.visitorKeys, ...templateVisitorKeys };
+ result.isTypescript = true;
+
+ // Splice Glimmer AST into the remapped TS AST (matchByRangeOnly because
+ // Glint produces different node types than transformForLint)
+ convertAst(result, preprocessedResult, { matchByRangeOnly: true });
+
+ // remapAstPositions marks nodes entirely inside a template span with
+ // __glintOrphaned=true (it skips remapping them since they will be replaced).
+ // After convertAst replaces the static block with the Glimmer AST, those nodes
+ // are gone from the tree — ESLint never traverses them so .parent stays
+ // undefined. Scope entries pointing to them crash rules like no-unused-vars.
+ // Remove those entries; they are Glint DSL artifacts, not user-authored code.
+ if (result.scopeManager && templateSpans.length > 0) {
+ const isOrphanedNode = (node) => node?.__glintOrphaned === true;
+ for (const scope of result.scopeManager.scopes) {
+ // Filter references whose identifier nodes are Glint-orphaned
+ const isOrphanedRef = (ref) => isOrphanedNode(ref.identifier);
+ scope.references = scope.references.filter((ref) => !isOrphanedRef(ref));
+ if (scope.through) {
+ scope.through = scope.through.filter((ref) => !isOrphanedRef(ref));
+ }
+ // Filter variables whose definition identifiers are Glint-orphaned
+ // (Glint DSL vars like __glintY__ are defined inside the template span)
+ const removedVarNames = new Set();
+ scope.variables = scope.variables.filter((variable) => {
+ const isOrphaned = variable.defs.some((def) => isOrphanedNode(def.name));
+ if (isOrphaned) removedVarNames.add(variable.name);
+ return !isOrphaned;
+ });
+ for (const name of removedVarNames) {
+ scope.set?.delete(name);
+ }
+ // Also clean up orphaned references on remaining variables
+ for (const variable of scope.variables) {
+ variable.references = variable.references.filter((ref) => !isOrphanedRef(ref));
+ }
+ }
+ }
+
+ if (result.services?.program) {
+ syncMtsGtsSourceFiles(result.services.program);
+ }
+
+ return { ...result, visitorKeys };
+}
+
/**
* @type {import('eslint').ParserModule}
*/
@@ -137,15 +250,39 @@ export const meta = {
};
export function parseForESLint(code, options) {
- const allowGjsWasSet = options.allowGjs !== undefined;
- const allowGjs = allowGjsWasSet ? options.allowGjs : getAllowJs(options);
- let actualAllowGjs;
+ const allowGjs = options.allowGjs !== undefined ? options.allowGjs : getAllowJs(options);
// Only patch TypeScript if we actually need it.
if (options.programs || options.projectService || options.project) {
- ({ allowGjs: actualAllowGjs } = patchTs({ allowGjs }));
+ patchTs({ allowGjs });
}
registerParsedFile(options.filePath);
+ // Type-aware .gts linting requires Glint. @glint/ember-tsc must be installed and
+ // tsconfig must have an explicit "glint" key. Without Glint, the legacy
+ // transformForLint path cannot produce correct type information for templates.
+ const isGts = options.filePath.endsWith('.gts');
+ const isTypeAware = Boolean(options.project || options.projectService || options.programs);
+ if (isGts && isTypeAware) {
+ if (!isGlintAvailable()) {
+ throw new Error(
+ '[ember-eslint-parser] @glint/ember-tsc is required for type-aware linting of .gts files. ' +
+ 'Install it as a dependency of your project.'
+ );
+ }
+ const glintConfig = getGlintConfig(options.filePath);
+ if (!glintConfig) {
+ throw new Error(
+ '[ember-eslint-parser] No Glint environment found for this .gts file. ' +
+ 'Ensure @glint/ember-tsc is configured in your tsconfig.'
+ );
+ }
+ const glintTransform = glintRewriteModule(code, options.filePath, ts, glintConfig);
+ if (glintTransform) {
+ return parseWithGlint(code, options, glintTransform);
+ }
+ // glintTransform === null means no templates — fall through to normal TS parse
+ }
+
const isTypescript = options.filePath.endsWith('.gts') || options.filePath.endsWith('.ts');
let useTypescript = true;
@@ -202,19 +339,6 @@ export function parseForESLint(code, options) {
if (!result.scopeManager) result.scopeManager = scopeManager;
if (result.services?.program) {
- const programAllowJs = result.services.program.getCompilerOptions?.()?.allowJs;
- if (
- !allowGjsWasSet &&
- programAllowJs !== undefined &&
- actualAllowGjs !== undefined &&
- actualAllowGjs !== programAllowJs
- ) {
- // eslint-disable-next-line no-console
- console.warn(
- '[ember-eslint-parser] allowJs does not match the actual program. Consider setting allowGjs explicitly.\n' +
- ` Current: ${allowGjs}, Program: ${programAllowJs}`
- );
- }
syncMtsGtsSourceFiles(result.services.program);
}
diff --git a/src/parser/glint-utils.js b/src/parser/glint-utils.js
new file mode 100644
index 0000000..efa194b
--- /dev/null
+++ b/src/parser/glint-utils.js
@@ -0,0 +1,113 @@
+import fs from 'node:fs';
+import { createRequire } from 'node:module';
+
+const require = createRequire(import.meta.url);
+
+let glintAvailable = false;
+let rewriteModule, ConfigLoader;
+
+try {
+ ({ rewriteModule } = require('@glint/ember-tsc/transform/index'));
+ ({ ConfigLoader } = require('@glint/ember-tsc/config/index'));
+ glintAvailable = true;
+} catch {
+ // @glint/ember-tsc not installed
+}
+
+const configLoader = glintAvailable ? new ConfigLoader() : null;
+
+/**
+ * @returns {boolean}
+ */
+export function isGlintAvailable() {
+ return glintAvailable;
+}
+
+/**
+ * Returns true if the tsconfig at tsconfigPath has an explicit "glint" section.
+ * Glint's ConfigLoader can auto-detect environments without explicit config, so
+ * we use this check to avoid silently activating Glint for projects that don't
+ * opt in.
+ * @param {string} tsconfigPath
+ * @returns {boolean}
+ */
+function tsconfigHasGlintSection(tsconfigPath) {
+ try {
+ // TypeScript supports JSONC (comments + trailing commas), so use a permissive
+ // parse that strips comments before JSON.parse.
+ const raw = fs.readFileSync(tsconfigPath, 'utf8');
+ // Strip single-line and block comments, trailing commas
+ const stripped = raw
+ .replace(/\/\/.*$/gm, '')
+ .replace(/\/\*[\s\S]*?\*\//g, '')
+ .replace(/,(\s*[}\]])/g, '$1');
+ const parsed = JSON.parse(stripped);
+ return Object.prototype.hasOwnProperty.call(parsed, 'glint');
+ } catch {
+ return false;
+ }
+}
+
+/**
+ * Loads and caches GlintConfig for the project containing filePath.
+ * Returns null if @glint/ember-tsc is not available or no glint
+ * environment is configured in the project's tsconfig.
+ * @param {string} filePath
+ * @returns {import('@glint/ember-tsc').GlintConfig | null}
+ */
+export function getGlintConfig(filePath) {
+ if (!configLoader) return null;
+ try {
+ const config = configLoader.configForFile(filePath);
+ if (!config || config.environment.names.length === 0) return null;
+ // Glint's ConfigLoader can auto-detect environments when @glint/ember-tsc is
+ // installed without the user explicitly configuring it in their tsconfig.
+ // Only activate Glint processing when the tsconfig has an explicit "glint" key.
+ if (!tsconfigHasGlintSection(config.configPath)) return null;
+ return config;
+ } catch {
+ return null;
+ }
+}
+
+/**
+ * Rewrites a .gts/.gjs module using Glint's template-to-TypeScript transform.
+ * Returns TransformedModule or null if no templates found / transform not needed.
+ * @param {string} code - file contents
+ * @param {string} filePath - absolute file path
+ * @param {*} ts - TypeScript instance
+ * @param {import('@glint/ember-tsc').GlintConfig} config - Glint config
+ * @returns {{ transformedContents: string } | null}
+ */
+export function glintRewriteModule(code, filePath, ts, config) {
+ if (!rewriteModule) return null;
+ return rewriteModule(ts, { script: { filename: filePath, contents: code } }, config.environment);
+}
+
+/**
+ * Build template info objects from a Glint TransformedModule's correlatedSpans.
+ * Returns template ranges in character (UTF-16) offsets suitable for
+ * preprocessGlimmerTemplatesFromCharOffsets.
+ *
+ * @param {object} transformedModule - Glint TransformedModule
+ * @returns {Array<{ range: [number, number] }>}
+ */
+export function buildTemplateInfoFromGlint(transformedModule) {
+ const result = [];
+ const seen = new Set();
+ for (const span of transformedModule.correlatedSpans) {
+ if (!span.glimmerAstMapping) continue;
+
+ const fullStart = span.originalStart;
+ // Deduplicate: multiple spans can map to the same original template
+ if (seen.has(fullStart)) continue;
+ seen.add(fullStart);
+
+ const fullEnd = span.originalStart + span.originalLength;
+
+ result.push({
+ range: [fullStart, fullEnd],
+ });
+ }
+ return result;
+}
diff --git a/src/parser/remap.js b/src/parser/remap.js
new file mode 100644
index 0000000..a9e9e99
--- /dev/null
+++ b/src/parser/remap.js
@@ -0,0 +1,204 @@
+import { DocumentLines } from 'ember-estree';
+
+/**
+ * Extract template spans (those with glimmerAstMapping) from correlatedSpans.
+ * @param {Array} correlatedSpans
+ * @returns {Array<{ transformedStart: number, transformedEnd: number, originalStart: number, originalEnd: number, span: object }>}
+ */
+function getTemplateSpans(correlatedSpans) {
+ const result = [];
+ for (const span of correlatedSpans) {
+ if (span.glimmerAstMapping) {
+ result.push({
+ transformedStart: span.transformedStart,
+ transformedEnd: span.transformedStart + span.transformedLength,
+ originalStart: span.originalStart,
+ originalEnd: span.originalStart + span.originalLength,
+ });
+ }
+ }
+ return result;
+}
+
+/**
+ * Map a transformed-space offset back to original-space.
+ * Returns null if the offset is in the interior of a template span
+ * (those nodes will be replaced by Glimmer AST).
+ *
+ * @param {Array} correlatedSpans
+ * @param {Array} templateSpans - precomputed from getTemplateSpans
+ * @param {number} transformedOffset
+ * @returns {number|null}
+ */
+function remapOffset(correlatedSpans, templateSpans, transformedOffset) {
+ // Check if inside a template span
+ for (const tpl of templateSpans) {
+ if (transformedOffset === tpl.transformedStart) {
+ return tpl.originalStart;
+ }
+ if (transformedOffset === tpl.transformedEnd) {
+ return tpl.originalEnd;
+ }
+ if (transformedOffset > tpl.transformedStart && transformedOffset < tpl.transformedEnd) {
+ return null; // interior of template span
+ }
+ }
+
+ // Find the enclosing span and apply linear formula.
+ // Template spans are included but safe: if we reach here, the offset is not at a
+ // template boundary (handled above) and not in the interior (returned null above).
+ // For non-template spans, originalLength === transformedLength, so the formula is a
+ // simple offset shift.
+ for (const span of correlatedSpans) {
+ const spanEnd = span.transformedStart + span.transformedLength;
+ if (transformedOffset >= span.transformedStart && transformedOffset <= spanEnd) {
+ return transformedOffset - span.transformedStart + span.originalStart;
+ }
+ }
+
+ // Past the end of all spans — use last span's end boundary
+ if (correlatedSpans.length > 0) {
+ const last = correlatedSpans[correlatedSpans.length - 1];
+ const lastTransformedEnd = last.transformedStart + last.transformedLength;
+ const lastOriginalEnd = last.originalStart + last.originalLength;
+ if (transformedOffset >= lastTransformedEnd) {
+ return lastOriginalEnd + (transformedOffset - lastTransformedEnd);
+ }
+ }
+
+ return transformedOffset;
+}
+
+/**
+ * Walk the AST and remap all positions from transformed-space to original-space.
+ * Nodes entirely inside a template span are skipped (replaced by Glimmer AST later).
+ *
+ * @param {object} ast - the parsed AST (mutated in-place)
+ * @param {object} visitorKeys - ESLint visitor keys
+ * @param {Array} correlatedSpans
+ * @param {string} originalCode - original source code
+ * @returns {{ templateSpans: Array }}
+ */
+function remapAstPositions(ast, visitorKeys, correlatedSpans, originalCode) {
+ const templateSpans = getTemplateSpans(correlatedSpans);
+ const originalDoc = new DocumentLines(originalCode);
+
+ function remapNode(node) {
+ if (!node || typeof node !== 'object' || !node.range) return;
+
+ const startOriginal = remapOffset(correlatedSpans, templateSpans, node.range[0]);
+ const endOriginal = remapOffset(correlatedSpans, templateSpans, node.range[1]);
+
+ // If both endpoints are inside a template span, skip — will be replaced
+ if (startOriginal === null && endOriginal === null) {
+ node.__glintOrphaned = true;
+ return;
+ }
+
+ // Remap positions. If one end is null (crosses boundary), use the template boundary.
+ let newStart = startOriginal;
+ let newEnd = endOriginal;
+
+ if (newStart === null) {
+ // Start is inside a template span — find the span and use its original start
+ for (const tpl of templateSpans) {
+ if (node.range[0] >= tpl.transformedStart && node.range[0] < tpl.transformedEnd) {
+ newStart = tpl.originalStart;
+ break;
+ }
+ }
+ }
+ if (newEnd === null) {
+ // End is inside a template span — find the span and use its original end
+ for (const tpl of templateSpans) {
+ if (node.range[1] > tpl.transformedStart && node.range[1] <= tpl.transformedEnd) {
+ newEnd = tpl.originalEnd;
+ break;
+ }
+ }
+ }
+
+ // If either endpoint is still null after fallback, skip this node
+ if (newStart === null || newEnd === null) return;
+
+ node.range = [newStart, newEnd];
+ node.start = newStart;
+ node.end = newEnd;
+ node.loc = {
+ start: originalDoc.offsetToPosition(newStart),
+ end: originalDoc.offsetToPosition(newEnd),
+ };
+ }
+
+ // Walk AST and remap all nodes
+ const queue = [ast];
+ while (queue.length > 0) {
+ const node = queue.pop();
+ if (!node || typeof node !== 'object') continue;
+
+ remapNode(node);
+
+ const keys = visitorKeys[node.type] || [];
+ for (const key of keys) {
+ const child = node[key];
+ if (!child) continue;
+ if (Array.isArray(child)) {
+ for (const item of child) {
+ if (item && typeof item === 'object' && item.type) {
+ queue.push(item);
+ }
+ }
+ } else if (child.type) {
+ queue.push(child);
+ }
+ }
+ }
+
+ return { templateSpans };
+}
+
+/**
+ * Remap tokens from transformed-space to original-space.
+ * Tokens inside template spans are discarded (replaced by Glimmer tokens later).
+ *
+ * @param {Array} tokens
+ * @param {Array} correlatedSpans
+ * @param {Array} templateSpans
+ * @param {string} originalCode
+ * @returns {Array} remapped non-template tokens
+ */
+function remapTokens(tokens, correlatedSpans, templateSpans, originalCode) {
+ const originalDoc = new DocumentLines(originalCode);
+ const remapped = [];
+
+ for (const token of tokens) {
+ // Skip tokens entirely within a template span
+ let inTemplate = false;
+ for (const tpl of templateSpans) {
+ if (token.range[0] >= tpl.transformedStart && token.range[1] <= tpl.transformedEnd) {
+ inTemplate = true;
+ break;
+ }
+ }
+ if (inTemplate) continue;
+
+ const newStart = remapOffset(correlatedSpans, templateSpans, token.range[0]);
+ const newEnd = remapOffset(correlatedSpans, templateSpans, token.range[1]);
+
+ if (newStart === null || newEnd === null) continue; // edge case: skip
+
+ token.range = [newStart, newEnd];
+ token.start = newStart;
+ token.end = newEnd;
+ token.loc = {
+ start: { ...originalDoc.offsetToPosition(newStart), index: newStart },
+ end: { ...originalDoc.offsetToPosition(newEnd), index: newEnd },
+ };
+
+ remapped.push(token);
+ }
+
+ return remapped;
+}
+
+export { remapAstPositions, remapTokens };
diff --git a/src/parser/transforms.js b/src/parser/transforms.js
index e9e0c60..52dd0af 100644
--- a/src/parser/transforms.js
+++ b/src/parser/transforms.js
@@ -1,7 +1,11 @@
import { createRequire } from 'node:module';
import { Preprocessor } from 'content-tag';
-import { isKeyword as glimmerIsKeyword } from '@glimmer/syntax';
-import { glimmerVisitorKeys } from 'ember-estree';
+import {
+ traverse as glimmerTraverse,
+ preprocess as glimmerPreprocess,
+ isKeyword as glimmerIsKeyword,
+} from '@glimmer/syntax';
+import { glimmerVisitorKeys, DocumentLines } from 'ember-estree';
import { Reference, Scope, Variable, Definition } from 'eslint-scope';
import htmlTags from 'html-tags';
import svgTags from 'svg-tags';
@@ -172,8 +176,6 @@ export function buildGlimmerVisitors(getScopeManager, isTypescript) {
};
}
-// ── registerGlimmerScopes (fallback for JS/oxc path) ──────────────────
-
function traverse(visitorKeys, node, visitor) {
const allVisitorKeys = { ...visitorKeys, ...glimmerVisitorKeys };
const queue = [];
@@ -219,17 +221,374 @@ function traverse(visitorKeys, node, visitor) {
}
}
+// ── Glint template processing helpers ─────────────────────────────────
+
+function isAlphaNumeric(code) {
+ return (
+ (code >= 65 && code <= 90) ||
+ (code >= 97 && code <= 122) ||
+ (code >= 48 && code <= 57) ||
+ code === 95
+ );
+}
+
+function isWhiteSpaceCode(code) {
+ return code === 32 || code === 9 || code === 10 || code === 13;
+}
+
+function tokenize(template, doc, startOffset) {
+ const tokens = [];
+ let wordStart = -1;
+ function pushToken(value, type, range) {
+ const t = {
+ type,
+ value,
+ range,
+ start: range[0],
+ end: range[1],
+ loc: {
+ start: { ...doc.offsetToPosition(range[0]), index: range[0] },
+ end: { ...doc.offsetToPosition(range[1]), index: range[1] },
+ },
+ };
+ tokens.push(t);
+ }
+ for (let i = 0; i < template.length; i++) {
+ const code = template.charCodeAt(i);
+ if (isAlphaNumeric(code)) {
+ if (wordStart < 0) {
+ wordStart = i;
+ }
+ } else {
+ if (wordStart >= 0) {
+ pushToken(template.slice(wordStart, i), 'word', [startOffset + wordStart, startOffset + i]);
+ wordStart = -1;
+ }
+ if (!isWhiteSpaceCode(code)) {
+ pushToken(template[i], 'Punctuator', [startOffset + i, startOffset + i + 1]);
+ }
+ }
+ }
+ if (wordStart >= 0) {
+ pushToken(template.slice(wordStart), 'word', [
+ startOffset + wordStart,
+ startOffset + template.length,
+ ]);
+ }
+ return tokens;
+}
+
+/**
+ * Traverses a Glimmer AST, sets parent references, and categorizes nodes.
+ * @param {object} ast
+ * @return {{ allNodes: object[], comments: object[], textNodes: object[], emptyTextNodes: object[] }}
+ */
+function collectNodes(ast) {
+ const allNodes = [];
+ const comments = [];
+ const textNodes = [];
+ const emptyTextNodes = [];
+
+ glimmerTraverse(ast, {
+ All(node, path) {
+ node.parent = path.parentNode;
+ allNodes.push(node);
+ if (node.type === 'CommentStatement' || node.type === 'MustacheCommentStatement') {
+ comments.push(node);
+ }
+ if (node.type === 'TextNode') {
+ node.value = node.chars;
+ if (node.value.trim().length !== 0 || (node.parent && node.parent.type === 'AttrNode')) {
+ textNodes.push(node);
+ } else {
+ emptyTextNodes.push(node);
+ }
+ }
+ },
+ });
+
+ return { allNodes, comments, textNodes, emptyTextNodes };
+}
+
+/**
+ * Removes nodes from their parent's children/body/parts arrays.
+ * @param {object[]} nodes
+ */
+function removeFromParent(nodes) {
+ for (const node of nodes) {
+ const children =
+ (node.parent && (node.parent.children || node.parent.body || node.parent.parts)) || [];
+ const idx = children.indexOf(node);
+ if (idx >= 0) {
+ children.splice(idx, 1);
+ }
+ }
+}
+
+/**
+ * Builds the final token stream by filtering out tokens covered by comments
+ * or text nodes, then merging text nodes back in sorted order.
+ * @param {object[]} rawTokens
+ * @param {object[]} comments
+ * @param {object[]} textNodes
+ * @return {object[]}
+ */
+function buildTokenStream(rawTokens, comments, textNodes) {
+ // Build sorted interval arrays for O(log n) exclusion checks
+ const commentIntervals = comments.map((c) => c.range).sort((a, b) => a[0] - b[0]);
+ const textNodeIntervals = textNodes.map((t) => t.range).sort((a, b) => a[0] - b[0]);
+
+ /**
+ * Binary-search: is the token's range fully covered by any interval in `intervals`?
+ * Intervals must be sorted by start offset.
+ * @param {number[]} tokenRange
+ * @param {number[][]} intervals
+ */
+ function isCovered(tokenRange, intervals) {
+ let lo = 0;
+ let hi = intervals.length - 1;
+ while (lo <= hi) {
+ const mid = (lo + hi) >> 1;
+ const iv = intervals[mid];
+ if (iv[0] <= tokenRange[0] && iv[1] >= tokenRange[1]) {
+ return true;
+ }
+ if (iv[0] > tokenRange[0]) {
+ hi = mid - 1;
+ } else {
+ lo = mid + 1;
+ }
+ }
+ return false;
+ }
+
+ // Single-pass filter: drop tokens covered by a comment or text node
+ const filteredTokens = rawTokens.filter(
+ (t) => !isCovered(t.range, commentIntervals) && !isCovered(t.range, textNodeIntervals)
+ );
+
+ // Merge text nodes (already sorted by position from the AST) into filteredTokens
+ // using a single linear merge pass instead of repeated splice calls.
+ const sortedTextNodes = [...textNodes].sort((a, b) => a.range[0] - b.range[0]);
+ const result = [];
+ let ti = 0;
+ for (const token of filteredTokens) {
+ while (ti < sortedTextNodes.length && sortedTextNodes[ti].range[0] < token.range[0]) {
+ result.push(sortedTextNodes[ti++]);
+ }
+ result.push(token);
+ }
+ while (ti < sortedTextNodes.length) {
+ result.push(sortedTextNodes[ti++]);
+ }
+
+ return result;
+}
+
/**
- * Full AST traversal for scope registration — used as fallback for JS/oxc path.
- * For the TS path, toTree's visitor API handles this during splicing.
+ * Parses a Glimmer template and produces a processed AST ready for ESLint.
+ * Shared between hbs-parser (standalone .hbs files) and gjs/gts parser (embedded templates).
+ *
+ * @param {object} options
+ * @param {string} options.templateContent - The template string to parse with glimmer
+ * @param {DocumentLines} options.codeLines - DocumentLines for the full source file
+ * @param {[number, number]} options.templateRange - Range [start, end] for the Template root node
+ * @param {string} [options.tokenSource] - String to tokenize (defaults to templateContent)
+ * @return {{ ast: object, comments: object[] }}
*/
-export function registerGlimmerScopes(result) {
+function processGlimmerTemplate({ templateContent, codeLines, templateRange, tokenSource }) {
+ const offset = templateRange[0];
+ const docLines = new DocumentLines(templateContent);
+
+ /** Convert a Glimmer loc to a file-level [start, end] range */
+ const toFileRange = (loc) => [
+ offset + docLines.positionToOffset(loc.start),
+ offset + docLines.positionToOffset(loc.end),
+ ];
+ /** Convert a file-level range to a file-level loc */
+ const toFileLoc = (range) => ({
+ start: codeLines.offsetToPosition(range[0]),
+ end: codeLines.offsetToPosition(range[1]),
+ });
+
+ const ast = glimmerPreprocess(templateContent, { mode: 'codemod' });
+ const { allNodes, comments, textNodes, emptyTextNodes } = collectNodes(ast);
+
+ // Fix ranges, locs, and prefix types with "Glimmer"
+ for (const n of allNodes) {
+ if (n.type === 'PathExpression') {
+ n.head.range = toFileRange(n.head.loc);
+ n.head.loc = toFileLoc(n.head.range);
+ }
+
+ n.range = n.type === 'Template' ? [...templateRange] : toFileRange(n.loc);
+ n.start = n.range[0];
+ n.end = n.range[1];
+ n.loc = toFileLoc(n.range);
+
+ if (n.type === 'ElementNode') {
+ n.name = n.tag;
+ n.parts = [n.path.head].map((p) => {
+ const range = toFileRange(p.loc);
+ return {
+ ...p,
+ name: p.original,
+ parent: n,
+ type: 'GlimmerElementNodePart',
+ range,
+ loc: toFileLoc(range),
+ };
+ });
+ }
+
+ if ('blockParams' in n) {
+ n.params = (n.params || []).map((p) => {
+ const range = toFileRange(p.loc);
+ return {
+ ...p,
+ type: 'BlockParam',
+ name: p.original,
+ parent: n,
+ range,
+ loc: toFileLoc(range),
+ };
+ });
+ }
+
+ // Nullify empty hashes before the type is renamed
+ if (
+ (n.type === 'MustacheStatement' ||
+ n.type === 'BlockStatement' ||
+ n.type === 'SubExpression') &&
+ n.hash &&
+ n.hash.pairs &&
+ n.hash.pairs.length === 0
+ ) {
+ n.hash = null;
+ }
+
+ n.type = `Glimmer${n.type}`;
+ }
+
+ // Clean up AST structure
+ removeFromParent(emptyTextNodes);
+ removeFromParent(comments);
+ for (const comment of comments) {
+ comment.type = 'Block';
+ }
+
+ // Build final token stream
+ ast.tokens = buildTokenStream(
+ tokenize(tokenSource || templateContent, codeLines, offset),
+ comments,
+ textNodes
+ );
+ ast.contents = templateContent;
+
+ return { ast, comments };
+}
+
+/**
+ * Template infos already have character (UTF-16) offsets — no byte→char conversion needed.
+ * @param {Array<{ range: [number, number] }>} glintTemplateInfos
+ * @param {string} code - original source code
+ */
+export function preprocessGlimmerTemplatesFromCharOffsets(glintTemplateInfos, code) {
+ const codeLines = new DocumentLines(code);
+ const allComments = [];
+ const templateInfos = glintTemplateInfos.map((r) => ({
+ utf16Range: [...r.range],
+ }));
+
+ for (const tpl of templateInfos) {
+ const template = code.slice(...tpl.utf16Range);
+ const { ast, comments } = processGlimmerTemplate({
+ templateContent: template,
+ codeLines,
+ templateRange: [...tpl.utf16Range],
+ });
+ ast.content = template;
+ allComments.push(...comments);
+ tpl.ast = ast;
+ }
+
+ return {
+ templateVisitorKeys: glimmerVisitorKeys,
+ templateInfos,
+ comments: allComments,
+ };
+}
+
+/**
+ * traverses the AST and replaces the transformed template parts with the Glimmer
+ * AST.
+ * This also creates the scopes for the Glimmer Blocks and registers the block params
+ * in the scope, and also any usages of variables in path expressions
+ * this allows the basic eslint rules no-undef and no-unsused to work also for the
+ * templates without needing any custom rules
+ * @param result
+ * @param preprocessedResult
+ * @param visitorKeys
+ */
+export function convertAst(result, preprocessedResult, options) {
+ const templateInfos = preprocessedResult.templateInfos;
+ const matchByRangeOnly = options?.matchByRangeOnly || false;
+ result.ast.comments.push(...preprocessedResult.comments);
+
+ for (const ti of templateInfos) {
+ const firstIdx = result.ast.tokens.findIndex((t) => t.range[0] === ti.utf16Range[0]);
+ const lastIdx = result.ast.tokens.findIndex((t) => t.range[1] === ti.utf16Range[1]);
+ if (firstIdx === -1 || lastIdx === -1) continue;
+ result.ast.tokens.splice(firstIdx, lastIdx - firstIdx + 1, ...ti.ast.tokens);
+ }
+
+ // Build a Map keyed by range start for O(1) lookup during traversal
+ const templateInfoByStart = new Map(templateInfos.map((t) => [t.utf16Range[0], t]));
+
// eslint-disable-next-line complexity
traverse(result.visitorKeys, result.ast, (path) => {
const node = path.node;
- if (!node) return;
- if (node.type === 'GlimmerPathExpression') {
- registerPathExpression(node, path, result.scopeManager);
+ if (!node) return null;
+
+ // Glint produces CallExpression for expression templates and StaticBlock for
+ // class-member templates (vs TemplateLiteral from transformForLint).
+ const typeMatches = matchByRangeOnly
+ ? node.type === 'ExpressionStatement' ||
+ node.type === 'CallExpression' ||
+ node.type === 'StaticBlock' ||
+ node.type === 'ExportDefaultDeclaration'
+ : node.type === 'ExpressionStatement' ||
+ node.type === 'StaticBlock' ||
+ node.type === 'TemplateLiteral' ||
+ node.type === 'ExportDefaultDeclaration';
+
+ if (typeMatches) {
+ let range = node.range;
+ if (node.type === 'ExportDefaultDeclaration' && node.declaration) {
+ range = [node.declaration.range[0], node.declaration.range[1]];
+ }
+
+ const template = templateInfoByStart.get(range[0]);
+ if (
+ !template ||
+ (template.utf16Range[1] !== range[1] && template.utf16Range[1] !== range[1] + 1)
+ ) {
+ return null;
+ }
+ const ast = template.ast;
+ Object.assign(node, ast);
+ }
+
+ if (node.type === 'GlimmerPathExpression' && node.head.type === 'VarHead') {
+ const name = node.head.name;
+ if (glimmerIsKeyword(name)) {
+ return null;
+ }
+ const { scope, variable } = findVarInParentScopes(result.scopeManager, path, name) || {};
+ if (scope) {
+ node.head.parent = node;
+ registerNodeInScope(node.head, scope, variable);
+ }
}
if (node.type === 'GlimmerElementNode') {
registerElementNode(node, path, result.scopeManager);
@@ -325,4 +684,4 @@ export function transformForLint(code, fileName) {
};
}
-export { traverse, glimmerVisitorKeys };
+export { traverse };
diff --git a/src/parser/ts-patch.js b/src/parser/ts-patch.js
index ebbec98..d17b8a4 100644
--- a/src/parser/ts-patch.js
+++ b/src/parser/ts-patch.js
@@ -1,21 +1,22 @@
import fs from 'node:fs';
import { createRequire } from 'node:module';
import { transformForLint, replaceRange } from './transforms.js';
+import { isGlintAvailable, getGlintConfig, glintRewriteModule } from './glint-utils.js';
const require = createRequire(import.meta.url);
-let patchTs, replaceExtensions, syncMtsGtsSourceFiles, typescriptParser, isPatched, allowGjs;
+let patchTs, replaceExtensions, syncMtsGtsSourceFiles, typescriptParser, isPatched, allowGjs, ts;
try {
const parserPath = require.resolve('@typescript-eslint/parser');
// eslint-disable-next-line n/no-unpublished-require
const tsPath = require.resolve('typescript', { paths: [parserPath] });
- const ts = require(tsPath);
+ ts = require(tsPath);
typescriptParser = require('@typescript-eslint/parser');
patchTs = function patchTs(options = {}) {
+ allowGjs = options.allowGjs !== undefined ? options.allowGjs : true;
if (isPatched) return { allowGjs };
isPatched = true;
- allowGjs = options.allowGjs !== undefined ? options.allowGjs : true;
const sys = { ...ts.sys };
const newSys = {
...ts.sys,
@@ -51,11 +52,33 @@ try {
}
content = fs.readFileSync(fileName).toString();
}
- if (fileName.endsWith('.gts') || (allowGjs && fileName.endsWith('.gjs'))) {
+ if (fileName.endsWith('.gts')) {
+ // ts-patch.js is only active during type-aware linting (patchTs is called
+ // only when project/projectService/programs options are set). Glint is
+ // therefore required here — throw rather than silently produce wrong type info.
+ if (!isGlintAvailable()) {
+ throw new Error(
+ '[ember-eslint-parser] @glint/ember-tsc is required for type-aware linting of .gts files. ' +
+ 'Install it as a dependency of your project.'
+ );
+ }
+ const config = getGlintConfig(fileName);
+ if (!config) {
+ throw new Error(
+ '[ember-eslint-parser] No Glint environment found for ' +
+ fileName +
+ '. Ensure @glint/ember-tsc is configured in your tsconfig.'
+ );
+ }
+ const result = glintRewriteModule(content, fileName, ts, config);
+ if (result) {
+ content = result.transformedContents;
+ }
+ } else if (allowGjs && fileName.endsWith('.gjs')) {
try {
content = transformForLint(content).output;
} catch (e) {
- console.error('failed to transformForLint for gts/gjs processing');
+ console.error('failed to transformForLint for .gjs processing');
console.error(e);
}
}
@@ -164,4 +187,4 @@ try {
syncMtsGtsSourceFiles = () => null;
}
-export { patchTs, replaceExtensions, syncMtsGtsSourceFiles, typescriptParser };
+export { patchTs, replaceExtensions, syncMtsGtsSourceFiles, typescriptParser, ts };
diff --git a/test-projects/configs/flat-ts/package.json b/test-projects/configs/flat-ts/package.json
index cec03d1..45bebfd 100644
--- a/test-projects/configs/flat-ts/package.json
+++ b/test-projects/configs/flat-ts/package.json
@@ -15,6 +15,8 @@
"@babel/plugin-transform-typescript": "^7.26.3",
"@eslint/js": "^9.17.0",
"@tsconfig/ember": "^3.0.8",
+ "@glint/ember-tsc": "^1.1.0",
+ "@glint/template": "^1.3.0",
"ember-source": "^6.1.0",
"eslint": "^9.17.0",
"eslint-config-prettier": "^9.1.0",
diff --git a/test-projects/configs/flat-ts/src/dynamic-import.gts b/test-projects/configs/flat-ts/src/dynamic-import.ts
similarity index 100%
rename from test-projects/configs/flat-ts/src/dynamic-import.gts
rename to test-projects/configs/flat-ts/src/dynamic-import.ts
diff --git a/test-projects/configs/flat-ts/src/non-ascii-import.gts b/test-projects/configs/flat-ts/src/non-ascii-import.ts
similarity index 100%
rename from test-projects/configs/flat-ts/src/non-ascii-import.gts
rename to test-projects/configs/flat-ts/src/non-ascii-import.ts
diff --git a/test-projects/configs/flat-ts/tsconfig.json b/test-projects/configs/flat-ts/tsconfig.json
index f940e9c..db0becc 100644
--- a/test-projects/configs/flat-ts/tsconfig.json
+++ b/test-projects/configs/flat-ts/tsconfig.json
@@ -44,5 +44,8 @@
"allowImportingTsExtensions": true,
"types": ["ember-source/types"]
+ },
+ "glint": {
+ "environment": "ember-template-imports"
}
}
diff --git a/test-projects/gts-glint/.eslintignore b/test-projects/gts-glint/.eslintignore
new file mode 100644
index 0000000..cc1b7f1
--- /dev/null
+++ b/test-projects/gts-glint/.eslintignore
@@ -0,0 +1 @@
+tsconfig.tsbuildinfo
diff --git a/test-projects/gts-glint/.eslintrc.cjs b/test-projects/gts-glint/.eslintrc.cjs
new file mode 100644
index 0000000..fd7fd5b
--- /dev/null
+++ b/test-projects/gts-glint/.eslintrc.cjs
@@ -0,0 +1,28 @@
+'use strict';
+
+module.exports = {
+ root: true,
+ overrides: [
+ {
+ files: ['**/*.{js,ts}'],
+ plugins: ['ember'],
+ parser: 'ember-eslint-parser',
+ extends: ['eslint:recommended', 'plugin:ember/recommended'],
+ },
+ {
+ files: ['**/*.gts'],
+ parser: 'ember-eslint-parser',
+ parserOptions: {
+ project: './tsconfig.json',
+ tsconfigRootDir: __dirname,
+ },
+ plugins: ['ember', '@typescript-eslint'],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended-type-checked',
+ 'plugin:ember/recommended',
+ 'plugin:ember/recommended-gts',
+ ],
+ },
+ ],
+};
diff --git a/test-projects/gts-glint/index.d.ts b/test-projects/gts-glint/index.d.ts
new file mode 100644
index 0000000..8766a46
--- /dev/null
+++ b/test-projects/gts-glint/index.d.ts
@@ -0,0 +1 @@
+import "ember-source/types/stable"
diff --git a/test-projects/gts-glint/package.json b/test-projects/gts-glint/package.json
new file mode 100644
index 0000000..e24e715
--- /dev/null
+++ b/test-projects/gts-glint/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@test-project/gts-glint",
+ "private": true,
+ "scripts": {
+ "test:check": "eslint src/greeter.gts src/consumer.ts --max-warnings=0"
+ },
+ "devDependencies": {
+ "@ember/test-waiters": "^3.1.0",
+ "@glimmer/tracking": "^1.1.2",
+ "@glimmer/component": "^1.1.2",
+ "@glint/ember-tsc": "^1.1.0",
+ "@glint/template": "^1.3.0",
+ "@typescript-eslint/eslint-plugin": "^8.46.4",
+ "@typescript-eslint/parser": "^8.46.4",
+ "ember-eslint-parser": "workspace:^",
+ "ember-source": "^5.6.0",
+ "eslint": "^8.0.1",
+ "eslint-plugin-ember": "^12.0.0",
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/test-projects/gts-glint/src/consumer.ts b/test-projects/gts-glint/src/consumer.ts
new file mode 100644
index 0000000..e4f5c92
--- /dev/null
+++ b/test-projects/gts-glint/src/consumer.ts
@@ -0,0 +1,5 @@
+import { greet } from './greeter';
+
+const message: string = greet('world');
+
+export { message };
diff --git a/test-projects/gts-glint/src/greeter.gts b/test-projects/gts-glint/src/greeter.gts
new file mode 100644
index 0000000..cfee513
--- /dev/null
+++ b/test-projects/gts-glint/src/greeter.gts
@@ -0,0 +1,19 @@
+import Component from '@glimmer/component';
+
+interface GreeterArgs {
+ name: string;
+}
+
+export function greet(name: string): string {
+ return `Hello, ${name}`;
+}
+
+export default class Greeter extends Component<{ Args: GreeterArgs }> {
+ get greeting(): string {
+ return greet(this.args.name);
+ }
+
+
+ {{this.greeting}}
+
+}
diff --git a/test-projects/gts-glint/src/lint-errors.gts b/test-projects/gts-glint/src/lint-errors.gts
new file mode 100644
index 0000000..aae7df9
--- /dev/null
+++ b/test-projects/gts-glint/src/lint-errors.gts
@@ -0,0 +1,7 @@
+import Component from '@glimmer/component';
+
+export default class LintErrors extends Component {
+
+ {{undefinedVar}}
+
+}
diff --git a/test-projects/gts-glint/tsconfig.json b/test-projects/gts-glint/tsconfig.json
new file mode 100644
index 0000000..9fb615d
--- /dev/null
+++ b/test-projects/gts-glint/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "es2019",
+ "lib": ["ES2018", "DOM"],
+ "module": "commonjs",
+ "experimentalDecorators": true,
+ "rootDir": ".",
+ "allowJs": true,
+ "strictNullChecks": true
+ },
+ "glint": {
+ "environment": "ember-template-imports"
+ },
+ "include": [
+ "**/*.ts",
+ "**/*.gts",
+ "index.d.ts"
+ ]
+}
diff --git a/test-projects/gts/.eslintrc.cjs b/test-projects/gts/.eslintrc.cjs
index 782e65b..f787db1 100644
--- a/test-projects/gts/.eslintrc.cjs
+++ b/test-projects/gts/.eslintrc.cjs
@@ -8,7 +8,7 @@ module.exports = {
root: true,
parserOptions: {
...(isV8 ? { projectService: true } : { project: true }),
- tsconfigRootDir: __dirname
+ tsconfigRootDir: __dirname,
},
rules: {
'no-use-before-define': ['error'],
@@ -18,20 +18,29 @@ module.exports = {
{
files: ['src-fixable/**/*'],
rules: {
- 'arrow-body-style':["error", "always"],
+ 'arrow-body-style': ['error', 'always'],
},
},
{
files: ['**/*.{js,ts}'],
plugins: ['ember'],
parser: 'ember-eslint-parser',
- extends: ['eslint:recommended', 'plugin:ember/recommended', 'plugin:@typescript-eslint/recommended-type-checked'],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:ember/recommended',
+ 'plugin:@typescript-eslint/recommended-type-checked',
+ ],
},
{
files: ['**/*.gts'],
parser: 'ember-eslint-parser',
plugins: ['ember'],
- extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended-type-checked', 'plugin:ember/recommended', 'plugin:ember/recommended-gts'],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended-type-checked',
+ 'plugin:ember/recommended',
+ 'plugin:ember/recommended-gts',
+ ],
},
{
files: ['**/*.gjs'],
diff --git a/test-projects/gts/package.json b/test-projects/gts/package.json
index d3dc9e5..555bdea 100644
--- a/test-projects/gts/package.json
+++ b/test-projects/gts/package.json
@@ -10,6 +10,7 @@
"@ember/test-waiters": "^3.1.0",
"@glimmer/component": "^1.1.2",
"@glimmer/tracking": "^1.1.2",
+ "@glint/ember-tsc": "^1.1.0",
"@glint/template": "^1.3.0",
"@typescript-eslint/eslint-plugin": "^8.46.4",
"@typescript-eslint/parser": "^8.46.4",
diff --git a/test-projects/gts/tsconfig.json b/test-projects/gts/tsconfig.json
index f7c3d94..568bc58 100644
--- a/test-projects/gts/tsconfig.json
+++ b/test-projects/gts/tsconfig.json
@@ -8,10 +8,8 @@
"allowJs": true,
"strictNullChecks": true
},
- "include": [
- "**/*.ts",
- "**/*.gts",
- "index.d.ts"
- ],
+ "glint": {
+ "environment": "ember-template-imports"
+ },
+ "include": ["**/*.ts", "**/*.gts", "index.d.ts"]
}
-
\ No newline at end of file
diff --git a/tests/fixtures/foo.gjs b/tests/fixtures/foo.gjs
new file mode 100644
index 0000000..ad1d380
--- /dev/null
+++ b/tests/fixtures/foo.gjs
@@ -0,0 +1 @@
+export const x = 1;
diff --git a/tests/fixtures/tsconfig.no-allow-js.json b/tests/fixtures/tsconfig.no-allow-js.json
new file mode 100644
index 0000000..ae82940
--- /dev/null
+++ b/tests/fixtures/tsconfig.no-allow-js.json
@@ -0,0 +1,8 @@
+{
+ "compilerOptions": {
+ "rootDir": ".",
+ "allowJs": false,
+ "strictNullChecks": true
+ },
+ "include": ["**/*.ts", "**/*.gts"]
+}
diff --git a/tests/parser.test.js b/tests/parser.test.js
index 9466614..e734913 100644
--- a/tests/parser.test.js
+++ b/tests/parser.test.js
@@ -1,4 +1,4 @@
-import { beforeAll, describe, expect, it } from 'vitest';
+import { beforeAll, describe, expect, it, vi } from 'vitest';
import { parseForESLint } from '../src/parser/gjs-gts-parser.js';
import { replaceExtensions } from '../src/parser/ts-patch.js';
import { traverse } from '../src/parser/transforms.js';
@@ -2495,3 +2495,134 @@ describe('replaceExtensions', () => {
);
});
});
+
+describe('patchTs allowGjs singleton', () => {
+ it('updates allowGjs on each call after the initial patch', async () => {
+ vi.resetModules();
+ const { patchTs } = await import('../src/parser/ts-patch.js');
+
+ expect(patchTs({ allowGjs: false }).allowGjs).toBe(false);
+ // Each call should reflect the passed value, not the value from the first call
+ expect(patchTs({ allowGjs: true }).allowGjs).toBe(true);
+ });
+});
+
+describe('allowGjs mismatch warning', () => {
+ it('does not warn when tsconfig has allowJs:false', () => {
+ // When allowJs:false, patchTs is called with allowGjs:false — no spurious warning.
+ // Use a .ts file so the Glint gate (type-aware .gts requires Glint) doesn't trigger.
+ expect(() =>
+ parseForESLint('export class Foo {}', {
+ filePath: new URL('./fixtures/baz.ts', import.meta.url).pathname,
+ project: new URL('./fixtures/tsconfig.no-allow-js.json', import.meta.url).pathname,
+ tsconfigRootDir: new URL('./fixtures', import.meta.url).pathname,
+ comment: true,
+ loc: true,
+ range: true,
+ tokens: true,
+ })
+ ).not.toThrow('[ember-eslint-parser]');
+ });
+});
+
+describe('Glint required for type-aware .gts linting', () => {
+ it('throws a clear error when @glint/ember-tsc is not installed', async () => {
+ vi.resetModules();
+ vi.doMock('../src/parser/glint-utils.js', () => ({
+ isGlintAvailable: () => false,
+ getGlintConfig: () => null,
+ glintRewriteModule: () => null,
+ buildTemplateInfoFromGlint: () => [],
+ }));
+ try {
+ const { parseForESLint: parse } = await import('../src/parser/gjs-gts-parser.js');
+ expect(() =>
+ parse('export class Foo {}', {
+ filePath: 'test.gts',
+ project: 'tsconfig.json',
+ })
+ ).toThrow('@glint/ember-tsc is required');
+ } finally {
+ vi.doUnmock('../src/parser/glint-utils.js');
+ vi.resetModules();
+ }
+ });
+
+ it('throws a clear error when Glint is available but not configured in tsconfig', async () => {
+ vi.resetModules();
+ vi.doMock('../src/parser/glint-utils.js', () => ({
+ isGlintAvailable: () => true,
+ getGlintConfig: () => null,
+ glintRewriteModule: () => null,
+ buildTemplateInfoFromGlint: () => [],
+ }));
+ try {
+ const { parseForESLint: parse } = await import('../src/parser/gjs-gts-parser.js');
+ expect(() =>
+ parse('export class Foo {}', {
+ filePath: 'test.gts',
+ project: 'tsconfig.json',
+ })
+ ).toThrow('No Glint environment found');
+ } finally {
+ vi.doUnmock('../src/parser/glint-utils.js');
+ vi.resetModules();
+ }
+ });
+
+ it('.gts without project option parses without requiring Glint', async () => {
+ vi.resetModules();
+ vi.doMock('../src/parser/glint-utils.js', () => ({
+ isGlintAvailable: () => false,
+ getGlintConfig: () => null,
+ glintRewriteModule: () => null,
+ buildTemplateInfoFromGlint: () => [],
+ }));
+ try {
+ const { parseForESLint: parse } = await import('../src/parser/gjs-gts-parser.js');
+ expect(() =>
+ parse('export class Foo {}', {
+ filePath: 'test.gts',
+ comment: true,
+ loc: true,
+ range: true,
+ tokens: true,
+ })
+ ).not.toThrow();
+ } finally {
+ vi.doUnmock('../src/parser/glint-utils.js');
+ vi.resetModules();
+ }
+ });
+
+ it('.gjs files are not gated on Glint even with project option', async () => {
+ vi.resetModules();
+ vi.doMock('../src/parser/glint-utils.js', () => ({
+ isGlintAvailable: () => false,
+ getGlintConfig: () => null,
+ glintRewriteModule: () => null,
+ buildTemplateInfoFromGlint: () => [],
+ }));
+ try {
+ const { parseForESLint: parse } = await import('../src/parser/gjs-gts-parser.js');
+ // The TS parser may throw for other reasons (e.g. file not in project),
+ // but it must NOT throw the Glint-required error.
+ try {
+ parse('const x = 1;', {
+ filePath: new URL('./fixtures/foo.gjs', import.meta.url).pathname,
+ project: new URL('./fixtures/tsconfig.no-allow-js.json', import.meta.url).pathname,
+ tsconfigRootDir: new URL('./fixtures', import.meta.url).pathname,
+ comment: true,
+ loc: true,
+ range: true,
+ tokens: true,
+ });
+ } catch (e) {
+ expect(e.message).not.toContain('@glint/ember-tsc is required');
+ }
+ } finally {
+ vi.doUnmock('../src/parser/glint-utils.js');
+ vi.resetModules();
+ }
+ });
+});