@wsxjs/wsx-core 0.0.12 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +168 -4
- package/dist/index.mjs +168 -4
- package/package.json +1 -1
- package/src/reactive-decorator.ts +109 -214
package/dist/index.js
CHANGED
|
@@ -1206,17 +1206,177 @@ function deriveTagName(className, prefix) {
|
|
|
1206
1206
|
}
|
|
1207
1207
|
|
|
1208
1208
|
// src/reactive-decorator.ts
|
|
1209
|
-
function state(
|
|
1209
|
+
function state(targetOrContext, propertyKey) {
|
|
1210
|
+
let propertyName;
|
|
1211
|
+
const propertyKeyIsObject = typeof propertyKey === "object" && propertyKey !== null;
|
|
1212
|
+
const targetIsObject = typeof targetOrContext === "object" && targetOrContext !== null;
|
|
1213
|
+
const hasStage3Indicators = targetIsObject && ("kind" in targetOrContext || "addInitializer" in targetOrContext || "access" in targetOrContext);
|
|
1214
|
+
const hasName = hasStage3Indicators && "name" in targetOrContext;
|
|
1215
|
+
const isStage3Decorator = propertyKeyIsObject || hasName || hasStage3Indicators && (propertyKey === void 0 || propertyKey === null) || targetIsObject && "addInitializer" in targetOrContext;
|
|
1216
|
+
if (isStage3Decorator) {
|
|
1217
|
+
const context = targetOrContext;
|
|
1218
|
+
if (context.name) {
|
|
1219
|
+
propertyName = typeof context.name === "string" ? context.name : context.name.toString();
|
|
1220
|
+
} else if (propertyKeyIsObject) {
|
|
1221
|
+
if ("name" in propertyKey) {
|
|
1222
|
+
const keyObj = propertyKey;
|
|
1223
|
+
propertyName = keyObj.name ? typeof keyObj.name === "string" ? keyObj.name : keyObj.name.toString() : "unknown";
|
|
1224
|
+
} else if ("key" in propertyKey) {
|
|
1225
|
+
const keyObj = propertyKey;
|
|
1226
|
+
propertyName = keyObj.key ? typeof keyObj.key === "string" ? keyObj.key : keyObj.key.toString() : "unknown";
|
|
1227
|
+
} else {
|
|
1228
|
+
const keyStr = String(propertyKey);
|
|
1229
|
+
if (keyStr !== "[object Object]") {
|
|
1230
|
+
propertyName = keyStr;
|
|
1231
|
+
} else {
|
|
1232
|
+
propertyName = "unknown";
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
} else {
|
|
1236
|
+
propertyName = "unknown";
|
|
1237
|
+
}
|
|
1238
|
+
} else {
|
|
1239
|
+
if (typeof propertyKey === "string" || typeof propertyKey === "symbol") {
|
|
1240
|
+
propertyName = typeof propertyKey === "string" ? propertyKey : propertyKey.toString();
|
|
1241
|
+
} else if (propertyKey != null) {
|
|
1242
|
+
const propertyKeyStr = String(propertyKey);
|
|
1243
|
+
if (propertyKeyStr === "[object Object]") {
|
|
1244
|
+
propertyName = "unknown";
|
|
1245
|
+
} else {
|
|
1246
|
+
propertyName = propertyKeyStr;
|
|
1247
|
+
}
|
|
1248
|
+
} else {
|
|
1249
|
+
propertyName = "unknown";
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
console.warn(
|
|
1253
|
+
`[WSX] @state decorator is using runtime fallback. Property "${propertyName}" will work but with reduced performance.
|
|
1254
|
+
|
|
1255
|
+
To fix this and enable compile-time processing, please:
|
|
1256
|
+
1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin
|
|
1257
|
+
2. Configure it in vite.config.ts:
|
|
1258
|
+
import { wsx } from '@wsxjs/wsx-vite-plugin';
|
|
1259
|
+
export default defineConfig({ plugins: [wsx()] });
|
|
1260
|
+
3. Configure TypeScript (recommended: use @wsxjs/wsx-tsconfig):
|
|
1261
|
+
npm install --save-dev @wsxjs/wsx-tsconfig
|
|
1262
|
+
Then in tsconfig.json: { "extends": "@wsxjs/wsx-tsconfig/tsconfig.base.json" }
|
|
1263
|
+
Or manually: { "compilerOptions": { "experimentalDecorators": true, "useDefineForClassFields": false } }
|
|
1264
|
+
|
|
1265
|
+
See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
1266
|
+
);
|
|
1267
|
+
if (isStage3Decorator) {
|
|
1268
|
+
let context;
|
|
1269
|
+
if (hasStage3Indicators) {
|
|
1270
|
+
context = targetOrContext;
|
|
1271
|
+
} else if (propertyKeyIsObject) {
|
|
1272
|
+
const keyObj = propertyKey;
|
|
1273
|
+
const targetObj = targetOrContext;
|
|
1274
|
+
const nameValue = targetObj.name || keyObj.name || keyObj.key || "unknown";
|
|
1275
|
+
context = {
|
|
1276
|
+
kind: targetObj.kind || "field",
|
|
1277
|
+
name: nameValue,
|
|
1278
|
+
addInitializer: targetObj.addInitializer || keyObj.addInitializer,
|
|
1279
|
+
access: targetObj.access || keyObj.access
|
|
1280
|
+
};
|
|
1281
|
+
} else {
|
|
1282
|
+
context = targetOrContext;
|
|
1283
|
+
}
|
|
1284
|
+
if (context.kind && context.kind !== "field") {
|
|
1285
|
+
const nameStr = typeof context.name === "string" ? context.name : context.name.toString();
|
|
1286
|
+
throw new Error(
|
|
1287
|
+
`@state decorator can only be used on class fields, not ${context.kind}. Property: "${nameStr}"`
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
if (!context.addInitializer) {
|
|
1291
|
+
console.warn(
|
|
1292
|
+
`[WSX] @state decorator: addInitializer not available for property "${propertyName}". The property will not be reactive. This usually means the decorator system is not properly configured.`
|
|
1293
|
+
);
|
|
1294
|
+
} else {
|
|
1295
|
+
context.addInitializer(function() {
|
|
1296
|
+
if (!this || typeof this.reactive !== "function" || typeof this.useState !== "function") {
|
|
1297
|
+
throw new Error(
|
|
1298
|
+
`@state decorator runtime fallback: Component does not extend WebComponent or LightComponent. Property "${propertyName}" cannot be made reactive.
|
|
1299
|
+
|
|
1300
|
+
The @state decorator can only be used in classes that extend WebComponent or LightComponent. Please ensure your component class extends one of these base classes.`
|
|
1301
|
+
);
|
|
1302
|
+
}
|
|
1303
|
+
let initialValue = void 0;
|
|
1304
|
+
if (context.access?.get) {
|
|
1305
|
+
try {
|
|
1306
|
+
initialValue = context.access.get();
|
|
1307
|
+
} catch {
|
|
1308
|
+
initialValue = this[propertyName];
|
|
1309
|
+
}
|
|
1310
|
+
} else {
|
|
1311
|
+
initialValue = this[propertyName];
|
|
1312
|
+
}
|
|
1313
|
+
const isObject = initialValue !== null && initialValue !== void 0 && (typeof initialValue === "object" || Array.isArray(initialValue));
|
|
1314
|
+
if (isObject) {
|
|
1315
|
+
let reactiveValue = this.reactive(initialValue);
|
|
1316
|
+
Object.defineProperty(this, propertyName, {
|
|
1317
|
+
get: () => reactiveValue,
|
|
1318
|
+
set: (newValue) => {
|
|
1319
|
+
if (newValue !== null && newValue !== void 0 && (typeof newValue === "object" || Array.isArray(newValue))) {
|
|
1320
|
+
reactiveValue = this.reactive(newValue);
|
|
1321
|
+
this.scheduleRerender();
|
|
1322
|
+
} else {
|
|
1323
|
+
reactiveValue = newValue;
|
|
1324
|
+
this.scheduleRerender();
|
|
1325
|
+
}
|
|
1326
|
+
},
|
|
1327
|
+
enumerable: true,
|
|
1328
|
+
configurable: true
|
|
1329
|
+
});
|
|
1330
|
+
} else {
|
|
1331
|
+
const [getState, setState] = this.useState(propertyName, initialValue);
|
|
1332
|
+
Object.defineProperty(this, propertyName, {
|
|
1333
|
+
get: getState,
|
|
1334
|
+
set: setState,
|
|
1335
|
+
enumerable: true,
|
|
1336
|
+
configurable: true
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
return context;
|
|
1342
|
+
}
|
|
1343
|
+
const target = targetOrContext;
|
|
1210
1344
|
let normalizedPropertyKey;
|
|
1211
1345
|
if (typeof propertyKey === "string" || typeof propertyKey === "symbol") {
|
|
1212
1346
|
normalizedPropertyKey = propertyKey;
|
|
1213
|
-
} else {
|
|
1347
|
+
} else if (propertyKey != null) {
|
|
1214
1348
|
const propertyKeyStr = String(propertyKey);
|
|
1215
1349
|
if (propertyKeyStr === "[object Object]") {
|
|
1350
|
+
if (typeof targetOrContext === "object" && targetOrContext !== null && ("kind" in targetOrContext || "addInitializer" in targetOrContext)) {
|
|
1351
|
+
console.warn(
|
|
1352
|
+
`[WSX] @state decorator: Detected potential Stage 3 decorator format but with unexpected propertyKey. This might be a compatibility issue. The decorator will attempt to work in runtime fallback mode.`
|
|
1353
|
+
);
|
|
1354
|
+
const context = targetOrContext;
|
|
1355
|
+
if (context.name) {
|
|
1356
|
+
const name = typeof context.name === "string" ? context.name : context.name.toString();
|
|
1357
|
+
throw new Error(
|
|
1358
|
+
`@state decorator: Detected Stage 3 decorator format but with invalid propertyKey. Property name: "${name}".
|
|
1359
|
+
|
|
1360
|
+
This usually means the decorator is being called in an unexpected format. Please ensure you have configured the Babel plugin correctly.
|
|
1361
|
+
|
|
1362
|
+
To fix this, please:
|
|
1363
|
+
1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin
|
|
1364
|
+
2. Configure it in vite.config.ts:
|
|
1365
|
+
import { wsx } from '@wsxjs/wsx-vite-plugin';
|
|
1366
|
+
export default defineConfig({ plugins: [wsx()] });
|
|
1367
|
+
3. Configure TypeScript (recommended: use @wsxjs/wsx-tsconfig):
|
|
1368
|
+
npm install --save-dev @wsxjs/wsx-tsconfig
|
|
1369
|
+
Then in tsconfig.json: { "extends": "@wsxjs/wsx-tsconfig/tsconfig.base.json" }
|
|
1370
|
+
Or manually: { "compilerOptions": { "experimentalDecorators": true, "useDefineForClassFields": false } }
|
|
1371
|
+
|
|
1372
|
+
See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1216
1376
|
throw new Error(
|
|
1217
|
-
`@state decorator: Invalid propertyKey detected.
|
|
1377
|
+
`@state decorator: Invalid propertyKey detected (received object instead of string/symbol).
|
|
1218
1378
|
|
|
1219
|
-
The @state decorator MUST be processed by Babel plugin at compile time. It appears the Babel plugin is not configured in your build setup.
|
|
1379
|
+
The @state decorator MUST be processed by Babel plugin at compile time. It appears the Babel plugin is not configured in your build setup.
|
|
1220
1380
|
|
|
1221
1381
|
To fix this, please:
|
|
1222
1382
|
1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin
|
|
@@ -1232,6 +1392,10 @@ See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
|
1232
1392
|
);
|
|
1233
1393
|
}
|
|
1234
1394
|
normalizedPropertyKey = propertyKeyStr;
|
|
1395
|
+
} else {
|
|
1396
|
+
throw new Error(
|
|
1397
|
+
`@state decorator: propertyKey is missing. This usually means the decorator is not being called correctly. Please ensure you're using @state on a class field, not a method or other construct.`
|
|
1398
|
+
);
|
|
1235
1399
|
}
|
|
1236
1400
|
if (target == null) {
|
|
1237
1401
|
const propertyKeyStr = typeof normalizedPropertyKey === "string" ? normalizedPropertyKey : normalizedPropertyKey.toString();
|
package/dist/index.mjs
CHANGED
|
@@ -973,17 +973,177 @@ function deriveTagName(className, prefix) {
|
|
|
973
973
|
}
|
|
974
974
|
|
|
975
975
|
// src/reactive-decorator.ts
|
|
976
|
-
function state(
|
|
976
|
+
function state(targetOrContext, propertyKey) {
|
|
977
|
+
let propertyName;
|
|
978
|
+
const propertyKeyIsObject = typeof propertyKey === "object" && propertyKey !== null;
|
|
979
|
+
const targetIsObject = typeof targetOrContext === "object" && targetOrContext !== null;
|
|
980
|
+
const hasStage3Indicators = targetIsObject && ("kind" in targetOrContext || "addInitializer" in targetOrContext || "access" in targetOrContext);
|
|
981
|
+
const hasName = hasStage3Indicators && "name" in targetOrContext;
|
|
982
|
+
const isStage3Decorator = propertyKeyIsObject || hasName || hasStage3Indicators && (propertyKey === void 0 || propertyKey === null) || targetIsObject && "addInitializer" in targetOrContext;
|
|
983
|
+
if (isStage3Decorator) {
|
|
984
|
+
const context = targetOrContext;
|
|
985
|
+
if (context.name) {
|
|
986
|
+
propertyName = typeof context.name === "string" ? context.name : context.name.toString();
|
|
987
|
+
} else if (propertyKeyIsObject) {
|
|
988
|
+
if ("name" in propertyKey) {
|
|
989
|
+
const keyObj = propertyKey;
|
|
990
|
+
propertyName = keyObj.name ? typeof keyObj.name === "string" ? keyObj.name : keyObj.name.toString() : "unknown";
|
|
991
|
+
} else if ("key" in propertyKey) {
|
|
992
|
+
const keyObj = propertyKey;
|
|
993
|
+
propertyName = keyObj.key ? typeof keyObj.key === "string" ? keyObj.key : keyObj.key.toString() : "unknown";
|
|
994
|
+
} else {
|
|
995
|
+
const keyStr = String(propertyKey);
|
|
996
|
+
if (keyStr !== "[object Object]") {
|
|
997
|
+
propertyName = keyStr;
|
|
998
|
+
} else {
|
|
999
|
+
propertyName = "unknown";
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
} else {
|
|
1003
|
+
propertyName = "unknown";
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
if (typeof propertyKey === "string" || typeof propertyKey === "symbol") {
|
|
1007
|
+
propertyName = typeof propertyKey === "string" ? propertyKey : propertyKey.toString();
|
|
1008
|
+
} else if (propertyKey != null) {
|
|
1009
|
+
const propertyKeyStr = String(propertyKey);
|
|
1010
|
+
if (propertyKeyStr === "[object Object]") {
|
|
1011
|
+
propertyName = "unknown";
|
|
1012
|
+
} else {
|
|
1013
|
+
propertyName = propertyKeyStr;
|
|
1014
|
+
}
|
|
1015
|
+
} else {
|
|
1016
|
+
propertyName = "unknown";
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
console.warn(
|
|
1020
|
+
`[WSX] @state decorator is using runtime fallback. Property "${propertyName}" will work but with reduced performance.
|
|
1021
|
+
|
|
1022
|
+
To fix this and enable compile-time processing, please:
|
|
1023
|
+
1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin
|
|
1024
|
+
2. Configure it in vite.config.ts:
|
|
1025
|
+
import { wsx } from '@wsxjs/wsx-vite-plugin';
|
|
1026
|
+
export default defineConfig({ plugins: [wsx()] });
|
|
1027
|
+
3. Configure TypeScript (recommended: use @wsxjs/wsx-tsconfig):
|
|
1028
|
+
npm install --save-dev @wsxjs/wsx-tsconfig
|
|
1029
|
+
Then in tsconfig.json: { "extends": "@wsxjs/wsx-tsconfig/tsconfig.base.json" }
|
|
1030
|
+
Or manually: { "compilerOptions": { "experimentalDecorators": true, "useDefineForClassFields": false } }
|
|
1031
|
+
|
|
1032
|
+
See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
1033
|
+
);
|
|
1034
|
+
if (isStage3Decorator) {
|
|
1035
|
+
let context;
|
|
1036
|
+
if (hasStage3Indicators) {
|
|
1037
|
+
context = targetOrContext;
|
|
1038
|
+
} else if (propertyKeyIsObject) {
|
|
1039
|
+
const keyObj = propertyKey;
|
|
1040
|
+
const targetObj = targetOrContext;
|
|
1041
|
+
const nameValue = targetObj.name || keyObj.name || keyObj.key || "unknown";
|
|
1042
|
+
context = {
|
|
1043
|
+
kind: targetObj.kind || "field",
|
|
1044
|
+
name: nameValue,
|
|
1045
|
+
addInitializer: targetObj.addInitializer || keyObj.addInitializer,
|
|
1046
|
+
access: targetObj.access || keyObj.access
|
|
1047
|
+
};
|
|
1048
|
+
} else {
|
|
1049
|
+
context = targetOrContext;
|
|
1050
|
+
}
|
|
1051
|
+
if (context.kind && context.kind !== "field") {
|
|
1052
|
+
const nameStr = typeof context.name === "string" ? context.name : context.name.toString();
|
|
1053
|
+
throw new Error(
|
|
1054
|
+
`@state decorator can only be used on class fields, not ${context.kind}. Property: "${nameStr}"`
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
if (!context.addInitializer) {
|
|
1058
|
+
console.warn(
|
|
1059
|
+
`[WSX] @state decorator: addInitializer not available for property "${propertyName}". The property will not be reactive. This usually means the decorator system is not properly configured.`
|
|
1060
|
+
);
|
|
1061
|
+
} else {
|
|
1062
|
+
context.addInitializer(function() {
|
|
1063
|
+
if (!this || typeof this.reactive !== "function" || typeof this.useState !== "function") {
|
|
1064
|
+
throw new Error(
|
|
1065
|
+
`@state decorator runtime fallback: Component does not extend WebComponent or LightComponent. Property "${propertyName}" cannot be made reactive.
|
|
1066
|
+
|
|
1067
|
+
The @state decorator can only be used in classes that extend WebComponent or LightComponent. Please ensure your component class extends one of these base classes.`
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
let initialValue = void 0;
|
|
1071
|
+
if (context.access?.get) {
|
|
1072
|
+
try {
|
|
1073
|
+
initialValue = context.access.get();
|
|
1074
|
+
} catch {
|
|
1075
|
+
initialValue = this[propertyName];
|
|
1076
|
+
}
|
|
1077
|
+
} else {
|
|
1078
|
+
initialValue = this[propertyName];
|
|
1079
|
+
}
|
|
1080
|
+
const isObject = initialValue !== null && initialValue !== void 0 && (typeof initialValue === "object" || Array.isArray(initialValue));
|
|
1081
|
+
if (isObject) {
|
|
1082
|
+
let reactiveValue = this.reactive(initialValue);
|
|
1083
|
+
Object.defineProperty(this, propertyName, {
|
|
1084
|
+
get: () => reactiveValue,
|
|
1085
|
+
set: (newValue) => {
|
|
1086
|
+
if (newValue !== null && newValue !== void 0 && (typeof newValue === "object" || Array.isArray(newValue))) {
|
|
1087
|
+
reactiveValue = this.reactive(newValue);
|
|
1088
|
+
this.scheduleRerender();
|
|
1089
|
+
} else {
|
|
1090
|
+
reactiveValue = newValue;
|
|
1091
|
+
this.scheduleRerender();
|
|
1092
|
+
}
|
|
1093
|
+
},
|
|
1094
|
+
enumerable: true,
|
|
1095
|
+
configurable: true
|
|
1096
|
+
});
|
|
1097
|
+
} else {
|
|
1098
|
+
const [getState, setState] = this.useState(propertyName, initialValue);
|
|
1099
|
+
Object.defineProperty(this, propertyName, {
|
|
1100
|
+
get: getState,
|
|
1101
|
+
set: setState,
|
|
1102
|
+
enumerable: true,
|
|
1103
|
+
configurable: true
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
return context;
|
|
1109
|
+
}
|
|
1110
|
+
const target = targetOrContext;
|
|
977
1111
|
let normalizedPropertyKey;
|
|
978
1112
|
if (typeof propertyKey === "string" || typeof propertyKey === "symbol") {
|
|
979
1113
|
normalizedPropertyKey = propertyKey;
|
|
980
|
-
} else {
|
|
1114
|
+
} else if (propertyKey != null) {
|
|
981
1115
|
const propertyKeyStr = String(propertyKey);
|
|
982
1116
|
if (propertyKeyStr === "[object Object]") {
|
|
1117
|
+
if (typeof targetOrContext === "object" && targetOrContext !== null && ("kind" in targetOrContext || "addInitializer" in targetOrContext)) {
|
|
1118
|
+
console.warn(
|
|
1119
|
+
`[WSX] @state decorator: Detected potential Stage 3 decorator format but with unexpected propertyKey. This might be a compatibility issue. The decorator will attempt to work in runtime fallback mode.`
|
|
1120
|
+
);
|
|
1121
|
+
const context = targetOrContext;
|
|
1122
|
+
if (context.name) {
|
|
1123
|
+
const name = typeof context.name === "string" ? context.name : context.name.toString();
|
|
1124
|
+
throw new Error(
|
|
1125
|
+
`@state decorator: Detected Stage 3 decorator format but with invalid propertyKey. Property name: "${name}".
|
|
1126
|
+
|
|
1127
|
+
This usually means the decorator is being called in an unexpected format. Please ensure you have configured the Babel plugin correctly.
|
|
1128
|
+
|
|
1129
|
+
To fix this, please:
|
|
1130
|
+
1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin
|
|
1131
|
+
2. Configure it in vite.config.ts:
|
|
1132
|
+
import { wsx } from '@wsxjs/wsx-vite-plugin';
|
|
1133
|
+
export default defineConfig({ plugins: [wsx()] });
|
|
1134
|
+
3. Configure TypeScript (recommended: use @wsxjs/wsx-tsconfig):
|
|
1135
|
+
npm install --save-dev @wsxjs/wsx-tsconfig
|
|
1136
|
+
Then in tsconfig.json: { "extends": "@wsxjs/wsx-tsconfig/tsconfig.base.json" }
|
|
1137
|
+
Or manually: { "compilerOptions": { "experimentalDecorators": true, "useDefineForClassFields": false } }
|
|
1138
|
+
|
|
1139
|
+
See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
983
1143
|
throw new Error(
|
|
984
|
-
`@state decorator: Invalid propertyKey detected.
|
|
1144
|
+
`@state decorator: Invalid propertyKey detected (received object instead of string/symbol).
|
|
985
1145
|
|
|
986
|
-
The @state decorator MUST be processed by Babel plugin at compile time. It appears the Babel plugin is not configured in your build setup.
|
|
1146
|
+
The @state decorator MUST be processed by Babel plugin at compile time. It appears the Babel plugin is not configured in your build setup.
|
|
987
1147
|
|
|
988
1148
|
To fix this, please:
|
|
989
1149
|
1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin
|
|
@@ -999,6 +1159,10 @@ See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
|
999
1159
|
);
|
|
1000
1160
|
}
|
|
1001
1161
|
normalizedPropertyKey = propertyKeyStr;
|
|
1162
|
+
} else {
|
|
1163
|
+
throw new Error(
|
|
1164
|
+
`@state decorator: propertyKey is missing. This usually means the decorator is not being called correctly. Please ensure you're using @state on a class field, not a method or other construct.`
|
|
1165
|
+
);
|
|
1002
1166
|
}
|
|
1003
1167
|
if (target == null) {
|
|
1004
1168
|
const propertyKeyStr = typeof normalizedPropertyKey === "string" ? normalizedPropertyKey : normalizedPropertyKey.toString();
|
package/package.json
CHANGED
|
@@ -48,241 +48,136 @@ interface DecoratorContext {
|
|
|
48
48
|
addInitializer?(initializer: () => void): void;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Helper function to create error message for missing Babel plugin
|
|
53
|
+
*/
|
|
54
|
+
function createBabelPluginError(propertyName: string): string {
|
|
55
|
+
return (
|
|
56
|
+
`@state decorator on property "${propertyName}" MUST be processed by Babel plugin at compile time. ` +
|
|
57
|
+
`It appears the Babel plugin is not configured in your build setup. ` +
|
|
58
|
+
`\n\n` +
|
|
59
|
+
`The @state decorator cannot work without the Babel plugin. ` +
|
|
60
|
+
`\n\n` +
|
|
61
|
+
`To fix this, please:` +
|
|
62
|
+
`\n1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin` +
|
|
63
|
+
`\n2. Configure it in vite.config.ts:` +
|
|
64
|
+
`\n import { wsx } from '@wsxjs/wsx-vite-plugin';` +
|
|
65
|
+
`\n export default defineConfig({ plugins: [wsx()] });` +
|
|
66
|
+
`\n3. Configure TypeScript (recommended: use @wsxjs/wsx-tsconfig):` +
|
|
67
|
+
`\n npm install --save-dev @wsxjs/wsx-tsconfig` +
|
|
68
|
+
`\n Then in tsconfig.json: { "extends": "@wsxjs/wsx-tsconfig/tsconfig.base.json" }` +
|
|
69
|
+
`\n Or manually: { "compilerOptions": { "experimentalDecorators": true, "useDefineForClassFields": false } }` +
|
|
70
|
+
`\n\n` +
|
|
71
|
+
`See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
51
75
|
export function state(
|
|
52
76
|
targetOrContext: unknown | DecoratorContext,
|
|
53
77
|
propertyKey?: string | symbol | unknown
|
|
54
|
-
|
|
78
|
+
// Compatibility with Babel plugin which is required for this decorator to work properly
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
|
+
): any {
|
|
55
81
|
/**
|
|
56
|
-
* @state decorator
|
|
57
|
-
* 1. Compile-time processing by Babel plugin (preferred) - decorator is removed at compile time
|
|
58
|
-
* 2. Runtime fallback when Babel plugin is not configured - decorator executes at runtime
|
|
59
|
-
*
|
|
82
|
+
* @state decorator MUST be processed by Babel plugin at compile time.
|
|
60
83
|
* If this function is executed at runtime, it means Babel plugin did not process it.
|
|
61
|
-
* We
|
|
84
|
+
* We MUST throw an error - no fallback is allowed.
|
|
62
85
|
*/
|
|
63
86
|
|
|
64
|
-
// Determine property name for
|
|
65
|
-
let propertyName: string;
|
|
66
|
-
if (
|
|
67
|
-
typeof targetOrContext === "object" &&
|
|
68
|
-
targetOrContext !== null &&
|
|
69
|
-
"kind" in targetOrContext &&
|
|
70
|
-
"name" in targetOrContext
|
|
71
|
-
) {
|
|
72
|
-
// Stage 3 decorator format
|
|
73
|
-
const context = targetOrContext as DecoratorContext;
|
|
74
|
-
propertyName = typeof context.name === "string" ? context.name : context.name.toString();
|
|
75
|
-
} else {
|
|
76
|
-
// Legacy decorator format
|
|
77
|
-
if (typeof propertyKey === "string" || typeof propertyKey === "symbol") {
|
|
78
|
-
propertyName = typeof propertyKey === "string" ? propertyKey : propertyKey.toString();
|
|
79
|
-
} else {
|
|
80
|
-
propertyName = String(propertyKey);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Show warning immediately when decorator is executed at runtime
|
|
85
|
-
// This means Babel plugin did not process it
|
|
86
|
-
console.warn(
|
|
87
|
-
`[WSX] @state decorator is using runtime fallback. ` +
|
|
88
|
-
`Property "${propertyName}" will work but with reduced performance. ` +
|
|
89
|
-
`\n\n` +
|
|
90
|
-
`To fix this and enable compile-time processing, please:` +
|
|
91
|
-
`\n1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin` +
|
|
92
|
-
`\n2. Configure it in vite.config.ts:` +
|
|
93
|
-
`\n import { wsx } from '@wsxjs/wsx-vite-plugin';` +
|
|
94
|
-
`\n export default defineConfig({ plugins: [wsx()] });` +
|
|
95
|
-
`\n3. Configure TypeScript (recommended: use @wsxjs/wsx-tsconfig):` +
|
|
96
|
-
`\n npm install --save-dev @wsxjs/wsx-tsconfig` +
|
|
97
|
-
`\n Then in tsconfig.json: { "extends": "@wsxjs/wsx-tsconfig/tsconfig.base.json" }` +
|
|
98
|
-
`\n Or manually: { "compilerOptions": { "experimentalDecorators": true, "useDefineForClassFields": false } }` +
|
|
99
|
-
`\n\n` +
|
|
100
|
-
`See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
101
|
-
);
|
|
87
|
+
// Determine property name for error message
|
|
88
|
+
let propertyName: string = "unknown";
|
|
102
89
|
|
|
103
90
|
// Check if this is a Stage 3 decorator (context object)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
context
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
91
|
+
const propertyKeyIsObject = typeof propertyKey === "object" && propertyKey !== null;
|
|
92
|
+
const targetIsObject = typeof targetOrContext === "object" && targetOrContext !== null;
|
|
93
|
+
|
|
94
|
+
const hasStage3Indicators =
|
|
95
|
+
targetIsObject &&
|
|
96
|
+
("kind" in targetOrContext ||
|
|
97
|
+
"addInitializer" in targetOrContext ||
|
|
98
|
+
"access" in targetOrContext);
|
|
99
|
+
|
|
100
|
+
const hasName = hasStage3Indicators && "name" in targetOrContext;
|
|
101
|
+
|
|
102
|
+
const isStage3Decorator =
|
|
103
|
+
propertyKeyIsObject ||
|
|
104
|
+
hasName ||
|
|
105
|
+
(hasStage3Indicators && (propertyKey === undefined || propertyKey === null)) ||
|
|
106
|
+
(targetIsObject && "addInitializer" in targetOrContext);
|
|
107
|
+
|
|
108
|
+
if (isStage3Decorator) {
|
|
109
|
+
// Stage 3 decorator format - determine property name safely
|
|
110
|
+
if (hasStage3Indicators && targetOrContext && typeof targetOrContext === "object") {
|
|
111
|
+
const context = targetOrContext as DecoratorContext;
|
|
112
|
+
if (context.name) {
|
|
113
|
+
propertyName =
|
|
114
|
+
typeof context.name === "string" ? context.name : context.name.toString();
|
|
115
|
+
}
|
|
116
|
+
} else if (propertyKeyIsObject) {
|
|
117
|
+
// If propertyKey is an object, try to extract name from it
|
|
118
|
+
const keyObj = propertyKey as Record<string, unknown>;
|
|
119
|
+
const targetObj = targetOrContext as Record<string, unknown> | null;
|
|
120
|
+
|
|
121
|
+
// Try to get name from multiple sources
|
|
122
|
+
const nameValue =
|
|
123
|
+
(targetObj?.name as string | symbol | undefined) ||
|
|
124
|
+
(keyObj.name as string | symbol | undefined) ||
|
|
125
|
+
(keyObj.key as string | symbol | undefined);
|
|
126
|
+
|
|
127
|
+
if (nameValue) {
|
|
128
|
+
propertyName = typeof nameValue === "string" ? nameValue : nameValue.toString();
|
|
129
|
+
} else {
|
|
130
|
+
const keyStr = String(propertyKey);
|
|
131
|
+
if (keyStr !== "[object Object]") {
|
|
132
|
+
propertyName = keyStr;
|
|
138
133
|
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
139
136
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
} else {
|
|
151
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
152
|
-
initialValue = (this as any)[propertyName];
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Determine if it's an object/array
|
|
156
|
-
const isObject =
|
|
157
|
-
initialValue !== null &&
|
|
158
|
-
initialValue !== undefined &&
|
|
159
|
-
(typeof initialValue === "object" || Array.isArray(initialValue));
|
|
160
|
-
|
|
161
|
-
if (isObject) {
|
|
162
|
-
// For objects/arrays: use reactive()
|
|
163
|
-
let reactiveValue = this.reactive(initialValue);
|
|
164
|
-
Object.defineProperty(this, propertyName, {
|
|
165
|
-
get: () => reactiveValue,
|
|
166
|
-
set: (newValue: unknown) => {
|
|
167
|
-
// Auto-wrap new values in reactive if they're objects/arrays
|
|
168
|
-
if (
|
|
169
|
-
newValue !== null &&
|
|
170
|
-
newValue !== undefined &&
|
|
171
|
-
(typeof newValue === "object" || Array.isArray(newValue))
|
|
172
|
-
) {
|
|
173
|
-
// Create new reactive value
|
|
174
|
-
reactiveValue = this.reactive(newValue);
|
|
175
|
-
this.scheduleRerender();
|
|
176
|
-
} else {
|
|
177
|
-
// For primitives, just assign (but this shouldn't happen for object properties)
|
|
178
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
179
|
-
reactiveValue = newValue as any;
|
|
180
|
-
this.scheduleRerender();
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
enumerable: true,
|
|
184
|
-
configurable: true,
|
|
185
|
-
});
|
|
186
|
-
} else {
|
|
187
|
-
// For primitives: use useState
|
|
188
|
-
const [getState, setState] = this.useState(propertyName, initialValue);
|
|
189
|
-
Object.defineProperty(this, propertyName, {
|
|
190
|
-
get: getState,
|
|
191
|
-
set: setState,
|
|
192
|
-
enumerable: true,
|
|
193
|
-
configurable: true,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
});
|
|
137
|
+
// Only support field decorators (if kind is specified)
|
|
138
|
+
if (targetIsObject && "kind" in targetOrContext) {
|
|
139
|
+
const context = targetOrContext as DecoratorContext;
|
|
140
|
+
if (context.kind && context.kind !== "field") {
|
|
141
|
+
const nameStr =
|
|
142
|
+
typeof context.name === "string" ? context.name : context.name.toString();
|
|
143
|
+
throw new Error(
|
|
144
|
+
`@state decorator can only be used on class fields, not ${context.kind}. Property: "${nameStr}"`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
197
147
|
}
|
|
198
148
|
|
|
199
|
-
//
|
|
200
|
-
|
|
149
|
+
// If we reach here, the decorator is being executed at runtime
|
|
150
|
+
// This means Babel plugin did not process it - throw error immediately
|
|
151
|
+
throw new Error(createBabelPluginError(propertyName));
|
|
201
152
|
}
|
|
202
153
|
|
|
203
154
|
// Legacy decorator format (experimentalDecorators: true)
|
|
204
155
|
// This should ideally be removed by Babel plugin
|
|
205
|
-
const target = targetOrContext;
|
|
206
|
-
let normalizedPropertyKey: string | symbol;
|
|
207
156
|
if (typeof propertyKey === "string" || typeof propertyKey === "symbol") {
|
|
208
|
-
|
|
209
|
-
} else {
|
|
157
|
+
propertyName = typeof propertyKey === "string" ? propertyKey : propertyKey.toString();
|
|
158
|
+
} else if (propertyKey != null) {
|
|
210
159
|
const propertyKeyStr = String(propertyKey);
|
|
211
160
|
if (propertyKeyStr === "[object Object]") {
|
|
212
|
-
// Invalid propertyKey -
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
`\n\n` +
|
|
229
|
-
`See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
230
|
-
);
|
|
161
|
+
// Invalid propertyKey - this might happen if decorator is called in unexpected format
|
|
162
|
+
// Check if targetOrContext might actually be a Stage 3 context that we missed
|
|
163
|
+
if (
|
|
164
|
+
typeof targetOrContext === "object" &&
|
|
165
|
+
targetOrContext !== null &&
|
|
166
|
+
("kind" in targetOrContext || "addInitializer" in targetOrContext)
|
|
167
|
+
) {
|
|
168
|
+
// This looks like it might be a Stage 3 decorator that we didn't detect properly
|
|
169
|
+
const context = targetOrContext as Partial<DecoratorContext>;
|
|
170
|
+
if (context.name) {
|
|
171
|
+
propertyName =
|
|
172
|
+
typeof context.name === "string" ? context.name : context.name.toString();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
propertyName = propertyKeyStr;
|
|
231
177
|
}
|
|
232
|
-
normalizedPropertyKey = propertyKeyStr;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Basic validation: ensure target is valid
|
|
236
|
-
if (target == null) {
|
|
237
|
-
const propertyKeyStr =
|
|
238
|
-
typeof normalizedPropertyKey === "string"
|
|
239
|
-
? normalizedPropertyKey
|
|
240
|
-
: normalizedPropertyKey.toString();
|
|
241
|
-
throw new Error(
|
|
242
|
-
`@state decorator: Cannot access property "${propertyKeyStr}". ` +
|
|
243
|
-
`Target is ${target === null ? "null" : "undefined"}.` +
|
|
244
|
-
`\n\n` +
|
|
245
|
-
`The @state decorator MUST be processed by Babel plugin at compile time. ` +
|
|
246
|
-
`It appears the Babel plugin is not configured in your build setup.` +
|
|
247
|
-
`\n\n` +
|
|
248
|
-
`To fix this, please:` +
|
|
249
|
-
`\n1. Install @wsxjs/wsx-vite-plugin: npm install @wsxjs/wsx-vite-plugin` +
|
|
250
|
-
`\n2. Configure it in vite.config.ts:` +
|
|
251
|
-
`\n import { wsx } from '@wsxjs/wsx-vite-plugin';` +
|
|
252
|
-
`\n export default defineConfig({ plugins: [wsx()] });` +
|
|
253
|
-
`\n3. Configure TypeScript (recommended: use @wsxjs/wsx-tsconfig):` +
|
|
254
|
-
`\n npm install --save-dev @wsxjs/wsx-tsconfig` +
|
|
255
|
-
`\n Then in tsconfig.json: { "extends": "@wsxjs/wsx-tsconfig/tsconfig.base.json" }` +
|
|
256
|
-
`\n Or manually: { "compilerOptions": { "experimentalDecorators": true, "useDefineForClassFields": false } }` +
|
|
257
|
-
`\n\n` +
|
|
258
|
-
`See: https://github.com/wsxjs/wsxjs#setup for more details.`
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (typeof target !== "object") {
|
|
263
|
-
const propertyKeyStr =
|
|
264
|
-
typeof normalizedPropertyKey === "string"
|
|
265
|
-
? normalizedPropertyKey
|
|
266
|
-
: normalizedPropertyKey.toString();
|
|
267
|
-
throw new Error(
|
|
268
|
-
`@state decorator: Cannot be used on "${propertyKeyStr}". ` +
|
|
269
|
-
`@state is for properties only, not methods.`
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Validate that property has an initial value
|
|
274
|
-
const descriptor = Object.getOwnPropertyDescriptor(target, normalizedPropertyKey);
|
|
275
|
-
if (descriptor?.get) {
|
|
276
|
-
const propertyKeyStr =
|
|
277
|
-
typeof normalizedPropertyKey === "string"
|
|
278
|
-
? normalizedPropertyKey
|
|
279
|
-
: normalizedPropertyKey.toString();
|
|
280
|
-
throw new Error(
|
|
281
|
-
`@state decorator cannot be used with getter properties. Property: "${propertyKeyStr}"`
|
|
282
|
-
);
|
|
283
178
|
}
|
|
284
179
|
|
|
285
|
-
//
|
|
286
|
-
// Babel plugin
|
|
287
|
-
|
|
180
|
+
// If we reach here, the decorator is being executed at runtime
|
|
181
|
+
// This means Babel plugin did not process it - throw error immediately
|
|
182
|
+
throw new Error(createBabelPluginError(propertyName));
|
|
288
183
|
}
|