release: prepare WRNexusJS 0.8.8
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ai",
|
"name": "@wrnexus/ai",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/authz",
|
"name": "@wrnexus/authz",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/authz — part of the WrNexus framework.",
|
"description": "@wrnexus/authz — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -41,8 +41,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/db": "^0.8.7"
|
"@wrnexus/db": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
+18
-18
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/cli — part of the WrNexus framework.",
|
"description": "@wrnexus/cli — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -44,23 +44,23 @@
|
|||||||
"wrnexus": "./dist/index.js"
|
"wrnexus": "./dist/index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/router": "^0.8.7",
|
"@wrnexus/router": "^0.8.8",
|
||||||
"@wrnexus/csr": "^0.8.7",
|
"@wrnexus/csr": "^0.8.8",
|
||||||
"@wrnexus/compiler": "^0.8.7",
|
"@wrnexus/compiler": "^0.8.8",
|
||||||
"@wrnexus/styles": "^0.8.7",
|
"@wrnexus/styles": "^0.8.8",
|
||||||
"@wrnexus/dev-server": "^0.8.7",
|
"@wrnexus/dev-server": "^0.8.8",
|
||||||
"@wrnexus/ui": "^0.8.7",
|
"@wrnexus/ui": "^0.8.8",
|
||||||
"@wrnexus/validation": "^0.8.7",
|
"@wrnexus/validation": "^0.8.8",
|
||||||
"@wrnexus/i18n": "^0.8.7",
|
"@wrnexus/i18n": "^0.8.8",
|
||||||
"@wrnexus/mcp": "^0.8.7",
|
"@wrnexus/mcp": "^0.8.8",
|
||||||
"@wrnexus/playground": "^0.8.7",
|
"@wrnexus/playground": "^0.8.8",
|
||||||
"@wrnexus/db": "^0.8.7",
|
"@wrnexus/db": "^0.8.8",
|
||||||
"@wrnexus/authz": "^0.8.7",
|
"@wrnexus/authz": "^0.8.8",
|
||||||
"@wrnexus/plugin": "^0.8.7",
|
"@wrnexus/plugin": "^0.8.8",
|
||||||
"@wrnexus/syntax": "^0.8.7",
|
"@wrnexus/syntax": "^0.8.8",
|
||||||
"@wrnexus/typecheck": "^0.8.7",
|
"@wrnexus/typecheck": "^0.8.8",
|
||||||
"@wrnexus/security": "^0.8.7",
|
"@wrnexus/security": "^0.8.8",
|
||||||
"selfsigned": "^5.5.0"
|
"selfsigned": "^5.5.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/compiler — part of the WrNexus framework.",
|
"description": "@wrnexus/compiler — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,10 +37,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/csr": "^0.8.7",
|
"@wrnexus/csr": "^0.8.8",
|
||||||
"@wrnexus/syntax": "^0.8.7",
|
"@wrnexus/syntax": "^0.8.8",
|
||||||
"@wrnexus/store": "^0.8.7",
|
"@wrnexus/store": "^0.8.8",
|
||||||
"@wrnexus/validation": "^0.8.7"
|
"@wrnexus/validation": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/core",
|
"name": "@wrnexus/core",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/core — part of the WrNexus framework.",
|
"description": "@wrnexus/core — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/csr — part of the WrNexus framework.",
|
"description": "@wrnexus/csr — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7"
|
"@wrnexus/core": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/db",
|
"name": "@wrnexus/db",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Typed database drivers, migrations, instrumentation, repositories, pagination, and transaction helpers.",
|
"description": "Typed database drivers, migrations, instrumentation, repositories, pagination, and transaction helpers.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
|
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -41,27 +41,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/authz": "^0.8.7",
|
"@wrnexus/authz": "^0.8.8",
|
||||||
"@wrnexus/rpc": "^0.8.7",
|
"@wrnexus/rpc": "^0.8.8",
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/dev-toolbar": "^0.8.7",
|
"@wrnexus/dev-toolbar": "^0.8.8",
|
||||||
"@wrnexus/router": "^0.8.7",
|
"@wrnexus/router": "^0.8.8",
|
||||||
"@wrnexus/ssr": "^0.8.7",
|
"@wrnexus/ssr": "^0.8.8",
|
||||||
"@wrnexus/csr": "^0.8.7",
|
"@wrnexus/csr": "^0.8.8",
|
||||||
"@wrnexus/compiler": "^0.8.7",
|
"@wrnexus/compiler": "^0.8.8",
|
||||||
"@wrnexus/styles": "^0.8.7",
|
"@wrnexus/styles": "^0.8.8",
|
||||||
"@wrnexus/ui": "^0.8.7",
|
"@wrnexus/ui": "^0.8.8",
|
||||||
"@wrnexus/validation": "^0.8.7",
|
"@wrnexus/validation": "^0.8.8",
|
||||||
"@wrnexus/i18n": "^0.8.7",
|
"@wrnexus/i18n": "^0.8.8",
|
||||||
"@wrnexus/db": "^0.8.7",
|
"@wrnexus/db": "^0.8.8",
|
||||||
"@wrnexus/pubsub": "^0.8.7",
|
"@wrnexus/pubsub": "^0.8.8",
|
||||||
"@wrnexus/uploader": "^0.8.7",
|
"@wrnexus/uploader": "^0.8.8",
|
||||||
"@wrnexus/plugin": "^0.8.7",
|
"@wrnexus/plugin": "^0.8.8",
|
||||||
"@wrnexus/store": "^0.8.7",
|
"@wrnexus/store": "^0.8.8",
|
||||||
"@wrnexus/security": "^0.8.7",
|
"@wrnexus/security": "^0.8.8",
|
||||||
"@wrnexus/observability": "^0.8.7",
|
"@wrnexus/observability": "^0.8.8",
|
||||||
"@wrnexus/cache": "^0.8.7",
|
"@wrnexus/cache": "^0.8.8",
|
||||||
"@wrnexus/pwa": "^0.8.7"
|
"@wrnexus/pwa": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-toolbar",
|
"name": "@wrnexus/dev-toolbar",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/dev-toolbar — part of the WrNexus framework.",
|
"description": "@wrnexus/dev-toolbar — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/encryption",
|
"name": "@wrnexus/encryption",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Authenticated encryption, key rotation, hashing, and optional application-layer encrypted HTTP envelopes.",
|
"description": "Authenticated encryption, key rotation, hashing, and optional application-layer encrypted HTTP envelopes.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7"
|
"@wrnexus/core": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/helpers",
|
"name": "@wrnexus/helpers",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7"
|
"@wrnexus/core": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/i18n",
|
"name": "@wrnexus/i18n",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Locale loading, fallback resolution, SSR/browser translations, formatters, and WRNexusJS language components.",
|
"description": "Locale loading, fallback resolution, SSR/browser translations, formatters, and WRNexusJS language components.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
"./components/*": "./components/*"
|
"./components/*": "./components/*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/plugin": "^0.8.7",
|
"@wrnexus/plugin": "^0.8.8",
|
||||||
"@wrnexus/ui": "^0.8.7"
|
"@wrnexus/ui": "^0.8.8"
|
||||||
},
|
},
|
||||||
"wrnexus": {
|
"wrnexus": {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/jwt",
|
"name": "@wrnexus/jwt",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "HS256 JSON Web Tokens, key rotation, access/refresh helpers, scopes, cookies, and auth middleware.",
|
"description": "HS256 JSON Web Tokens, key rotation, access/refresh helpers, scopes, cookies, and auth middleware.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7"
|
"@wrnexus/core": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/mobile",
|
"name": "@wrnexus/mobile",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/mobile — part of the WrNexus framework.",
|
"description": "@wrnexus/mobile — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/native": "^0.8.7"
|
"@wrnexus/native": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/native",
|
"name": "@wrnexus/native",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/native — part of the WrNexus framework.",
|
"description": "@wrnexus/native — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/oauth",
|
"name": "@wrnexus/oauth",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/oauth — part of the WrNexus framework.",
|
"description": "@wrnexus/oauth — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/jwt": "^0.8.7"
|
"@wrnexus/jwt": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/plugin",
|
"name": "@wrnexus/plugin",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/plugin — part of the WrNexus framework.",
|
"description": "@wrnexus/plugin — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/syntax": "^0.8.7"
|
"@wrnexus/syntax": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/pubsub",
|
"name": "@wrnexus/pubsub",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
|
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -45,8 +45,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/rpc": "^0.8.7"
|
"@wrnexus/rpc": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/queue",
|
"name": "@wrnexus/queue",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/queue — part of the WrNexus framework.",
|
"description": "@wrnexus/queue — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,8 +37,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/rpc": "^0.8.7"
|
"@wrnexus/rpc": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/reactive",
|
"name": "@wrnexus/reactive",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/reactive — part of the WrNexus framework.",
|
"description": "@wrnexus/reactive — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/router",
|
"name": "@wrnexus/router",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/router — part of the WrNexus framework.",
|
"description": "@wrnexus/router — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,8 +37,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/compiler": "^0.8.7",
|
"@wrnexus/compiler": "^0.8.8",
|
||||||
"@wrnexus/core": "^0.8.7"
|
"@wrnexus/core": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ssr",
|
"name": "@wrnexus/ssr",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/ssr — part of the WrNexus framework.",
|
"description": "@wrnexus/ssr — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -45,9 +45,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/store": "^0.8.7",
|
"@wrnexus/store": "^0.8.8",
|
||||||
"@wrnexus/security": "^0.8.7"
|
"@wrnexus/security": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/styles",
|
"name": "@wrnexus/styles",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/styles — part of the WrNexus framework.",
|
"description": "@wrnexus/styles — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,9 +37,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/uploader": "^0.8.7",
|
"@wrnexus/uploader": "^0.8.8",
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/plugin": "^0.8.7"
|
"@wrnexus/plugin": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/syntax",
|
"name": "@wrnexus/syntax",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/syntax — part of the WrNexus framework.",
|
"description": "@wrnexus/syntax — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/test",
|
"name": "@wrnexus/test",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/test — part of the WrNexus framework.",
|
"description": "@wrnexus/test — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/tracking",
|
"name": "@wrnexus/tracking",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/tracking — part of the WrNexus framework.",
|
"description": "@wrnexus/tracking — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/ui — part of the WrNexus framework.",
|
"description": "@wrnexus/ui — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
"./ui.css": "./ui.css"
|
"./ui.css": "./ui.css"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7"
|
"@wrnexus/core": "^0.8.8"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Secure upload drivers, policies, client runtime, helper functions, and reusable upload components.",
|
"description": "Secure upload drivers, policies, client runtime, helper functions, and reusable upload components.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
"./components/*": "./components/*"
|
"./components/*": "./components/*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/plugin": "^0.8.7",
|
"@wrnexus/plugin": "^0.8.8",
|
||||||
"@wrnexus/ui": "^0.8.7"
|
"@wrnexus/ui": "^0.8.8"
|
||||||
},
|
},
|
||||||
"wrnexus": {
|
"wrnexus": {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/validation",
|
"name": "@wrnexus/validation",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Shared server/browser schemas, validation helpers, form runtime, and reusable error components.",
|
"description": "Shared server/browser schemas, validation helpers, form runtime, and reusable error components.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
"./components/*": "./components/*"
|
"./components/*": "./components/*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.7",
|
"@wrnexus/core": "^0.8.8",
|
||||||
"@wrnexus/plugin": "^0.8.7",
|
"@wrnexus/plugin": "^0.8.8",
|
||||||
"@wrnexus/ui": "^0.8.7"
|
"@wrnexus/ui": "^0.8.8"
|
||||||
},
|
},
|
||||||
"wrnexus": {
|
"wrnexus": {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.8.8
|
||||||
|
|
||||||
|
- Added the framework request context to `.wrn` language-server type environments.
|
||||||
|
- Kept workspace type declarations inside runnable apps during updates.
|
||||||
|
- Regenerated lint-safe application declarations before update verification.
|
||||||
|
|
||||||
All notable framework changes are recorded here. Every release must also include an idempotent
|
All notable framework changes are recorded here. Every release must also include an idempotent
|
||||||
entry in the CLI migration registry.
|
entry in the CLI migration registry.
|
||||||
|
|
||||||
|
|||||||
@@ -208,11 +208,11 @@
|
|||||||
},
|
},
|
||||||
"packages/ai": {
|
"packages/ai": {
|
||||||
"name": "@wrnexus/ai",
|
"name": "@wrnexus/ai",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/auth": {
|
"packages/auth": {
|
||||||
"name": "@wrnexus/auth",
|
"name": "@wrnexus/auth",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/authz": "workspace:*",
|
"@wrnexus/authz": "workspace:*",
|
||||||
"@wrnexus/captcha": "workspace:*",
|
"@wrnexus/captcha": "workspace:*",
|
||||||
@@ -234,7 +234,7 @@
|
|||||||
},
|
},
|
||||||
"packages/authz": {
|
"packages/authz": {
|
||||||
"name": "@wrnexus/authz",
|
"name": "@wrnexus/authz",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/db": "workspace:*",
|
"@wrnexus/db": "workspace:*",
|
||||||
@@ -242,18 +242,18 @@
|
|||||||
},
|
},
|
||||||
"packages/benchmark": {
|
"packages/benchmark": {
|
||||||
"name": "@wrnexus/benchmark",
|
"name": "@wrnexus/benchmark",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/cache": {
|
"packages/cache": {
|
||||||
"name": "@wrnexus/cache",
|
"name": "@wrnexus/cache",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/captcha": {
|
"packages/captcha": {
|
||||||
"name": "@wrnexus/captcha",
|
"name": "@wrnexus/captcha",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -268,7 +268,7 @@
|
|||||||
},
|
},
|
||||||
"packages/cli": {
|
"packages/cli": {
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"bin": {
|
"bin": {
|
||||||
"wrnexus": "src/index.ts",
|
"wrnexus": "src/index.ts",
|
||||||
},
|
},
|
||||||
@@ -295,7 +295,7 @@
|
|||||||
},
|
},
|
||||||
"packages/compiler": {
|
"packages/compiler": {
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/csr": "workspace:*",
|
"@wrnexus/csr": "workspace:*",
|
||||||
"@wrnexus/store": "workspace:*",
|
"@wrnexus/store": "workspace:*",
|
||||||
@@ -305,7 +305,7 @@
|
|||||||
},
|
},
|
||||||
"packages/content": {
|
"packages/content": {
|
||||||
"name": "@wrnexus/content",
|
"name": "@wrnexus/content",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
@@ -313,18 +313,18 @@
|
|||||||
},
|
},
|
||||||
"packages/core": {
|
"packages/core": {
|
||||||
"name": "@wrnexus/core",
|
"name": "@wrnexus/core",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/csr": {
|
"packages/csr": {
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/db": {
|
"packages/db": {
|
||||||
"name": "@wrnexus/db",
|
"name": "@wrnexus/db",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
@@ -332,7 +332,7 @@
|
|||||||
},
|
},
|
||||||
"packages/dev-server": {
|
"packages/dev-server": {
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/authz": "workspace:*",
|
"@wrnexus/authz": "workspace:*",
|
||||||
"@wrnexus/cache": "workspace:*",
|
"@wrnexus/cache": "workspace:*",
|
||||||
@@ -359,7 +359,7 @@
|
|||||||
},
|
},
|
||||||
"packages/dev-toolbar": {
|
"packages/dev-toolbar": {
|
||||||
"name": "@wrnexus/dev-toolbar",
|
"name": "@wrnexus/dev-toolbar",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
@@ -367,7 +367,7 @@
|
|||||||
},
|
},
|
||||||
"packages/encryption": {
|
"packages/encryption": {
|
||||||
"name": "@wrnexus/encryption",
|
"name": "@wrnexus/encryption",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
@@ -378,21 +378,21 @@
|
|||||||
},
|
},
|
||||||
"packages/graphql": {
|
"packages/graphql": {
|
||||||
"name": "@wrnexus/graphql",
|
"name": "@wrnexus/graphql",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/helpers": {
|
"packages/helpers": {
|
||||||
"name": "@wrnexus/helpers",
|
"name": "@wrnexus/helpers",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/i18n": {
|
"packages/i18n": {
|
||||||
"name": "@wrnexus/i18n",
|
"name": "@wrnexus/i18n",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -406,7 +406,7 @@
|
|||||||
},
|
},
|
||||||
"packages/identity": {
|
"packages/identity": {
|
||||||
"name": "@wrnexus/identity",
|
"name": "@wrnexus/identity",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/auth": "workspace:*",
|
"@wrnexus/auth": "workspace:*",
|
||||||
"@wrnexus/authz": "workspace:*",
|
"@wrnexus/authz": "workspace:*",
|
||||||
@@ -415,7 +415,7 @@
|
|||||||
},
|
},
|
||||||
"packages/image": {
|
"packages/image": {
|
||||||
"name": "@wrnexus/image",
|
"name": "@wrnexus/image",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
"@wrnexus/security": "workspace:*",
|
"@wrnexus/security": "workspace:*",
|
||||||
@@ -435,7 +435,7 @@
|
|||||||
},
|
},
|
||||||
"packages/jwt": {
|
"packages/jwt": {
|
||||||
"name": "@wrnexus/jwt",
|
"name": "@wrnexus/jwt",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
@@ -446,7 +446,7 @@
|
|||||||
},
|
},
|
||||||
"packages/language-server": {
|
"packages/language-server": {
|
||||||
"name": "@wrnexus/language-server",
|
"name": "@wrnexus/language-server",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"bin": {
|
"bin": {
|
||||||
"wrnexus-language-server": "src/server.ts",
|
"wrnexus-language-server": "src/server.ts",
|
||||||
},
|
},
|
||||||
@@ -457,39 +457,39 @@
|
|||||||
},
|
},
|
||||||
"packages/mcp": {
|
"packages/mcp": {
|
||||||
"name": "@wrnexus/mcp",
|
"name": "@wrnexus/mcp",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"bin": {
|
"bin": {
|
||||||
"wrnexus-mcp": "src/stdio.ts",
|
"wrnexus-mcp": "src/stdio.ts",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/mobile": {
|
"packages/mobile": {
|
||||||
"name": "@wrnexus/mobile",
|
"name": "@wrnexus/mobile",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/native": "workspace:*",
|
"@wrnexus/native": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/native": {
|
"packages/native": {
|
||||||
"name": "@wrnexus/native",
|
"name": "@wrnexus/native",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/oauth": {
|
"packages/oauth": {
|
||||||
"name": "@wrnexus/oauth",
|
"name": "@wrnexus/oauth",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/jwt": "workspace:*",
|
"@wrnexus/jwt": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/observability": {
|
"packages/observability": {
|
||||||
"name": "@wrnexus/observability",
|
"name": "@wrnexus/observability",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/playground": {
|
"packages/playground": {
|
||||||
"name": "@wrnexus/playground",
|
"name": "@wrnexus/playground",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/compiler": "workspace:*",
|
"@wrnexus/compiler": "workspace:*",
|
||||||
"@wrnexus/syntax": "workspace:*",
|
"@wrnexus/syntax": "workspace:*",
|
||||||
@@ -497,14 +497,14 @@
|
|||||||
},
|
},
|
||||||
"packages/plugin": {
|
"packages/plugin": {
|
||||||
"name": "@wrnexus/plugin",
|
"name": "@wrnexus/plugin",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/syntax": "workspace:*",
|
"@wrnexus/syntax": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/pubsub": {
|
"packages/pubsub": {
|
||||||
"name": "@wrnexus/pubsub",
|
"name": "@wrnexus/pubsub",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/rpc": "workspace:*",
|
"@wrnexus/rpc": "workspace:*",
|
||||||
@@ -512,7 +512,7 @@
|
|||||||
},
|
},
|
||||||
"packages/pwa": {
|
"packages/pwa": {
|
||||||
"name": "@wrnexus/pwa",
|
"name": "@wrnexus/pwa",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
@@ -520,7 +520,7 @@
|
|||||||
},
|
},
|
||||||
"packages/queue": {
|
"packages/queue": {
|
||||||
"name": "@wrnexus/queue",
|
"name": "@wrnexus/queue",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/rpc": "workspace:*",
|
"@wrnexus/rpc": "workspace:*",
|
||||||
@@ -528,11 +528,11 @@
|
|||||||
},
|
},
|
||||||
"packages/reactive": {
|
"packages/reactive": {
|
||||||
"name": "@wrnexus/reactive",
|
"name": "@wrnexus/reactive",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/realtime": {
|
"packages/realtime": {
|
||||||
"name": "@wrnexus/realtime",
|
"name": "@wrnexus/realtime",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -546,7 +546,7 @@
|
|||||||
},
|
},
|
||||||
"packages/router": {
|
"packages/router": {
|
||||||
"name": "@wrnexus/router",
|
"name": "@wrnexus/router",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/compiler": "workspace:*",
|
"@wrnexus/compiler": "workspace:*",
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
@@ -554,7 +554,7 @@
|
|||||||
},
|
},
|
||||||
"packages/rpc": {
|
"packages/rpc": {
|
||||||
"name": "@wrnexus/rpc",
|
"name": "@wrnexus/rpc",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/helpers": "workspace:*",
|
"@wrnexus/helpers": "workspace:*",
|
||||||
@@ -568,14 +568,14 @@
|
|||||||
},
|
},
|
||||||
"packages/security": {
|
"packages/security": {
|
||||||
"name": "@wrnexus/security",
|
"name": "@wrnexus/security",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/ssr": {
|
"packages/ssr": {
|
||||||
"name": "@wrnexus/ssr",
|
"name": "@wrnexus/ssr",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/security": "workspace:*",
|
"@wrnexus/security": "workspace:*",
|
||||||
@@ -584,11 +584,11 @@
|
|||||||
},
|
},
|
||||||
"packages/store": {
|
"packages/store": {
|
||||||
"name": "@wrnexus/store",
|
"name": "@wrnexus/store",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/styles": {
|
"packages/styles": {
|
||||||
"name": "@wrnexus/styles",
|
"name": "@wrnexus/styles",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -597,19 +597,19 @@
|
|||||||
},
|
},
|
||||||
"packages/syntax": {
|
"packages/syntax": {
|
||||||
"name": "@wrnexus/syntax",
|
"name": "@wrnexus/syntax",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/test": {
|
"packages/test": {
|
||||||
"name": "@wrnexus/test",
|
"name": "@wrnexus/test",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/tracking": {
|
"packages/tracking": {
|
||||||
"name": "@wrnexus/tracking",
|
"name": "@wrnexus/tracking",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
},
|
},
|
||||||
"packages/typecheck": {
|
"packages/typecheck": {
|
||||||
"name": "@wrnexus/typecheck",
|
"name": "@wrnexus/typecheck",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/syntax": "workspace:*",
|
"@wrnexus/syntax": "workspace:*",
|
||||||
"typescript": "^5.5.0",
|
"typescript": "^5.5.0",
|
||||||
@@ -617,14 +617,14 @@
|
|||||||
},
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/uploader": {
|
"packages/uploader": {
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -638,7 +638,7 @@
|
|||||||
},
|
},
|
||||||
"packages/validation": {
|
"packages/validation": {
|
||||||
"name": "@wrnexus/validation",
|
"name": "@wrnexus/validation",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
|
|||||||
@@ -1830,10 +1830,13 @@
|
|||||||
"htmlToWrn",
|
"htmlToWrn",
|
||||||
"offsetAt",
|
"offsetAt",
|
||||||
"positionAt",
|
"positionAt",
|
||||||
|
"semanticTokens",
|
||||||
|
"semanticTokensLegend",
|
||||||
"symbolLocations",
|
"symbolLocations",
|
||||||
"virtualTypeScriptDocument",
|
"virtualTypeScriptDocument",
|
||||||
"wordAt",
|
"wordAt",
|
||||||
"workspaceCompletionItems"
|
"workspaceCompletionItems",
|
||||||
|
"workspaceSymbolLocations"
|
||||||
],
|
],
|
||||||
"./server": []
|
"./server": []
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,3 +10,5 @@ package-lock.json
|
|||||||
bun.lock
|
bun.lock
|
||||||
../../**
|
../../**
|
||||||
node_modules/**
|
node_modules/**
|
||||||
|
src/*.js
|
||||||
|
src/compiler.cjs
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "wrnexus",
|
"name": "wrnexus",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "wrnexus",
|
"name": "wrnexus",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"license": "SEE LICENSE IN LICENSE",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vscode-languageclient": "^10.1.0"
|
"vscode-languageclient": "^10.1.0"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "wrnexus",
|
"name": "wrnexus",
|
||||||
"displayName": "WRNexus Language Support",
|
"displayName": "WRNexus Language Support",
|
||||||
"description": "Complete WRNexus v0.8.3 language support for typed imports, props, state, outputs, runtime functions, stores, diagnostics, formatting, navigation, and migration assistance.",
|
"description": "Complete WRNexus v0.8.3 language support for typed imports, props, state, outputs, runtime functions, stores, diagnostics, formatting, navigation, and migration assistance.",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"publisher": "wrnexus",
|
"publisher": "wrnexus",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "SEE LICENSE IN LICENSE",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
@@ -275,9 +275,9 @@
|
|||||||
"validate": "node test/validate.mjs && node ../../scripts/build-editor-compiler.mjs --check && node ../../scripts/build-editor-language-server.mjs --check && node ../../scripts/build-editor-extension.mjs --check",
|
"validate": "node test/validate.mjs && node ../../scripts/build-editor-compiler.mjs --check && node ../../scripts/build-editor-language-server.mjs --check && node ../../scripts/build-editor-extension.mjs --check",
|
||||||
"check": "bun run build && bun run test && bun run validate",
|
"check": "bun run build && bun run test && bun run validate",
|
||||||
"vscode:prepublish": "bun run check",
|
"vscode:prepublish": "bun run check",
|
||||||
"package": "vsce package --no-dependencies",
|
"package": "vsce package --no-dependencies --no-rewrite-relative-links",
|
||||||
"publish": "vsce publish --no-dependencies",
|
"publish": "vsce publish --no-dependencies --no-rewrite-relative-links",
|
||||||
"publish:azure": "vsce publish --no-dependencies --azure-credential"
|
"publish:azure": "vsce publish --no-dependencies --no-rewrite-relative-links --azure-credential"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vscode/vsce": "^3.9.2"
|
"@vscode/vsce": "^3.9.2"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+23
-575
@@ -1,321 +1,18 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const vscode = require("vscode");
|
|
||||||
const path = require("node:path");
|
const path = require("node:path");
|
||||||
|
const vscode = require("vscode");
|
||||||
const { LanguageClient, TransportKind } = require("vscode-languageclient/node");
|
const { LanguageClient, TransportKind } = require("vscode-languageclient/node");
|
||||||
|
|
||||||
const { formatWrn } = require("./formatter");
|
|
||||||
|
|
||||||
const { registerCompletionProvider } = require("./completion");
|
|
||||||
|
|
||||||
const { registerDefinitionProvider } = require("./definition");
|
|
||||||
|
|
||||||
const { registerComponentIntelligence } = require("./component-intelligence");
|
|
||||||
|
|
||||||
const { registerDiagnostics } = require("./diagnostics");
|
|
||||||
|
|
||||||
const { registerV060LanguageFeatures } = require("./v060-language");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The WRN compiler is bundled to CommonJS using:
|
|
||||||
*
|
|
||||||
* bun run build:compiler
|
|
||||||
*
|
|
||||||
* Loading is optional so highlighting, formatting, snippets,
|
|
||||||
* autocomplete and navigation continue working when the compiler
|
|
||||||
* bundle is temporarily unavailable.
|
|
||||||
*/
|
|
||||||
let compiler = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
compiler = require("./compiler.cjs");
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(
|
|
||||||
"[wrnexus] compiler bundle not found; compiler diagnostics disabled.",
|
|
||||||
error instanceof Error ? error.message : String(error),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const WRN_LANGUAGE_ID = "wrn";
|
const WRN_LANGUAGE_ID = "wrn";
|
||||||
const COMPILER_DIAGNOSTIC_COLLECTION = "wrnexus-compiler";
|
/** @type {LanguageClient | undefined} */
|
||||||
|
let client;
|
||||||
|
|
||||||
/**
|
/** @param {vscode.TextDocument} document */
|
||||||
* Register the WRN document formatter.
|
|
||||||
*
|
|
||||||
* @param {vscode.ExtensionContext} context
|
|
||||||
*/
|
|
||||||
function registerFormatter(context) {
|
|
||||||
const selector = {
|
|
||||||
language: WRN_LANGUAGE_ID,
|
|
||||||
};
|
|
||||||
|
|
||||||
const provider = vscode.languages.registerDocumentFormattingEditProvider(selector, {
|
|
||||||
provideDocumentFormattingEdits(document, options, token) {
|
|
||||||
if (token.isCancellationRequested) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const configuration = vscode.workspace.getConfiguration("wrnexus", document.uri);
|
|
||||||
|
|
||||||
const enabled = configuration.get("format.enable", true);
|
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const source = document.getText();
|
|
||||||
|
|
||||||
if (!source.trim()) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const printWidth = configuration.get("formatting.printWidth", 100);
|
|
||||||
|
|
||||||
const multilineAttributes = configuration.get("formatting.multilineAttributes", true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const formatted = formatWrn(source, {
|
|
||||||
tabSize: options.tabSize || 4,
|
|
||||||
insertSpaces: options.insertSpaces !== false,
|
|
||||||
printWidth,
|
|
||||||
multilineAttributes,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (typeof formatted !== "string" || formatted === source) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const fullRange = new vscode.Range(
|
|
||||||
document.positionAt(0),
|
|
||||||
document.positionAt(source.length),
|
|
||||||
);
|
|
||||||
|
|
||||||
return [vscode.TextEdit.replace(fullRange, formatted)];
|
|
||||||
} catch (error) {
|
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
|
||||||
|
|
||||||
console.error("[wrnexus] formatting failed:", message);
|
|
||||||
|
|
||||||
vscode.window.showErrorMessage(`WRNexus formatting failed: ${message}`);
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
context.subscriptions.push(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a compiler ParseError into a VS Code diagnostic.
|
|
||||||
*
|
|
||||||
* Compiler errors normally contain:
|
|
||||||
*
|
|
||||||
* at offset 123
|
|
||||||
*
|
|
||||||
* When no offset exists, the diagnostic is attached to the last
|
|
||||||
* line of the document.
|
|
||||||
*
|
|
||||||
* @param {vscode.TextDocument} document
|
|
||||||
* @param {unknown} error
|
|
||||||
* @returns {vscode.Diagnostic}
|
|
||||||
*/
|
|
||||||
function toCompilerDiagnostic(document, error) {
|
|
||||||
const message =
|
|
||||||
error && typeof error === "object" && "message" in error
|
|
||||||
? String(error.message)
|
|
||||||
: "Failed to compile .wrn file.";
|
|
||||||
|
|
||||||
const offsetMatch = /offset\s+(\d+)/i.exec(message);
|
|
||||||
|
|
||||||
let range;
|
|
||||||
|
|
||||||
if (offsetMatch) {
|
|
||||||
const requestedOffset = Number(offsetMatch[1]);
|
|
||||||
|
|
||||||
const safeOffset = Math.max(0, Math.min(requestedOffset, document.getText().length));
|
|
||||||
|
|
||||||
const start = document.positionAt(safeOffset);
|
|
||||||
|
|
||||||
const wordRange = document.getWordRangeAtPosition(start);
|
|
||||||
|
|
||||||
range =
|
|
||||||
wordRange ||
|
|
||||||
new vscode.Range(
|
|
||||||
start,
|
|
||||||
document.positionAt(Math.min(safeOffset + 1, document.getText().length)),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const lastLine = document.lineAt(Math.max(0, document.lineCount - 1));
|
|
||||||
|
|
||||||
range = lastLine.range;
|
|
||||||
}
|
|
||||||
|
|
||||||
const diagnostic = new vscode.Diagnostic(range, message, vscode.DiagnosticSeverity.Error);
|
|
||||||
|
|
||||||
diagnostic.source = "WRNexus Compiler";
|
|
||||||
|
|
||||||
diagnostic.code = "wrn-compiler-error";
|
|
||||||
|
|
||||||
return diagnostic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register diagnostics produced by the actual WRN compiler.
|
|
||||||
*
|
|
||||||
* The lightweight diagnostics in diagnostics.js provide immediate
|
|
||||||
* editor feedback. Compiler diagnostics verify that the document
|
|
||||||
* can also be parsed and generated by the real framework compiler.
|
|
||||||
*
|
|
||||||
* @param {vscode.ExtensionContext} context
|
|
||||||
*/
|
|
||||||
function registerCompilerDiagnostics(context) {
|
|
||||||
const collection = vscode.languages.createDiagnosticCollection(COMPILER_DIAGNOSTIC_COLLECTION);
|
|
||||||
|
|
||||||
const timers = new Map();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {vscode.TextDocument} document
|
|
||||||
*/
|
|
||||||
const run = (document) => {
|
|
||||||
if (document.languageId !== WRN_LANGUAGE_ID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const configuration = vscode.workspace.getConfiguration("wrnexus", document.uri);
|
|
||||||
|
|
||||||
const enabled = configuration.get("diagnostics.enable", true);
|
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
collection.delete(document.uri);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!compiler || typeof compiler.compileWireFile !== "function") {
|
|
||||||
collection.delete(document.uri);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const source = document.getText();
|
|
||||||
|
|
||||||
if (!source.trim()) {
|
|
||||||
collection.delete(document.uri);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
compiler.compileWireFile(source);
|
|
||||||
|
|
||||||
collection.set(document.uri, []);
|
|
||||||
} catch (error) {
|
|
||||||
collection.set(document.uri, [toCompilerDiagnostic(document, error)]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {vscode.TextDocument} document
|
|
||||||
*/
|
|
||||||
const schedule = (document) => {
|
|
||||||
if (document.languageId !== WRN_LANGUAGE_ID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const key = document.uri.toString();
|
|
||||||
|
|
||||||
const existing = timers.get(key);
|
|
||||||
|
|
||||||
if (existing) {
|
|
||||||
clearTimeout(existing);
|
|
||||||
}
|
|
||||||
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
timers.delete(key);
|
|
||||||
run(document);
|
|
||||||
}, 250);
|
|
||||||
|
|
||||||
timers.set(key, timer);
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const document of vscode.workspace.textDocuments) {
|
|
||||||
run(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.subscriptions.push(
|
|
||||||
collection,
|
|
||||||
|
|
||||||
vscode.workspace.onDidOpenTextDocument(run),
|
|
||||||
|
|
||||||
vscode.workspace.onDidChangeTextDocument((event) => {
|
|
||||||
schedule(event.document);
|
|
||||||
}),
|
|
||||||
|
|
||||||
vscode.workspace.onDidSaveTextDocument(run),
|
|
||||||
|
|
||||||
vscode.workspace.onDidCloseTextDocument((document) => {
|
|
||||||
const key = document.uri.toString();
|
|
||||||
|
|
||||||
const timer = timers.get(key);
|
|
||||||
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
timers.delete(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
collection.delete(document.uri);
|
|
||||||
}),
|
|
||||||
|
|
||||||
vscode.workspace.onDidChangeConfiguration((event) => {
|
|
||||||
if (!event.affectsConfiguration("wrnexus.diagnostics.enable")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const document of vscode.workspace.textDocuments) {
|
|
||||||
run(document);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
{
|
|
||||||
dispose() {
|
|
||||||
for (const timer of timers.values()) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
timers.clear();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register semantic highlighting for WRN state declarations and references.
|
|
||||||
*
|
|
||||||
* @param {vscode.ExtensionContext} context
|
|
||||||
*/
|
|
||||||
function registerSemanticTokens(context) {
|
|
||||||
context.subscriptions.push(
|
|
||||||
vscode.languages.registerDocumentSemanticTokensProvider(
|
|
||||||
{
|
|
||||||
language: WRN_LANGUAGE_ID,
|
|
||||||
},
|
|
||||||
wrnSemanticTokensProvider,
|
|
||||||
semanticTokenLegend,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recover files affected by older workspace settings that associated `*.wrn`
|
|
||||||
* with the obsolete `wire` language id. Normal language contribution matching
|
|
||||||
* happens before activation; this fallback is intentionally limited to Plain
|
|
||||||
* Text and the legacy id so explicit third-party associations are respected.
|
|
||||||
*
|
|
||||||
* @param {vscode.TextDocument} document
|
|
||||||
*/
|
|
||||||
async function recoverWrnLanguage(document) {
|
async function recoverWrnLanguage(document) {
|
||||||
if (!document.fileName.toLowerCase().endsWith(".wrn")) return;
|
if (!document.fileName.toLowerCase().endsWith(".wrn")) return;
|
||||||
if (!["plaintext", "wire"].includes(document.languageId)) return;
|
if (!["plaintext", "wire"].includes(document.languageId)) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await vscode.languages.setTextDocumentLanguage(document, WRN_LANGUAGE_ID);
|
await vscode.languages.setTextDocumentLanguage(document, WRN_LANGUAGE_ID);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -326,281 +23,32 @@ async function recoverWrnLanguage(document) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @param {vscode.ExtensionContext} context */
|
||||||
* Activate the WRNexus VS Code extension.
|
|
||||||
*
|
|
||||||
* @param {vscode.ExtensionContext} context
|
|
||||||
*/
|
|
||||||
async function activate(context) {
|
async function activate(context) {
|
||||||
for (const document of vscode.workspace.textDocuments) {
|
for (const document of vscode.workspace.textDocuments) void recoverWrnLanguage(document);
|
||||||
void recoverWrnLanguage(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.workspace.onDidOpenTextDocument((document) => {
|
vscode.workspace.onDidOpenTextDocument((document) => void recoverWrnLanguage(document)),
|
||||||
void recoverWrnLanguage(document);
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const useLanguageServer = vscode.workspace
|
if (!vscode.workspace.getConfiguration("wrnexus").get("languageServer.enable", true)) return;
|
||||||
.getConfiguration("wrnexus")
|
|
||||||
.get("languageServer.enable", true);
|
const module = path.join(context.extensionPath, "src", "language-server.cjs");
|
||||||
let languageServerStarted = false;
|
client = new LanguageClient(
|
||||||
if (useLanguageServer) {
|
"wrnexusLanguageServer",
|
||||||
const module = path.join(context.extensionPath, "src", "language-server.cjs");
|
"WRNexus Language Server",
|
||||||
const serverOptions = {
|
{
|
||||||
run: { module, transport: TransportKind.stdio },
|
run: { module, transport: TransportKind.stdio },
|
||||||
debug: { module, transport: TransportKind.stdio, options: { execArgv: ["--nolazy"] } },
|
debug: { module, transport: TransportKind.stdio, options: { execArgv: ["--nolazy"] } },
|
||||||
};
|
},
|
||||||
const client = new LanguageClient(
|
{ documentSelector: [{ scheme: "file", language: WRN_LANGUAGE_ID }] },
|
||||||
"wrnexusLanguageServer",
|
);
|
||||||
"WRNexus Language Server",
|
await client.start();
|
||||||
serverOptions,
|
|
||||||
{
|
|
||||||
documentSelector: [{ scheme: "file", language: WRN_LANGUAGE_ID }],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
await client.start();
|
|
||||||
languageServerStarted = true;
|
|
||||||
context.subscriptions.push({ dispose: () => void client.stop() });
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(
|
|
||||||
"[wrnexus] language server failed to start; using built-in providers.",
|
|
||||||
error instanceof Error ? error.message : String(error),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!languageServerStarted) {
|
|
||||||
registerDiagnostics(context);
|
|
||||||
registerCompilerDiagnostics(context);
|
|
||||||
registerCompletionProvider(context);
|
|
||||||
registerDefinitionProvider(context);
|
|
||||||
registerFormatter(context);
|
|
||||||
}
|
|
||||||
// Package/local component metadata is not yet part of the LSP workspace
|
|
||||||
// catalog, so keep prop/event completion, hover, and validation available in
|
|
||||||
// both LSP and built-in-provider modes.
|
|
||||||
registerComponentIntelligence(context);
|
|
||||||
registerSemanticTokens(context);
|
|
||||||
registerV060LanguageFeatures(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function deactivate() {}
|
async function deactivate() {
|
||||||
|
const running = client;
|
||||||
const semanticTokenLegend = new vscode.SemanticTokensLegend(
|
client = undefined;
|
||||||
["variable"],
|
if (running) await running.stop();
|
||||||
["declaration", "modification"],
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} value
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function escapeRegExp(value) {
|
|
||||||
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
module.exports = { activate, deactivate, recoverWrnLanguage };
|
||||||
* @param {string} text
|
|
||||||
* @returns {Map<string, Set<number>>}
|
|
||||||
*/
|
|
||||||
function collectStateVariables(text) {
|
|
||||||
const states = new Map();
|
|
||||||
const statePattern = /\bstate\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*(?==|;|\r?$)/gm;
|
|
||||||
|
|
||||||
let match;
|
|
||||||
|
|
||||||
while ((match = statePattern.exec(text)) !== null) {
|
|
||||||
const name = match[1];
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const offset = match.index + match[0].lastIndexOf(name);
|
|
||||||
const declarations = states.get(name) || new Set();
|
|
||||||
|
|
||||||
declarations.add(offset);
|
|
||||||
states.set(name, declarations);
|
|
||||||
}
|
|
||||||
|
|
||||||
return states;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comments are excluded, but quoted attribute expressions are deliberately
|
|
||||||
* included because WRN state references commonly appear in values such as
|
|
||||||
* class:flex="centered" and @click="enabled = !enabled".
|
|
||||||
*
|
|
||||||
* @param {string} text
|
|
||||||
* @returns {Array<{start: number, end: number}>}
|
|
||||||
*/
|
|
||||||
function collectCommentRanges(text) {
|
|
||||||
const ranges = [];
|
|
||||||
let index = 0;
|
|
||||||
let quote = null;
|
|
||||||
let escaped = false;
|
|
||||||
|
|
||||||
while (index < text.length) {
|
|
||||||
const current = text[index];
|
|
||||||
const next = text[index + 1];
|
|
||||||
|
|
||||||
if (quote) {
|
|
||||||
if (escaped) {
|
|
||||||
escaped = false;
|
|
||||||
index++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current === "\\") {
|
|
||||||
escaped = true;
|
|
||||||
index++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current === quote) {
|
|
||||||
quote = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current === '"' || current === "'" || current === "`") {
|
|
||||||
quote = current;
|
|
||||||
index++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current === "/" && next === "/") {
|
|
||||||
const start = index;
|
|
||||||
index += 2;
|
|
||||||
|
|
||||||
while (index < text.length && text[index] !== "\n") {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ranges.push({ start, end: index });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current === "/" && next === "*") {
|
|
||||||
const start = index;
|
|
||||||
index += 2;
|
|
||||||
|
|
||||||
while (index < text.length && !(text[index] === "*" && text[index + 1] === "/")) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
index = Math.min(text.length, index + 2);
|
|
||||||
ranges.push({ start, end: index });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ranges;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} offset
|
|
||||||
* @param {Array<{start: number, end: number}>} ranges
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
function isInsideComment(offset, ranges) {
|
|
||||||
let low = 0;
|
|
||||||
let high = ranges.length - 1;
|
|
||||||
|
|
||||||
while (low <= high) {
|
|
||||||
const middle = Math.floor((low + high) / 2);
|
|
||||||
const range = ranges[middle];
|
|
||||||
|
|
||||||
if (!range) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < range.start) {
|
|
||||||
high = middle - 1;
|
|
||||||
} else if (offset >= range.end) {
|
|
||||||
low = middle + 1;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} text
|
|
||||||
* @param {number} offset
|
|
||||||
* @param {number} length
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
function isStateModification(text, offset, length) {
|
|
||||||
const after = text.slice(offset + length).match(/^\s*(=|\+=|-=|\*=|\/=|%=|\+\+|--)/);
|
|
||||||
|
|
||||||
if (after) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const before = text.slice(Math.max(0, offset - 8), offset).match(/(\+\+|--)\s*$/);
|
|
||||||
|
|
||||||
return Boolean(before);
|
|
||||||
}
|
|
||||||
|
|
||||||
const wrnSemanticTokensProvider = {
|
|
||||||
/**
|
|
||||||
* @param {vscode.TextDocument} document
|
|
||||||
* @param {vscode.CancellationToken} token
|
|
||||||
*/
|
|
||||||
provideDocumentSemanticTokens(document, token) {
|
|
||||||
const builder = new vscode.SemanticTokensBuilder(semanticTokenLegend);
|
|
||||||
const text = document.getText();
|
|
||||||
const states = collectStateVariables(text);
|
|
||||||
const commentRanges = collectCommentRanges(text);
|
|
||||||
|
|
||||||
for (const [name, declarationOffsets] of states) {
|
|
||||||
if (token.isCancellationRequested) {
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
const pattern = new RegExp(`(?<![A-Za-z0-9_$])${escapeRegExp(name)}(?![A-Za-z0-9_$])`, "g");
|
|
||||||
|
|
||||||
let match;
|
|
||||||
|
|
||||||
while ((match = pattern.exec(text)) !== null) {
|
|
||||||
const offset = match.index;
|
|
||||||
|
|
||||||
if (isInsideComment(offset, commentRanges)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const position = document.positionAt(offset);
|
|
||||||
let modifiers = [];
|
|
||||||
|
|
||||||
if (declarationOffsets.has(offset)) {
|
|
||||||
modifiers = ["declaration"];
|
|
||||||
} else if (isStateModification(text, offset, name.length)) {
|
|
||||||
modifiers = ["modification"];
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.push(position.line, position.character, name.length, "variable", modifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
activate,
|
|
||||||
deactivate,
|
|
||||||
registerCompilerDiagnostics,
|
|
||||||
registerFormatter,
|
|
||||||
registerSemanticTokens,
|
|
||||||
recoverWrnLanguage,
|
|
||||||
toCompilerDiagnostic,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
// WRN editor language server source hash: eb2126d09754a516bf6846aea69409578879532f74759f66ae37cf60c961b3bf
|
// WRN editor language server source hash: da83a5e1dbf90523ee0fe9a0d232182b0a78d025f3be8d07c324728d1cdcc17c
|
||||||
// WRN editor language server generator hash: f593a44aaf05495b789ce7a3086bee1eebb951b884d41c0e017bbcfe5f547e72
|
// WRN editor language server generator hash: f593a44aaf05495b789ce7a3086bee1eebb951b884d41c0e017bbcfe5f547e72
|
||||||
// @bun @bun-cjs
|
// @bun @bun-cjs
|
||||||
(function(exports, require, module, __filename, __dirname) {var __create = Object.create;
|
(function(exports, require, module, __filename, __dirname) {var __create = Object.create;
|
||||||
@@ -171925,6 +171925,7 @@ function virtualTypeScriptModule(source, filePath = "component.wrn", appRoot = f
|
|||||||
append(ast.types.join(`
|
append(ast.types.join(`
|
||||||
|
|
||||||
`), ast.types[0]?.trim());
|
`), ast.types[0]?.trim());
|
||||||
|
append('declare const ctx: import("@wrnexus/core").Context;');
|
||||||
for (const prop of ast.props) {
|
for (const prop of ast.props) {
|
||||||
if (!safeBindingName(prop.name))
|
if (!safeBindingName(prop.name))
|
||||||
continue;
|
continue;
|
||||||
@@ -172370,7 +172371,7 @@ var SKIPPED_DIRECTORIES = new Set([
|
|||||||
]);
|
]);
|
||||||
var MAX_INDEX_FILES = 5000;
|
var MAX_INDEX_FILES = 5000;
|
||||||
var MAX_SOURCE_BYTES = 1048576;
|
var MAX_SOURCE_BYTES = 1048576;
|
||||||
var INDEX_TTL_MS = 5000;
|
var INDEX_TTL_MS = 5 * 60000;
|
||||||
var MAX_CACHED_ROOTS = 8;
|
var MAX_CACHED_ROOTS = 8;
|
||||||
var workspaceIndexCache = new Map;
|
var workspaceIndexCache = new Map;
|
||||||
function walk3(root, test) {
|
function walk3(root, test) {
|
||||||
@@ -172494,6 +172495,36 @@ function workspaceCompletionItems(root) {
|
|||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
function clearWorkspaceIndexCache(root) {
|
||||||
|
if (root)
|
||||||
|
workspaceIndexCache.delete(import_node_path3.resolve(root));
|
||||||
|
else
|
||||||
|
workspaceIndexCache.clear();
|
||||||
|
}
|
||||||
|
function workspaceSymbolLocations(root, name, limit = 1000) {
|
||||||
|
if (!/^[A-Za-z_$][\w$]*$/.test(name))
|
||||||
|
return [];
|
||||||
|
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
|
const pattern = new RegExp(`(?<![A-Za-z0-9_$])${escaped}(?![A-Za-z0-9_$])`, "g");
|
||||||
|
const locations = [];
|
||||||
|
for (const file of walk3(import_node_path3.resolve(root), (path) => import_node_path3.extname(path) === ".wrn").slice(0, limit)) {
|
||||||
|
let source;
|
||||||
|
try {
|
||||||
|
source = import_node_fs3.readFileSync(file, "utf8");
|
||||||
|
} catch {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const match of source.matchAll(pattern)) {
|
||||||
|
const before = source.slice(0, match.index).split(/\r?\n/);
|
||||||
|
const start = { line: before.length - 1, character: before.at(-1)?.length ?? 0 };
|
||||||
|
locations.push({
|
||||||
|
uri: `file:///${file.replace(/\\/g, "/")}`,
|
||||||
|
range: { start, end: { line: start.line, character: start.character + name.length } }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
function extractComponentRefactor(document, range, name) {
|
function extractComponentRefactor(document, range, name) {
|
||||||
if (!/^[A-Z][A-Za-z0-9_$]*$/.test(name))
|
if (!/^[A-Z][A-Za-z0-9_$]*$/.test(name))
|
||||||
throw new Error("Component name must use PascalCase");
|
throw new Error("Component name must use PascalCase");
|
||||||
@@ -172599,7 +172630,7 @@ function diagnosticRange(diagnostic) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function documentDiagnostics(document) {
|
function documentDiagnostics(document, options = {}) {
|
||||||
if (Buffer.byteLength(document.text, "utf8") > 1048576) {
|
if (Buffer.byteLength(document.text, "utf8") > 1048576) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -172618,7 +172649,7 @@ function documentDiagnostics(document) {
|
|||||||
source: "wrnexus",
|
source: "wrnexus",
|
||||||
message: diagnostic.message
|
message: diagnostic.message
|
||||||
}));
|
}));
|
||||||
if (syntax.some((diagnostic) => diagnostic.severity === 1))
|
if (syntax.some((diagnostic) => diagnostic.severity === 1) || options.includeTypes === false)
|
||||||
return syntax;
|
return syntax;
|
||||||
const types = checkWrnSource(document.text, { filePath: documentPath(document.uri) }).map((diagnostic) => ({
|
const types = checkWrnSource(document.text, { filePath: documentPath(document.uri) }).map((diagnostic) => ({
|
||||||
range: {
|
range: {
|
||||||
@@ -172688,19 +172719,6 @@ function documentSymbols(document) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function symbolLocations(document, position) {
|
|
||||||
const selected = wordAt(document.text, position);
|
|
||||||
if (!selected)
|
|
||||||
return [];
|
|
||||||
const pattern = new RegExp(`(?<![A-Za-z0-9_$])${selected.word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![A-Za-z0-9_$])`, "g");
|
|
||||||
return [...document.text.matchAll(pattern)].map((match) => ({
|
|
||||||
uri: document.uri,
|
|
||||||
range: {
|
|
||||||
start: positionAt2(document.text, match.index),
|
|
||||||
end: positionAt2(document.text, match.index + selected.word.length)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
function definitionLocation(document, position) {
|
function definitionLocation(document, position) {
|
||||||
const selected = wordAt(document.text, position);
|
const selected = wordAt(document.text, position);
|
||||||
if (!selected)
|
if (!selected)
|
||||||
@@ -172734,6 +172752,55 @@ ${declaration[0]}
|
|||||||
function completionItems() {
|
function completionItems() {
|
||||||
return WRN_COMPLETIONS.map((label) => ({ label, kind: 14, detail: "WRNexus language keyword" }));
|
return WRN_COMPLETIONS.map((label) => ({ label, kind: 14, detail: "WRNexus language keyword" }));
|
||||||
}
|
}
|
||||||
|
var semanticTokenTypes = ["variable"];
|
||||||
|
var semanticTokenModifiers = ["declaration", "modification"];
|
||||||
|
var semanticTokensLegend = {
|
||||||
|
tokenTypes: [...semanticTokenTypes],
|
||||||
|
tokenModifiers: [...semanticTokenModifiers]
|
||||||
|
};
|
||||||
|
function semanticTokens(document) {
|
||||||
|
const declarations = new Map;
|
||||||
|
for (const match of document.text.matchAll(/\bstate\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*(?==|;|\r?$)/gm)) {
|
||||||
|
const name = match[1];
|
||||||
|
const offset = match.index + match[0].lastIndexOf(name);
|
||||||
|
const offsets = declarations.get(name) ?? new Set;
|
||||||
|
offsets.add(offset);
|
||||||
|
declarations.set(name, offsets);
|
||||||
|
}
|
||||||
|
const comments = [...document.text.matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\//g)].map((match) => ({
|
||||||
|
start: match.index,
|
||||||
|
end: match.index + match[0].length
|
||||||
|
}));
|
||||||
|
const tokens = [];
|
||||||
|
for (const [name, offsets] of declarations) {
|
||||||
|
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
|
for (const match of document.text.matchAll(new RegExp(`(?<![A-Za-z0-9_$])${escaped}(?![A-Za-z0-9_$])`, "g"))) {
|
||||||
|
const offset = match.index;
|
||||||
|
if (comments.some((range) => offset >= range.start && offset < range.end))
|
||||||
|
continue;
|
||||||
|
const position = positionAt2(document.text, offset);
|
||||||
|
const after = document.text.slice(offset + name.length).match(/^\s*(?:=|\+=|-=|\*=|\/=|%=|\+\+|--)/);
|
||||||
|
const before = document.text.slice(Math.max(0, offset - 8), offset).match(/(?:\+\+|--)\s*$/);
|
||||||
|
tokens.push({
|
||||||
|
...position,
|
||||||
|
length: name.length,
|
||||||
|
modifiers: offsets.has(offset) ? 1 : after || before ? 2 : 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokens.sort((a, b) => a.line - b.line || a.character - b.character);
|
||||||
|
const data = [];
|
||||||
|
let previousLine = 0;
|
||||||
|
let previousCharacter = 0;
|
||||||
|
for (const token of tokens) {
|
||||||
|
const deltaLine = token.line - previousLine;
|
||||||
|
const deltaCharacter = deltaLine === 0 ? token.character - previousCharacter : token.character;
|
||||||
|
data.push(deltaLine, deltaCharacter, token.length, 0, token.modifiers);
|
||||||
|
previousLine = token.line;
|
||||||
|
previousCharacter = token.character;
|
||||||
|
}
|
||||||
|
return { data };
|
||||||
|
}
|
||||||
|
|
||||||
// packages/language-server/src/server.ts
|
// packages/language-server/src/server.ts
|
||||||
var documents = new Map;
|
var documents = new Map;
|
||||||
@@ -172767,20 +172834,20 @@ function internalDiagnostic(document, error) {
|
|||||||
message: `WRNexus language analysis failed safely: ${message}`
|
message: `WRNexus language analysis failed safely: ${message}`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function safeDocumentDiagnostics(document) {
|
function safeDocumentDiagnostics(document, includeTypes = true) {
|
||||||
try {
|
try {
|
||||||
return documentDiagnostics(document);
|
return documentDiagnostics(document, { includeTypes });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
process.stderr.write(`[wrnexus-lsp] diagnostics failed for ${document.uri}: ${error instanceof Error ? error.stack ?? error.message : String(error)}
|
process.stderr.write(`[wrnexus-lsp] diagnostics failed for ${document.uri}: ${error instanceof Error ? error.stack ?? error.message : String(error)}
|
||||||
`);
|
`);
|
||||||
return [internalDiagnostic(document, error)];
|
return [internalDiagnostic(document, error)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function publish(document) {
|
function publish(document, includeTypes = true) {
|
||||||
send({
|
send({
|
||||||
jsonrpc: "2.0",
|
jsonrpc: "2.0",
|
||||||
method: "textDocument/publishDiagnostics",
|
method: "textDocument/publishDiagnostics",
|
||||||
params: { uri: document.uri, diagnostics: safeDocumentDiagnostics(document) }
|
params: { uri: document.uri, diagnostics: safeDocumentDiagnostics(document, includeTypes) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function clearDiagnosticTimer(uri) {
|
function clearDiagnosticTimer(uri) {
|
||||||
@@ -172796,7 +172863,7 @@ function schedulePublish(document) {
|
|||||||
diagnosticTimers.delete(document.uri);
|
diagnosticTimers.delete(document.uri);
|
||||||
const current = documents.get(document.uri);
|
const current = documents.get(document.uri);
|
||||||
if (current && current.version === expectedVersion)
|
if (current && current.version === expectedVersion)
|
||||||
publish(current);
|
publish(current, false);
|
||||||
}, DIAGNOSTIC_DEBOUNCE_MS));
|
}, DIAGNOSTIC_DEBOUNCE_MS));
|
||||||
}
|
}
|
||||||
function rememberDocument(document) {
|
function rememberDocument(document) {
|
||||||
@@ -172818,7 +172885,7 @@ async function handle(message) {
|
|||||||
result(message.id, {
|
result(message.id, {
|
||||||
serverInfo: { name: "WRNexus Language Server", version: "0.8.3" },
|
serverInfo: { name: "WRNexus Language Server", version: "0.8.3" },
|
||||||
capabilities: {
|
capabilities: {
|
||||||
textDocumentSync: 1,
|
textDocumentSync: { openClose: true, change: 1, save: true },
|
||||||
documentFormattingProvider: true,
|
documentFormattingProvider: true,
|
||||||
completionProvider: { triggerCharacters: ["<", "@", ":", "."] },
|
completionProvider: { triggerCharacters: ["<", "@", ":", "."] },
|
||||||
hoverProvider: true,
|
hoverProvider: true,
|
||||||
@@ -172826,8 +172893,14 @@ async function handle(message) {
|
|||||||
referencesProvider: true,
|
referencesProvider: true,
|
||||||
renameProvider: { prepareProvider: true },
|
renameProvider: { prepareProvider: true },
|
||||||
documentSymbolProvider: true,
|
documentSymbolProvider: true,
|
||||||
|
semanticTokensProvider: { legend: semanticTokensLegend, full: true },
|
||||||
codeActionProvider: {
|
codeActionProvider: {
|
||||||
codeActionKinds: ["quickfix", "refactor.extract", "refactor.rewrite"]
|
codeActionKinds: [
|
||||||
|
"quickfix",
|
||||||
|
"refactor.extract",
|
||||||
|
"refactor.rewrite",
|
||||||
|
"source.organizeImports"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
experimental: { wrnexusVirtualTypeScript: true }
|
experimental: { wrnexusVirtualTypeScript: true }
|
||||||
}
|
}
|
||||||
@@ -172842,6 +172915,10 @@ async function handle(message) {
|
|||||||
result(message.id, null);
|
result(message.id, null);
|
||||||
break;
|
break;
|
||||||
case "exit":
|
case "exit":
|
||||||
|
for (const timer of diagnosticTimers.values())
|
||||||
|
clearTimeout(timer);
|
||||||
|
diagnosticTimers.clear();
|
||||||
|
documents.clear();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
break;
|
break;
|
||||||
case "textDocument/didOpen": {
|
case "textDocument/didOpen": {
|
||||||
@@ -172861,6 +172938,15 @@ async function handle(message) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "textDocument/didSave": {
|
||||||
|
const document = documents.get(params.textDocument.uri);
|
||||||
|
if (document) {
|
||||||
|
clearDiagnosticTimer(document.uri);
|
||||||
|
clearWorkspaceIndexCache(workspaceRoot);
|
||||||
|
publish(document, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "textDocument/didClose":
|
case "textDocument/didClose":
|
||||||
clearDiagnosticTimer(params.textDocument.uri);
|
clearDiagnosticTimer(params.textDocument.uri);
|
||||||
documents.delete(params.textDocument.uri);
|
documents.delete(params.textDocument.uri);
|
||||||
@@ -172890,6 +172976,11 @@ async function handle(message) {
|
|||||||
result(message.id, document ? documentSymbols(document) : []);
|
result(message.id, document ? documentSymbols(document) : []);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "textDocument/semanticTokens/full": {
|
||||||
|
const document = documents.get(params.textDocument.uri);
|
||||||
|
result(message.id, document ? semanticTokens(document) : { data: [] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "textDocument/hover": {
|
case "textDocument/hover": {
|
||||||
const document = documents.get(params.textDocument.uri);
|
const document = documents.get(params.textDocument.uri);
|
||||||
result(message.id, document ? hover(document, params.position) : null);
|
result(message.id, document ? hover(document, params.position) : null);
|
||||||
@@ -172902,7 +172993,8 @@ async function handle(message) {
|
|||||||
}
|
}
|
||||||
case "textDocument/references": {
|
case "textDocument/references": {
|
||||||
const document = documents.get(params.textDocument.uri);
|
const document = documents.get(params.textDocument.uri);
|
||||||
result(message.id, document ? symbolLocations(document, params.position) : []);
|
const selected = document ? wordAt(document.text, params.position) : null;
|
||||||
|
result(message.id, selected ? workspaceSymbolLocations(workspaceRoot, selected.word) : []);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "textDocument/prepareRename": {
|
case "textDocument/prepareRename": {
|
||||||
@@ -172912,11 +173004,16 @@ async function handle(message) {
|
|||||||
}
|
}
|
||||||
case "textDocument/rename": {
|
case "textDocument/rename": {
|
||||||
const document = documents.get(params.textDocument.uri);
|
const document = documents.get(params.textDocument.uri);
|
||||||
const edits = document ? symbolLocations(document, params.position).map(({ range }) => ({
|
const selected = document ? wordAt(document.text, params.position) : null;
|
||||||
range,
|
if (!selected || !/^[A-Za-z_$][\w$]*$/.test(params.newName)) {
|
||||||
newText: params.newName
|
result(message.id, null);
|
||||||
})) : [];
|
break;
|
||||||
result(message.id, document ? { changes: { [document.uri]: edits } } : null);
|
}
|
||||||
|
const changes = {};
|
||||||
|
for (const location of workspaceSymbolLocations(workspaceRoot, selected.word)) {
|
||||||
|
(changes[location.uri] ??= []).push({ range: location.range, newText: params.newName });
|
||||||
|
}
|
||||||
|
result(message.id, { changes });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "textDocument/codeAction": {
|
case "textDocument/codeAction": {
|
||||||
@@ -172937,6 +173034,70 @@ async function handle(message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
const imports = [
|
||||||
|
...document.text.matchAll(/^import(?:\s+type)?[\s\S]*?(?:;\s*|\n(?=import|\s*(?:page|component|layout|global\s+store|page\s+store)\b))/gm)
|
||||||
|
].map((match) => ({
|
||||||
|
start: match.index,
|
||||||
|
end: match.index + match[0].length,
|
||||||
|
text: match[0].trim()
|
||||||
|
}));
|
||||||
|
if (imports.length > 1) {
|
||||||
|
const ordered = [...imports].sort((a, b) => {
|
||||||
|
const aType = /^import\s+type\b/.test(a.text) ? 0 : 1;
|
||||||
|
const bType = /^import\s+type\b/.test(b.text) ? 0 : 1;
|
||||||
|
return aType - bType || a.text.localeCompare(b.text);
|
||||||
|
});
|
||||||
|
const replacement = ordered.map((entry) => entry.text.replace(/;$/, "")).join(`
|
||||||
|
`) + `
|
||||||
|
`;
|
||||||
|
const start = imports[0].start;
|
||||||
|
const end = imports.at(-1).end;
|
||||||
|
if (document.text.slice(start, end) !== replacement) {
|
||||||
|
actions.push({
|
||||||
|
title: "Organize WRN imports",
|
||||||
|
kind: "source.organizeImports",
|
||||||
|
edit: {
|
||||||
|
changes: {
|
||||||
|
[document.uri]: [
|
||||||
|
{
|
||||||
|
range: {
|
||||||
|
start: positionAt2(document.text, start),
|
||||||
|
end: positionAt2(document.text, end)
|
||||||
|
},
|
||||||
|
newText: replacement
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const diagnostic of params.context?.diagnostics ?? []) {
|
||||||
|
if (diagnostic.code !== "WRN-OUTPUT-LEGACY-EMIT")
|
||||||
|
continue;
|
||||||
|
const start = offsetAt(document.text, diagnostic.range.start);
|
||||||
|
const end = offsetAt(document.text, diagnostic.range.end);
|
||||||
|
const source = document.text.slice(start, end);
|
||||||
|
const match = /\$emit\(\s*["']([A-Za-z_$][\w$]*)["']\s*,?/.exec(source);
|
||||||
|
if (!match)
|
||||||
|
continue;
|
||||||
|
actions.push({
|
||||||
|
title: `Convert $emit to output.${match[1]}`,
|
||||||
|
kind: "quickfix",
|
||||||
|
diagnostics: [diagnostic],
|
||||||
|
isPreferred: true,
|
||||||
|
edit: {
|
||||||
|
changes: {
|
||||||
|
[document.uri]: [
|
||||||
|
{
|
||||||
|
range: diagnostic.range,
|
||||||
|
newText: source.replace(/\$emit\(\s*["'][A-Za-z_$][\w$]*["']\s*,?\s*/, `output.${match[1]}(`)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
const selected = document.text.slice(document.text.split(/\r?\n/).slice(0, params.range.start.line).reduce((n, line) => n + line.length + 1, 0) + params.range.start.character, document.text.split(/\r?\n/).slice(0, params.range.end.line).reduce((n, line) => n + line.length + 1, 0) + params.range.end.character);
|
const selected = document.text.slice(document.text.split(/\r?\n/).slice(0, params.range.start.line).reduce((n, line) => n + line.length + 1, 0) + params.range.start.character, document.text.split(/\r?\n/).slice(0, params.range.end.line).reduce((n, line) => n + line.length + 1, 0) + params.range.end.character);
|
||||||
if (selected.trim().startsWith("<")) {
|
if (selected.trim().startsWith("<")) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -68,7 +68,13 @@ test("language server starts under Node and keeps official typed components clea
|
|||||||
messages.push({ jsonrpc: "2.0", method: "exit", params: {} });
|
messages.push({ jsonrpc: "2.0", method: "exit", params: {} });
|
||||||
|
|
||||||
const responses = run(messages);
|
const responses = run(messages);
|
||||||
assert.equal(responses.find((item) => item.id === 1)?.result?.serverInfo?.version, "0.8.3");
|
const initialization = responses.find((item) => item.id === 1)?.result;
|
||||||
|
assert.equal(initialization?.serverInfo?.version, "0.8.3");
|
||||||
|
assert.deepEqual(initialization?.capabilities?.textDocumentSync, {
|
||||||
|
openClose: true,
|
||||||
|
change: 1,
|
||||||
|
save: true,
|
||||||
|
});
|
||||||
const diagnostics = responses.filter((item) => item.method === "textDocument/publishDiagnostics");
|
const diagnostics = responses.filter((item) => item.method === "textDocument/publishDiagnostics");
|
||||||
assert.equal(diagnostics.length, 2);
|
assert.equal(diagnostics.length, 2);
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
@@ -77,6 +83,36 @@ test("language server starts under Node and keeps official typed components clea
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("language server defers expensive type analysis while typing and restores it on save", () => {
|
||||||
|
const uri = "file:///tmp/wrnexus-save-analysis.wrn";
|
||||||
|
const valid = `component SaveAnalysis {
|
||||||
|
outputs { save(payload: { id: string }) }
|
||||||
|
functions { client function submit(): void { output.save({ id: "ok" }) } }
|
||||||
|
view { <button @click="submit()"></button> }
|
||||||
|
}`;
|
||||||
|
const invalid = valid.replace('id: "ok"', "id: 123");
|
||||||
|
const responses = run([
|
||||||
|
{ jsonrpc: "2.0", id: 1, method: "initialize", params: { rootPath: root } },
|
||||||
|
{ jsonrpc: "2.0", method: "initialized", params: {} },
|
||||||
|
{
|
||||||
|
jsonrpc: "2.0",
|
||||||
|
method: "textDocument/didOpen",
|
||||||
|
params: { textDocument: { uri, languageId: "wrn", version: 1, text: valid } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: "2.0",
|
||||||
|
method: "textDocument/didChange",
|
||||||
|
params: { textDocument: { uri, version: 2 }, contentChanges: [{ text: invalid }] },
|
||||||
|
},
|
||||||
|
{ jsonrpc: "2.0", method: "textDocument/didSave", params: { textDocument: { uri } } },
|
||||||
|
{ jsonrpc: "2.0", id: 2, method: "shutdown", params: {} },
|
||||||
|
{ jsonrpc: "2.0", method: "exit", params: {} },
|
||||||
|
]);
|
||||||
|
const diagnostics = responses.filter((item) => item.method === "textDocument/publishDiagnostics");
|
||||||
|
assert.equal(diagnostics.length, 2);
|
||||||
|
assert.ok(diagnostics.at(-1).params.diagnostics.some((item) => item.code === "WRN-TYPE-2322"));
|
||||||
|
});
|
||||||
|
|
||||||
test("language server formatter preserves code samples and compact sibling markup", () => {
|
test("language server formatter preserves code samples and compact sibling markup", () => {
|
||||||
const source = `page Docs {
|
const source = `page Docs {
|
||||||
view {
|
view {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wrnexus",
|
"name": "wrnexus",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "An SSR-first full-stack web framework with server-rendered reactive components. Bun-first, Node-friendly.",
|
"description": "An SSR-first full-stack web framework with server-rendered reactive components. Bun-first, Node-friendly.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ai",
|
"name": "@wrnexus/ai",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/auth",
|
"name": "@wrnexus/auth",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"description": "Complete authentication, account security, MFA, passkeys, recovery, devices, risk, and audit system for WRNexusJS.",
|
"description": "Complete authentication, account security, MFA, passkeys, recovery, devices, risk, and audit system for WRNexusJS.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/authz",
|
"name": "@wrnexus/authz",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/benchmark",
|
"name": "@wrnexus/benchmark",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Deterministic benchmark runner and performance regression budgets for WRNexusJS.",
|
"description": "Deterministic benchmark runner and performance regression budgets for WRNexusJS.",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/cache",
|
"name": "@wrnexus/cache",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Tag-aware memory and response caching with stale-while-revalidate for WRNexusJS.",
|
"description": "Tag-aware memory and response caching with stale-while-revalidate for WRNexusJS.",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/captcha",
|
"name": "@wrnexus/captcha",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"description": "First-class CAPTCHA challenges, providers, verification guards, page gates, and WRNexusJS UI.",
|
"description": "First-class CAPTCHA challenges, providers, verification guards, page gates, and WRNexusJS UI.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
+12
-18
@@ -24,6 +24,12 @@ function literalUnion(values: Iterable<string>): string {
|
|||||||
return unique.length ? unique.map((value) => JSON.stringify(value)).join(" | ") : "never";
|
return unique.length ? unique.map((value) => JSON.stringify(value)).join(" | ") : "never";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generatedContractMap(name: string, members: string): string {
|
||||||
|
return members.trim()
|
||||||
|
? `interface ${name} {\n${members}\n }`
|
||||||
|
: `type ${name} = Record<string, never>;`;
|
||||||
|
}
|
||||||
|
|
||||||
function typeImport(fromDirectory: string, file: string): string {
|
function typeImport(fromDirectory: string, file: string): string {
|
||||||
const path = relative(fromDirectory, file).replace(/\\/g, "/");
|
const path = relative(fromDirectory, file).replace(/\\/g, "/");
|
||||||
return JSON.stringify(path.startsWith(".") ? path : `./${path}`);
|
return JSON.stringify(path.startsWith(".") ? path : `./${path}`);
|
||||||
@@ -203,24 +209,12 @@ declare namespace WRNexusGenerated {
|
|||||||
type TranslationKey = ${literalUnion(localeKeys)};
|
type TranslationKey = ${literalUnion(localeKeys)};
|
||||||
type QueueName = ${literalUnion(queueNames)};
|
type QueueName = ${literalUnion(queueNames)};
|
||||||
type CacheKey = ${literalUnion(cacheKeys)};
|
type CacheKey = ${literalUnion(cacheKeys)};
|
||||||
interface Components {
|
${generatedContractMap("Components", componentMap)}
|
||||||
${componentMap}
|
${generatedContractMap("ApiContracts", apiContracts)}
|
||||||
}
|
${generatedContractMap("MiddlewareContexts", middlewareContracts)}
|
||||||
interface ApiContracts {
|
${generatedContractMap("DatabaseQueries", databaseContracts)}
|
||||||
${apiContracts}
|
${generatedContractMap("RealtimeMessages", realtimeContracts)}
|
||||||
}
|
${generatedContractMap("QueuePayloads", queueContracts)}
|
||||||
interface MiddlewareContexts {
|
|
||||||
${middlewareContracts}
|
|
||||||
}
|
|
||||||
interface DatabaseQueries {
|
|
||||||
${databaseContracts}
|
|
||||||
}
|
|
||||||
interface RealtimeMessages {
|
|
||||||
${realtimeContracts}
|
|
||||||
}
|
|
||||||
interface QueuePayloads {
|
|
||||||
${queueContracts}
|
|
||||||
}
|
|
||||||
type ApplicationConfig = ${configFile ? `(typeof import(${typeImport(typeDir, configFile)}))["default"]` : "Record<string, never>"};
|
type ApplicationConfig = ${configFile ? `(typeof import(${typeImport(typeDir, configFile)}))["default"]` : "Record<string, never>"};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { pathToFileURL } from "node:url";
|
|||||||
import { formatWrn, parse } from "@wrnexus/syntax";
|
import { formatWrn, parse } from "@wrnexus/syntax";
|
||||||
import { AI_GUIDE, CLAUDE_MD } from "./ai-guide.ts";
|
import { AI_GUIDE, CLAUDE_MD } from "./ai-guide.ts";
|
||||||
import { inspectProject, type DoctorCheck } from "./doctor.ts";
|
import { inspectProject, type DoctorCheck } from "./doctor.ts";
|
||||||
|
import { generateApplicationTypes } from "./types.ts";
|
||||||
|
|
||||||
/** The version of the CLI currently running (its own package.json). */
|
/** The version of the CLI currently running (its own package.json). */
|
||||||
function cliVersion(): string {
|
function cliVersion(): string {
|
||||||
@@ -1783,6 +1784,10 @@ const MIGRATIONS: Migration[] = [
|
|||||||
description:
|
description:
|
||||||
"Adds compatible imports, type checking, stores, and legacy behavior configuration.",
|
"Adds compatible imports, type checking, stores, and legacy behavior configuration.",
|
||||||
apply(ctx) {
|
apply(ctx) {
|
||||||
|
// Workspace manifests are updated alongside each configured application,
|
||||||
|
// but they are not themselves runnable apps. Keep app-owned declarations
|
||||||
|
// under the individual app roots instead of creating `<workspace>/app`.
|
||||||
|
if (!existsSync(join(ctx.appRoot, "app", "pages"))) return;
|
||||||
updateV060Config(ctx);
|
updateV060Config(ctx);
|
||||||
const types = join(ctx.appRoot, "app", "types");
|
const types = join(ctx.appRoot, "app", "types");
|
||||||
if (!existsSync(types)) {
|
if (!existsSync(types)) {
|
||||||
@@ -2115,6 +2120,17 @@ const MIGRATIONS: Migration[] = [
|
|||||||
// select for non-link items as well as navigation items.
|
// select for non-link items as well as navigation items.
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
version: "0.8.8",
|
||||||
|
id: "0.8.8-editor-types-and-update-verification",
|
||||||
|
description:
|
||||||
|
"Adds typed page context support and regenerates lint-safe application declarations before update verification.",
|
||||||
|
apply() {
|
||||||
|
// No source rewrite is required. The 0.8.8 CLI regenerates application
|
||||||
|
// declarations immediately before verification, repairing stale empty
|
||||||
|
// interface contracts produced by earlier releases.
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Release tooling uses this to require an explicit migration entry per version. */
|
/** Release tooling uses this to require an explicit migration entry per version. */
|
||||||
@@ -2297,6 +2313,10 @@ export function blockingVerificationChecks(checks: DoctorCheck[]): DoctorCheck[]
|
|||||||
}
|
}
|
||||||
|
|
||||||
function verifyApp(app: UpdatedApp): boolean {
|
function verifyApp(app: UpdatedApp): boolean {
|
||||||
|
// Generated declarations must reflect the newly installed CLI before the
|
||||||
|
// application's lint/typecheck scripts inspect them. This also repairs stale
|
||||||
|
// generated output left by an older framework version.
|
||||||
|
if (existsSync(join(app.root, "app", "pages"))) generateApplicationTypes(app.root);
|
||||||
const health = inspectProject(app.root);
|
const health = inspectProject(app.root);
|
||||||
const failed = blockingVerificationChecks(health);
|
const failed = blockingVerificationChecks(health);
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ test("generate types emits application-wide deterministic contracts", () => {
|
|||||||
expect(output).toContain('"/realtime/chat": RealtimeMessage<');
|
expect(output).toContain('"/realtime/chat": RealtimeMessage<');
|
||||||
expect(output).toContain("interface QueuePayloads");
|
expect(output).toContain("interface QueuePayloads");
|
||||||
expect(output).toContain('"email": QueuePayload<');
|
expect(output).toContain('"email": QueuePayload<');
|
||||||
|
expect(output).toContain("type MiddlewareContexts = Record<string, never>");
|
||||||
|
expect(output).toContain("type DatabaseQueries = Record<string, never>");
|
||||||
|
expect(output).not.toMatch(/interface\s+\w+\s*\{\s*\}/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("application checker validates every wrn source", () => {
|
test("application checker validates every wrn source", () => {
|
||||||
|
|||||||
@@ -169,6 +169,30 @@ test("update verification skips unavailable scripts", () => {
|
|||||||
expect(verificationCommands({ check: "bun run lint" })).toEqual([["run", "check"]]);
|
expect(verificationCommands({ check: "bun run lint" })).toEqual([["run", "check"]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("0.6 type declarations are created only inside runnable apps", () => {
|
||||||
|
const workspaceRoot = mkdtempSync(join(tmpdir(), "wrnexus-update-workspace-"));
|
||||||
|
const appRoot = join(workspaceRoot, "apps", "web");
|
||||||
|
mkdirSync(join(appRoot, "app", "pages"), { recursive: true });
|
||||||
|
writeFileSync(
|
||||||
|
join(workspaceRoot, "package.json"),
|
||||||
|
JSON.stringify({ name: "workspace", wrnexus: { version: "0.5.9" } }),
|
||||||
|
);
|
||||||
|
writeFileSync(
|
||||||
|
join(appRoot, "package.json"),
|
||||||
|
JSON.stringify({ name: "web", wrnexus: { version: "0.5.9" } }),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
updateApp(workspaceRoot, "0.6.0", false);
|
||||||
|
updateApp(appRoot, "0.6.0", false);
|
||||||
|
|
||||||
|
expect(existsSync(join(workspaceRoot, "app", "types", "global.d.ts"))).toBe(false);
|
||||||
|
expect(existsSync(join(appRoot, "app", "types", "global.d.ts"))).toBe(true);
|
||||||
|
} finally {
|
||||||
|
rmSync(workspaceRoot, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test("0.3 WRN source normalization is conservative and idempotent", async () => {
|
test("0.3 WRN source normalization is conservative and idempotent", async () => {
|
||||||
const { migrateWrnSource } = await import("../src/update.ts");
|
const { migrateWrnSource } = await import("../src/update.ts");
|
||||||
const source = `component Card {
|
const source = `component Card {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/content",
|
"name": "@wrnexus/content",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Typed Markdown content collections, loaders, indexes, feeds, and preview workflows for WRNexusJS.",
|
"description": "Typed Markdown content collections, loaders, indexes, feeds, and preview workflows for WRNexusJS.",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/core",
|
"name": "@wrnexus/core",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/db",
|
"name": "@wrnexus/db",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-toolbar",
|
"name": "@wrnexus/dev-toolbar",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/encryption",
|
"name": "@wrnexus/encryption",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/graphql",
|
"name": "@wrnexus/graphql",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/helpers",
|
"name": "@wrnexus/helpers",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/i18n",
|
"name": "@wrnexus/i18n",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/identity",
|
"name": "@wrnexus/identity",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Enterprise federation, provisioning, machine identity, and privacy governance for WRNexusJS.",
|
"description": "Enterprise federation, provisioning, machine identity, and privacy governance for WRNexusJS.",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/image",
|
"name": "@wrnexus/image",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Responsive image planning, secure remote image policies, and performance auditing for WRNexusJS.",
|
"description": "Responsive image planning, secure remote image policies, and performance auditing for WRNexusJS.",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/jwt",
|
"name": "@wrnexus/jwt",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/language-server",
|
"name": "@wrnexus/language-server",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Editor-neutral Language Server Protocol implementation for WRNexus .wrn files.",
|
"description": "Editor-neutral Language Server Protocol implementation for WRNexus .wrn files.",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -75,7 +75,10 @@ function diagnosticRange(diagnostic: WrnDiagnostic): Range {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function documentDiagnostics(document: TextDocument) {
|
export function documentDiagnostics(
|
||||||
|
document: TextDocument,
|
||||||
|
options: { includeTypes?: boolean } = {},
|
||||||
|
) {
|
||||||
if (Buffer.byteLength(document.text, "utf8") > 1_048_576) {
|
if (Buffer.byteLength(document.text, "utf8") > 1_048_576) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -96,7 +99,8 @@ export function documentDiagnostics(document: TextDocument) {
|
|||||||
message: diagnostic.message,
|
message: diagnostic.message,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
if (syntax.some((diagnostic) => diagnostic.severity === 1)) return syntax;
|
if (syntax.some((diagnostic) => diagnostic.severity === 1) || options.includeTypes === false)
|
||||||
|
return syntax;
|
||||||
const types = checkWrnSource(document.text, { filePath: documentPath(document.uri) }).map(
|
const types = checkWrnSource(document.text, { filePath: documentPath(document.uri) }).map(
|
||||||
(diagnostic) => ({
|
(diagnostic) => ({
|
||||||
range: {
|
range: {
|
||||||
@@ -235,4 +239,61 @@ export function hover(document: TextDocument, position: Position) {
|
|||||||
export function completionItems() {
|
export function completionItems() {
|
||||||
return WRN_COMPLETIONS.map((label) => ({ label, kind: 14, detail: "WRNexus language keyword" }));
|
return WRN_COMPLETIONS.map((label) => ({ label, kind: 14, detail: "WRNexus language keyword" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const semanticTokenTypes = ["variable"] as const;
|
||||||
|
const semanticTokenModifiers = ["declaration", "modification"] as const;
|
||||||
|
export const semanticTokensLegend = {
|
||||||
|
tokenTypes: [...semanticTokenTypes],
|
||||||
|
tokenModifiers: [...semanticTokenModifiers],
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Encode state declarations, reads, and writes using the LSP relative token format. */
|
||||||
|
export function semanticTokens(document: TextDocument): { data: number[] } {
|
||||||
|
const declarations = new Map<string, Set<number>>();
|
||||||
|
for (const match of document.text.matchAll(
|
||||||
|
/\bstate\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*(?==|;|\r?$)/gm,
|
||||||
|
)) {
|
||||||
|
const name = match[1]!;
|
||||||
|
const offset = match.index! + match[0].lastIndexOf(name);
|
||||||
|
const offsets = declarations.get(name) ?? new Set<number>();
|
||||||
|
offsets.add(offset);
|
||||||
|
declarations.set(name, offsets);
|
||||||
|
}
|
||||||
|
const comments = [...document.text.matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\//g)].map((match) => ({
|
||||||
|
start: match.index!,
|
||||||
|
end: match.index! + match[0].length,
|
||||||
|
}));
|
||||||
|
const tokens: Array<{ line: number; character: number; length: number; modifiers: number }> = [];
|
||||||
|
for (const [name, offsets] of declarations) {
|
||||||
|
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
|
for (const match of document.text.matchAll(
|
||||||
|
new RegExp(`(?<![A-Za-z0-9_$])${escaped}(?![A-Za-z0-9_$])`, "g"),
|
||||||
|
)) {
|
||||||
|
const offset = match.index!;
|
||||||
|
if (comments.some((range) => offset >= range.start && offset < range.end)) continue;
|
||||||
|
const position = positionAt(document.text, offset);
|
||||||
|
const after = document.text
|
||||||
|
.slice(offset + name.length)
|
||||||
|
.match(/^\s*(?:=|\+=|-=|\*=|\/=|%=|\+\+|--)/);
|
||||||
|
const before = document.text.slice(Math.max(0, offset - 8), offset).match(/(?:\+\+|--)\s*$/);
|
||||||
|
tokens.push({
|
||||||
|
...position,
|
||||||
|
length: name.length,
|
||||||
|
modifiers: offsets.has(offset) ? 1 : after || before ? 2 : 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokens.sort((a, b) => a.line - b.line || a.character - b.character);
|
||||||
|
const data: number[] = [];
|
||||||
|
let previousLine = 0;
|
||||||
|
let previousCharacter = 0;
|
||||||
|
for (const token of tokens) {
|
||||||
|
const deltaLine = token.line - previousLine;
|
||||||
|
const deltaCharacter = deltaLine === 0 ? token.character - previousCharacter : token.character;
|
||||||
|
data.push(deltaLine, deltaCharacter, token.length, 0, token.modifiers);
|
||||||
|
previousLine = token.line;
|
||||||
|
previousCharacter = token.character;
|
||||||
|
}
|
||||||
|
return { data };
|
||||||
|
}
|
||||||
export * from "./workspace.ts";
|
export * from "./workspace.ts";
|
||||||
|
|||||||
@@ -6,10 +6,15 @@ import {
|
|||||||
documentSymbols,
|
documentSymbols,
|
||||||
formatDocument,
|
formatDocument,
|
||||||
hover,
|
hover,
|
||||||
symbolLocations,
|
offsetAt,
|
||||||
|
positionAt,
|
||||||
|
semanticTokens,
|
||||||
|
semanticTokensLegend,
|
||||||
wordAt,
|
wordAt,
|
||||||
virtualTypeScriptDocument,
|
virtualTypeScriptDocument,
|
||||||
workspaceCompletionItems,
|
workspaceCompletionItems,
|
||||||
|
workspaceSymbolLocations,
|
||||||
|
clearWorkspaceIndexCache,
|
||||||
extractComponentRefactor,
|
extractComponentRefactor,
|
||||||
htmlToWrn,
|
htmlToWrn,
|
||||||
type TextDocument,
|
type TextDocument,
|
||||||
@@ -47,9 +52,9 @@ function internalDiagnostic(document: TextDocument, error: unknown) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function safeDocumentDiagnostics(document: TextDocument) {
|
function safeDocumentDiagnostics(document: TextDocument, includeTypes = true) {
|
||||||
try {
|
try {
|
||||||
return documentDiagnostics(document);
|
return documentDiagnostics(document, { includeTypes });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`[wrnexus-lsp] diagnostics failed for ${document.uri}: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\n`,
|
`[wrnexus-lsp] diagnostics failed for ${document.uri}: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\n`,
|
||||||
@@ -58,11 +63,11 @@ function safeDocumentDiagnostics(document: TextDocument) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function publish(document: TextDocument): void {
|
function publish(document: TextDocument, includeTypes = true): void {
|
||||||
send({
|
send({
|
||||||
jsonrpc: "2.0",
|
jsonrpc: "2.0",
|
||||||
method: "textDocument/publishDiagnostics",
|
method: "textDocument/publishDiagnostics",
|
||||||
params: { uri: document.uri, diagnostics: safeDocumentDiagnostics(document) },
|
params: { uri: document.uri, diagnostics: safeDocumentDiagnostics(document, includeTypes) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +85,7 @@ function schedulePublish(document: TextDocument): void {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
diagnosticTimers.delete(document.uri);
|
diagnosticTimers.delete(document.uri);
|
||||||
const current = documents.get(document.uri);
|
const current = documents.get(document.uri);
|
||||||
if (current && current.version === expectedVersion) publish(current);
|
if (current && current.version === expectedVersion) publish(current, false);
|
||||||
}, DIAGNOSTIC_DEBOUNCE_MS),
|
}, DIAGNOSTIC_DEBOUNCE_MS),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -104,7 +109,7 @@ async function handle(message: JsonRpc): Promise<void> {
|
|||||||
result(message.id, {
|
result(message.id, {
|
||||||
serverInfo: { name: "WRNexus Language Server", version: "0.8.3" },
|
serverInfo: { name: "WRNexus Language Server", version: "0.8.3" },
|
||||||
capabilities: {
|
capabilities: {
|
||||||
textDocumentSync: 1,
|
textDocumentSync: { openClose: true, change: 1, save: true },
|
||||||
documentFormattingProvider: true,
|
documentFormattingProvider: true,
|
||||||
completionProvider: { triggerCharacters: ["<", "@", ":", "."] },
|
completionProvider: { triggerCharacters: ["<", "@", ":", "."] },
|
||||||
hoverProvider: true,
|
hoverProvider: true,
|
||||||
@@ -112,8 +117,14 @@ async function handle(message: JsonRpc): Promise<void> {
|
|||||||
referencesProvider: true,
|
referencesProvider: true,
|
||||||
renameProvider: { prepareProvider: true },
|
renameProvider: { prepareProvider: true },
|
||||||
documentSymbolProvider: true,
|
documentSymbolProvider: true,
|
||||||
|
semanticTokensProvider: { legend: semanticTokensLegend, full: true },
|
||||||
codeActionProvider: {
|
codeActionProvider: {
|
||||||
codeActionKinds: ["quickfix", "refactor.extract", "refactor.rewrite"],
|
codeActionKinds: [
|
||||||
|
"quickfix",
|
||||||
|
"refactor.extract",
|
||||||
|
"refactor.rewrite",
|
||||||
|
"source.organizeImports",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
experimental: { wrnexusVirtualTypeScript: true },
|
experimental: { wrnexusVirtualTypeScript: true },
|
||||||
},
|
},
|
||||||
@@ -127,6 +138,9 @@ async function handle(message: JsonRpc): Promise<void> {
|
|||||||
result(message.id, null);
|
result(message.id, null);
|
||||||
break;
|
break;
|
||||||
case "exit":
|
case "exit":
|
||||||
|
for (const timer of diagnosticTimers.values()) clearTimeout(timer);
|
||||||
|
diagnosticTimers.clear();
|
||||||
|
documents.clear();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
break;
|
break;
|
||||||
case "textDocument/didOpen": {
|
case "textDocument/didOpen": {
|
||||||
@@ -146,6 +160,15 @@ async function handle(message: JsonRpc): Promise<void> {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "textDocument/didSave": {
|
||||||
|
const document = documents.get(params.textDocument.uri);
|
||||||
|
if (document) {
|
||||||
|
clearDiagnosticTimer(document.uri);
|
||||||
|
clearWorkspaceIndexCache(workspaceRoot);
|
||||||
|
publish(document, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "textDocument/didClose":
|
case "textDocument/didClose":
|
||||||
clearDiagnosticTimer(params.textDocument.uri);
|
clearDiagnosticTimer(params.textDocument.uri);
|
||||||
documents.delete(params.textDocument.uri);
|
documents.delete(params.textDocument.uri);
|
||||||
@@ -180,6 +203,11 @@ async function handle(message: JsonRpc): Promise<void> {
|
|||||||
result(message.id, document ? documentSymbols(document) : []);
|
result(message.id, document ? documentSymbols(document) : []);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "textDocument/semanticTokens/full": {
|
||||||
|
const document = documents.get(params.textDocument.uri);
|
||||||
|
result(message.id, document ? semanticTokens(document) : { data: [] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "textDocument/hover": {
|
case "textDocument/hover": {
|
||||||
const document = documents.get(params.textDocument.uri);
|
const document = documents.get(params.textDocument.uri);
|
||||||
result(message.id, document ? hover(document, params.position) : null);
|
result(message.id, document ? hover(document, params.position) : null);
|
||||||
@@ -192,7 +220,8 @@ async function handle(message: JsonRpc): Promise<void> {
|
|||||||
}
|
}
|
||||||
case "textDocument/references": {
|
case "textDocument/references": {
|
||||||
const document = documents.get(params.textDocument.uri);
|
const document = documents.get(params.textDocument.uri);
|
||||||
result(message.id, document ? symbolLocations(document, params.position) : []);
|
const selected = document ? wordAt(document.text, params.position) : null;
|
||||||
|
result(message.id, selected ? workspaceSymbolLocations(workspaceRoot, selected.word) : []);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "textDocument/prepareRename": {
|
case "textDocument/prepareRename": {
|
||||||
@@ -202,13 +231,16 @@ async function handle(message: JsonRpc): Promise<void> {
|
|||||||
}
|
}
|
||||||
case "textDocument/rename": {
|
case "textDocument/rename": {
|
||||||
const document = documents.get(params.textDocument.uri);
|
const document = documents.get(params.textDocument.uri);
|
||||||
const edits = document
|
const selected = document ? wordAt(document.text, params.position) : null;
|
||||||
? symbolLocations(document, params.position).map(({ range }) => ({
|
if (!selected || !/^[A-Za-z_$][\w$]*$/.test(params.newName)) {
|
||||||
range,
|
result(message.id, null);
|
||||||
newText: params.newName,
|
break;
|
||||||
}))
|
}
|
||||||
: [];
|
const changes: Record<string, Array<{ range: any; newText: string }>> = {};
|
||||||
result(message.id, document ? { changes: { [document.uri]: edits } } : null);
|
for (const location of workspaceSymbolLocations(workspaceRoot, selected.word)) {
|
||||||
|
(changes[location.uri] ??= []).push({ range: location.range, newText: params.newName });
|
||||||
|
}
|
||||||
|
result(message.id, { changes });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "textDocument/codeAction": {
|
case "textDocument/codeAction": {
|
||||||
@@ -231,6 +263,71 @@ async function handle(message: JsonRpc): Promise<void> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
const imports = [
|
||||||
|
...document.text.matchAll(
|
||||||
|
/^import(?:\s+type)?[\s\S]*?(?:;\s*|\n(?=import|\s*(?:page|component|layout|global\s+store|page\s+store)\b))/gm,
|
||||||
|
),
|
||||||
|
].map((match) => ({
|
||||||
|
start: match.index!,
|
||||||
|
end: match.index! + match[0].length,
|
||||||
|
text: match[0].trim(),
|
||||||
|
}));
|
||||||
|
if (imports.length > 1) {
|
||||||
|
const ordered = [...imports].sort((a, b) => {
|
||||||
|
const aType = /^import\s+type\b/.test(a.text) ? 0 : 1;
|
||||||
|
const bType = /^import\s+type\b/.test(b.text) ? 0 : 1;
|
||||||
|
return aType - bType || a.text.localeCompare(b.text);
|
||||||
|
});
|
||||||
|
const replacement = ordered.map((entry) => entry.text.replace(/;$/, "")).join("\n") + "\n";
|
||||||
|
const start = imports[0]!.start;
|
||||||
|
const end = imports.at(-1)!.end;
|
||||||
|
if (document.text.slice(start, end) !== replacement) {
|
||||||
|
actions.push({
|
||||||
|
title: "Organize WRN imports",
|
||||||
|
kind: "source.organizeImports",
|
||||||
|
edit: {
|
||||||
|
changes: {
|
||||||
|
[document.uri]: [
|
||||||
|
{
|
||||||
|
range: {
|
||||||
|
start: positionAt(document.text, start),
|
||||||
|
end: positionAt(document.text, end),
|
||||||
|
},
|
||||||
|
newText: replacement,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const diagnostic of params.context?.diagnostics ?? []) {
|
||||||
|
if (diagnostic.code !== "WRN-OUTPUT-LEGACY-EMIT") continue;
|
||||||
|
const start = offsetAt(document.text, diagnostic.range.start);
|
||||||
|
const end = offsetAt(document.text, diagnostic.range.end);
|
||||||
|
const source = document.text.slice(start, end);
|
||||||
|
const match = /\$emit\(\s*["']([A-Za-z_$][\w$]*)["']\s*,?/.exec(source);
|
||||||
|
if (!match) continue;
|
||||||
|
actions.push({
|
||||||
|
title: `Convert $emit to output.${match[1]}`,
|
||||||
|
kind: "quickfix",
|
||||||
|
diagnostics: [diagnostic],
|
||||||
|
isPreferred: true,
|
||||||
|
edit: {
|
||||||
|
changes: {
|
||||||
|
[document.uri]: [
|
||||||
|
{
|
||||||
|
range: diagnostic.range,
|
||||||
|
newText: source.replace(
|
||||||
|
/\$emit\(\s*["'][A-Za-z_$][\w$]*["']\s*,?\s*/,
|
||||||
|
`output.${match[1]}(`,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
const selected = document.text.slice(
|
const selected = document.text.slice(
|
||||||
document.text
|
document.text
|
||||||
.split(/\r?\n/)
|
.split(/\r?\n/)
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ const SKIPPED_DIRECTORIES = new Set([
|
|||||||
]);
|
]);
|
||||||
const MAX_INDEX_FILES = 5_000;
|
const MAX_INDEX_FILES = 5_000;
|
||||||
const MAX_SOURCE_BYTES = 1_048_576;
|
const MAX_SOURCE_BYTES = 1_048_576;
|
||||||
const INDEX_TTL_MS = 5_000;
|
// Completion can be requested repeatedly while the list is visible. Avoid
|
||||||
|
// rescanning thousands of files on that hot path; document saves invalidate it.
|
||||||
|
const INDEX_TTL_MS = 5 * 60_000;
|
||||||
const MAX_CACHED_ROOTS = 8;
|
const MAX_CACHED_ROOTS = 8;
|
||||||
const workspaceIndexCache = new Map<
|
const workspaceIndexCache = new Map<
|
||||||
string,
|
string,
|
||||||
@@ -168,6 +170,30 @@ export function clearWorkspaceIndexCache(root?: string): void {
|
|||||||
else workspaceIndexCache.clear();
|
else workspaceIndexCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function workspaceSymbolLocations(root: string, name: string, limit = 1_000) {
|
||||||
|
if (!/^[A-Za-z_$][\w$]*$/.test(name)) return [];
|
||||||
|
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
|
const pattern = new RegExp(`(?<![A-Za-z0-9_$])${escaped}(?![A-Za-z0-9_$])`, "g");
|
||||||
|
const locations: Array<{ uri: string; range: Range }> = [];
|
||||||
|
for (const file of walk(resolve(root), (path) => extname(path) === ".wrn").slice(0, limit)) {
|
||||||
|
let source: string;
|
||||||
|
try {
|
||||||
|
source = readFileSync(file, "utf8");
|
||||||
|
} catch {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const match of source.matchAll(pattern)) {
|
||||||
|
const before = source.slice(0, match.index!).split(/\r?\n/);
|
||||||
|
const start = { line: before.length - 1, character: before.at(-1)?.length ?? 0 };
|
||||||
|
locations.push({
|
||||||
|
uri: `file:///${file.replace(/\\/g, "/")}`,
|
||||||
|
range: { start, end: { line: start.line, character: start.character + name.length } },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
export function extractComponentRefactor(document: TextDocument, range: Range, name: string) {
|
export function extractComponentRefactor(document: TextDocument, range: Range, name: string) {
|
||||||
if (!/^[A-Z][A-Za-z0-9_$]*$/.test(name)) throw new Error("Component name must use PascalCase");
|
if (!/^[A-Z][A-Za-z0-9_$]*$/.test(name)) throw new Error("Component name must use PascalCase");
|
||||||
const lines = document.text.split(/\r?\n/);
|
const lines = document.text.split(/\r?\n/);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/mcp",
|
"name": "@wrnexus/mcp",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Model Context Protocol server exposing WRNexus application and framework context.",
|
"description": "Model Context Protocol server exposing WRNexus application and framework context.",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/mobile",
|
"name": "@wrnexus/mobile",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/native",
|
"name": "@wrnexus/native",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/oauth",
|
"name": "@wrnexus/oauth",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/observability",
|
"name": "@wrnexus/observability",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Metrics, Web Vitals collection, request instrumentation, and exporter adapters for WRNexusJS.",
|
"description": "Metrics, Web Vitals collection, request instrumentation, and exporter adapters for WRNexusJS.",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/playground",
|
"name": "@wrnexus/playground",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Secure, shareable WRNexus compiler and UI playground.",
|
"description": "Secure, shareable WRNexus compiler and UI playground.",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/plugin",
|
"name": "@wrnexus/plugin",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/pubsub",
|
"name": "@wrnexus/pubsub",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/pwa",
|
"name": "@wrnexus/pwa",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Service workers, manifests, offline queues, background sync, push, and conflict resolution for WRNexusJS.",
|
"description": "Service workers, manifests, offline queues, background sync, push, and conflict resolution for WRNexusJS.",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/queue",
|
"name": "@wrnexus/queue",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/reactive",
|
"name": "@wrnexus/reactive",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/realtime",
|
"name": "@wrnexus/realtime",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"description": "Typed realtime rooms, message helpers, presence utilities, package UI blocks, and WRNexusJS integration.",
|
"description": "Typed realtime rooms, message helpers, presence utilities, package UI blocks, and WRNexusJS integration.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/router",
|
"name": "@wrnexus/router",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/rpc",
|
"name": "@wrnexus/rpc",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/security",
|
"name": "@wrnexus/security",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Security policies, safe serialization, SSRF protection, request limits, and secure cookie helpers for WRNexusJS.",
|
"description": "Security policies, safe serialization, SSRF protection, request limits, and secure cookie helpers for WRNexusJS.",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ssr",
|
"name": "@wrnexus/ssr",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/store",
|
"name": "@wrnexus/store",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/styles",
|
"name": "@wrnexus/styles",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/syntax",
|
"name": "@wrnexus/syntax",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/test",
|
"name": "@wrnexus/test",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/tracking",
|
"name": "@wrnexus/tracking",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/typecheck",
|
"name": "@wrnexus/typecheck",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -239,6 +239,10 @@ export function virtualTypeScriptModule(
|
|||||||
|
|
||||||
append(retainedImports(ast), ast.imports[0]);
|
append(retainedImports(ast), ast.imports[0]);
|
||||||
append(ast.types.join("\n\n"), ast.types[0]?.trim());
|
append(ast.types.join("\n\n"), ast.types[0]?.trim());
|
||||||
|
// Pages, components, and stores are rendered with the framework request
|
||||||
|
// context in scope. Mirror the compiler-generated function parameter here so
|
||||||
|
// expressions such as `state user = ctx.user` type-check in the editor.
|
||||||
|
append('declare const ctx: import("@wrnexus/core").Context;');
|
||||||
|
|
||||||
for (const prop of ast.props) {
|
for (const prop of ast.props) {
|
||||||
// JavaScript keywords such as the conventional `class` component prop are
|
// JavaScript keywords such as the conventional `class` component prop are
|
||||||
|
|||||||
@@ -73,3 +73,15 @@ test("treats omitted runtime parameter types as dynamic JavaScript values", () =
|
|||||||
);
|
);
|
||||||
expect(diagnostics.filter((diagnostic) => diagnostic.code.startsWith("WRN-TYPE-"))).toEqual([]);
|
expect(diagnostics.filter((diagnostic) => diagnostic.code.startsWith("WRN-TYPE-"))).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("provides the framework context to page state expressions", () => {
|
||||||
|
const root = app();
|
||||||
|
const diagnostics = checkWrnSource(
|
||||||
|
`page AccountPage {
|
||||||
|
state user = ctx.user
|
||||||
|
view { <main></main> }
|
||||||
|
}`,
|
||||||
|
{ appRoot: root, filePath: join(root, "app", "pages", "account.wrn") },
|
||||||
|
);
|
||||||
|
expect(diagnostics.some((diagnostic) => diagnostic.code === "WRN-TYPE-2304")).toBe(false);
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/validation",
|
"name": "@wrnexus/validation",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
const version = "0.8.7";
|
const version = "0.8.8";
|
||||||
|
|
||||||
const dependencyGroups = [
|
const dependencyGroups = [
|
||||||
"dependencies",
|
"dependencies",
|
||||||
@@ -10,6 +10,11 @@ const dependencyGroups = [
|
|||||||
"optionalDependencies",
|
"optionalDependencies",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const rootPackageFile = "package.json";
|
||||||
|
const rootPackage = JSON.parse(readFileSync(rootPackageFile, "utf8"));
|
||||||
|
rootPackage.version = version;
|
||||||
|
writeFileSync(rootPackageFile, `${JSON.stringify(rootPackage, null, 2)}\n`);
|
||||||
|
|
||||||
for (const entry of readdirSync("packages", {
|
for (const entry of readdirSync("packages", {
|
||||||
withFileTypes: true,
|
withFileTypes: true,
|
||||||
})) {
|
})) {
|
||||||
|
|||||||
Reference in New Issue
Block a user