@wcstack/typescript 3.1.0 → 3.2.0

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.esm.js CHANGED
@@ -566,7 +566,7 @@ function loadSchemaCore() {
566
566
  return cached;
567
567
  }
568
568
 
569
- var version = "3.1.0";
569
+ var version = "3.2.0";
570
570
  var pkg = {
571
571
  version: version};
572
572
 
@@ -150,6 +150,9 @@ var WcsDiagnosticCode = {
150
150
  // タグのメンバー名が "on" で始まる(`once` 等)のに先頭ドット無しで束縛した: ランタイムはイベント束縛にして
151
151
  // "ce" イベントを待ち、値は届かない。明示のプロパティ形 `.once:` を提案する(@wcstack/state 3.1・要件 B5 / 3.x 計画 D36)
152
152
  OnPrefixedMember: "wcs/on-prefixed-member",
153
+ // 3.x の間だけ残る旧名(フィルタ `uc` → `upper`、`$trackDependency` → `$dependOn` …)を書いた(info)。
154
+ // 動くが 4.0 で外れるので正式名を提案する(@wcstack/state 3.2・要件 B12 / 3.x 計画 D39)
155
+ NameAlias: "wcs/name-alias",
153
156
  // wcBindable 無宣言タグ(wcs-fetch-header 等のヘルパー)への spread。
154
157
  // ランタイム(expandSpread)は raiseError で落とす。
155
158
  SpreadNoBindable: "wcs/spread-no-bindable",
@@ -694,6 +697,18 @@ function valueMustBeDate(fnName) {
694
697
  function valueMustBeArray(fnName) {
695
698
  raiseError(`filter ${fnName} requires an array value`);
696
699
  }
700
+ var builtinFilterAliases = {
701
+ inc: "add",
702
+ dec: "sub",
703
+ fix: "toFixed",
704
+ uc: "upper",
705
+ lc: "lower",
706
+ cap: "capitalize",
707
+ rep: "repeat",
708
+ rev: "reverse",
709
+ pad: "padStart",
710
+ null: "nullIfEmpty"
711
+ };
697
712
  function validateNumberString(value) {
698
713
  if (!value || isNaN(Number(value))) {
699
714
  return false;
@@ -789,25 +804,25 @@ var ge = (options) => {
789
804
  };
790
805
  };
791
806
  var inc = (options) => {
792
- const opt = options?.[0] ?? optionsRequired("inc");
807
+ const opt = options?.[0] ?? optionsRequired("add");
793
808
  if (!validateNumberString(opt)) {
794
- optionMustBeNumber("inc");
809
+ optionMustBeNumber("add");
795
810
  }
796
811
  return (value) => {
797
812
  if (typeof value !== "number") {
798
- valueMustBeNumber("inc");
813
+ valueMustBeNumber("add");
799
814
  }
800
815
  return value + Number(opt);
801
816
  };
802
817
  };
803
818
  var dec = (options) => {
804
- const opt = options?.[0] ?? optionsRequired("dec");
819
+ const opt = options?.[0] ?? optionsRequired("sub");
805
820
  if (!validateNumberString(opt)) {
806
- optionMustBeNumber("dec");
821
+ optionMustBeNumber("sub");
807
822
  }
808
823
  return (value) => {
809
824
  if (typeof value !== "number") {
810
- valueMustBeNumber("dec");
825
+ valueMustBeNumber("sub");
811
826
  }
812
827
  return value - Number(opt);
813
828
  };
@@ -877,11 +892,11 @@ var clamp = (options) => {
877
892
  var fix = (options) => {
878
893
  const opt = options?.[0] ?? "0";
879
894
  if (!validateNumberString(opt)) {
880
- optionMustBeNumber("fix");
895
+ optionMustBeNumber("toFixed");
881
896
  }
882
897
  return (value) => {
883
898
  if (typeof value !== "number") {
884
- valueMustBeNumber("fix");
899
+ valueMustBeNumber("toFixed");
885
900
  }
886
901
  return value.toFixed(Number(opt));
887
902
  };
@@ -954,19 +969,29 @@ var substr = (options) => {
954
969
  };
955
970
  };
956
971
  var pad = (options) => {
957
- const opt1 = options?.[0] ?? optionsRequired("pad");
972
+ const opt1 = options?.[0] ?? optionsRequired("padStart");
958
973
  if (!validateNumberString(opt1)) {
959
- optionMustBeNumber("pad");
974
+ optionMustBeNumber("padStart");
960
975
  }
961
976
  const opt2 = options?.[1] ?? "0";
962
977
  return (value) => {
963
978
  return String(value).padStart(Number(opt1), opt2);
964
979
  };
965
980
  };
981
+ var padEnd = (options) => {
982
+ const opt1 = options?.[0] ?? optionsRequired("padEnd");
983
+ if (!validateNumberString(opt1)) {
984
+ optionMustBeNumber("padEnd");
985
+ }
986
+ const opt2 = options?.[1] ?? " ";
987
+ return (value) => {
988
+ return String(value).padEnd(Number(opt1), opt2);
989
+ };
990
+ };
966
991
  var rep = (options) => {
967
- const opt = options?.[0] ?? optionsRequired("rep");
992
+ const opt = options?.[0] ?? optionsRequired("repeat");
968
993
  if (!validateNumberString(opt)) {
969
- optionMustBeNumber("rep");
994
+ optionMustBeNumber("repeat");
970
995
  }
971
996
  return (value) => {
972
997
  return String(value).repeat(Number(opt));
@@ -1138,6 +1163,11 @@ var defaults = (options, literals) => {
1138
1163
  return value;
1139
1164
  };
1140
1165
  };
1166
+ var coalesce = (options, literals) => {
1167
+ const opt = options?.[0] ?? optionsRequired("coalesce");
1168
+ const fallback = literals !== void 0 && literals.length > 0 ? literals[0] : opt;
1169
+ return (value) => value ?? fallback;
1170
+ };
1141
1171
  var boolean = (_options) => {
1142
1172
  return (value) => {
1143
1173
  return Boolean(value);
@@ -1166,24 +1196,25 @@ var builtinFilters = {
1166
1196
  "le": le,
1167
1197
  "gt": gt,
1168
1198
  "ge": ge,
1169
- "inc": inc,
1170
- "dec": dec,
1199
+ "add": inc,
1200
+ "sub": dec,
1171
1201
  "mul": mul,
1172
1202
  "div": div,
1173
1203
  "mod": mod,
1174
1204
  "abs": abs,
1175
1205
  "clamp": clamp,
1176
- "fix": fix,
1206
+ "toFixed": fix,
1177
1207
  "locale": locale,
1178
- "uc": uc,
1179
- "lc": lc,
1180
- "cap": cap,
1208
+ "upper": uc,
1209
+ "lower": lc,
1210
+ "capitalize": cap,
1181
1211
  "trim": trim,
1182
1212
  "slice": slice,
1183
1213
  "substr": substr,
1184
- "pad": pad,
1185
- "rep": rep,
1186
- "rev": rev,
1214
+ "padStart": pad,
1215
+ "padEnd": padEnd,
1216
+ "repeat": rep,
1217
+ "reverse": rev,
1187
1218
  "truncate": truncate,
1188
1219
  "join": join,
1189
1220
  "int": int,
@@ -1201,10 +1232,11 @@ var builtinFilters = {
1201
1232
  "falsy": falsy,
1202
1233
  "truthy": truthy,
1203
1234
  "defaults": defaults,
1235
+ "coalesce": coalesce,
1204
1236
  "boolean": boolean,
1205
1237
  "number": number,
1206
1238
  "string": string,
1207
- "null": _null
1239
+ "nullIfEmpty": _null
1208
1240
  };
1209
1241
  var outputBuiltinFilters = builtinFilters;
1210
1242
  var builtinFilterMeta = {
@@ -1217,26 +1249,27 @@ var builtinFilterMeta = {
1217
1249
  gt: { description: "\u3088\u308A\u5927\u304D\u3044\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1218
1250
  ge: { description: "\u4EE5\u4E0A\u304B", hasArgs: true, resultType: "boolean", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1219
1251
  // 算術
1220
- inc: { description: "\u52A0\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
1221
- dec: { description: "\u6E1B\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
1252
+ add: { description: "\u52A0\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1253
+ sub: { description: "\u6E1B\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1222
1254
  mul: { description: "\u4E57\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1223
1255
  div: { description: "\u9664\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1224
1256
  mod: { description: "\u5270\u4F59", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1225
1257
  abs: { description: "\u7D76\u5BFE\u5024", hasArgs: false, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 0 },
1226
1258
  clamp: { description: "\u7BC4\u56F2\u5185\u306B\u4E38\u3081\u308B (min,max)", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 2, maxArgs: 2, argTypes: ["number", "number"] },
1227
1259
  // 数値フォーマット
1228
- fix: { description: "\u56FA\u5B9A\u5C0F\u6570\u70B9\u8868\u8A18", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
1260
+ toFixed: { description: "\u56FA\u5B9A\u5C0F\u6570\u70B9\u8868\u8A18", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
1229
1261
  locale: { description: "\u30ED\u30B1\u30FC\u30EB\u5F62\u5F0F\u3067\u6570\u5024\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["string"] },
1230
1262
  // 文字列
1231
- uc: { description: "\u5927\u6587\u5B57\u306B\u5909\u63DB", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1232
- lc: { description: "\u5C0F\u6587\u5B57\u306B\u5909\u63DB", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1233
- cap: { description: "\u5148\u982D\u6587\u5B57\u3092\u5927\u6587\u5B57\u306B", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1263
+ upper: { description: "\u5927\u6587\u5B57\u306B\u5909\u63DB", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1264
+ lower: { description: "\u5C0F\u6587\u5B57\u306B\u5909\u63DB", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1265
+ capitalize: { description: "\u5148\u982D\u6587\u5B57\u3092\u5927\u6587\u5B57\u306B", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1234
1266
  trim: { description: "\u524D\u5F8C\u306E\u7A7A\u767D\u3092\u524A\u9664", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1235
1267
  slice: { description: "\u90E8\u5206\u6587\u5B57\u5217 (start[,end])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "number"] },
1236
1268
  substr: { description: "\u90E8\u5206\u6587\u5B57\u5217 (pos,len)", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "number"] },
1237
- pad: { description: "\u30D1\u30C7\u30A3\u30F3\u30B0 (length[,char])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "string"] },
1238
- rep: { description: "\u7E70\u308A\u8FD4\u3057 (count)", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1239
- rev: { description: "\u6587\u5B57\u9806\u3092\u53CD\u8EE2", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1269
+ padStart: { description: "\u5148\u982D\u3092\u57CB\u3081\u308B (length[,char])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "string"] },
1270
+ padEnd: { description: "\u672B\u5C3E\u3092\u57CB\u3081\u308B (length[,char])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "string"] },
1271
+ repeat: { description: "\u7E70\u308A\u8FD4\u3057 (count)", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
1272
+ reverse: { description: "\u6587\u5B57\u9806\u3092\u53CD\u8EE2", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
1240
1273
  truncate: { description: "\u5207\u308A\u8A70\u3081\u3066\u7701\u7565\u8A18\u53F7 (length[,suffix])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "string"] },
1241
1274
  join: { description: "\u914D\u5217\u3092\u9023\u7D50 ([separator])", hasArgs: true, resultType: "string", acceptTypes: ["array"], minArgs: 0, maxArgs: 1, argTypes: ["string"] },
1242
1275
  // 数値パース・丸め
@@ -1259,10 +1292,11 @@ var builtinFilterMeta = {
1259
1292
  falsy: { description: "\u507D\u5024\u304B\u5224\u5B9A", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
1260
1293
  truthy: { description: "\u771F\u5024\u304B\u5224\u5B9A", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
1261
1294
  defaults: { description: "\u507D\u5024\u306E\u5834\u5408\u30C7\u30D5\u30A9\u30EB\u30C8\u5024", hasArgs: true, resultType: "passthrough", acceptTypes: "any", minArgs: 1, maxArgs: 1, argTypes: ["any"] },
1295
+ coalesce: { description: "null / undefined \u306E\u5834\u5408\u30C7\u30D5\u30A9\u30EB\u30C8\u5024", hasArgs: true, resultType: "passthrough", acceptTypes: "any", minArgs: 1, maxArgs: 1, argTypes: ["any"] },
1262
1296
  boolean: { description: "\u30D6\u30FC\u30EB\u5024\u306B\u5909\u63DB", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
1263
1297
  number: { description: "\u6570\u5024\u306B\u5909\u63DB", hasArgs: false, resultType: "number", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
1264
1298
  string: { description: "\u6587\u5B57\u5217\u306B\u5909\u63DB", hasArgs: false, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
1265
- null: { description: "\u7A7A\u6587\u5B57\u5217\u3092null\u306B\u5909\u63DB", hasArgs: false, resultType: "passthrough", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 }
1299
+ nullIfEmpty: { description: "\u7A7A\u6587\u5B57\u5217\u3092null\u306B\u5909\u63DB", hasArgs: false, resultType: "passthrough", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 }
1266
1300
  };
1267
1301
  var STRUCTURAL_BINDING_TYPE_SET = /* @__PURE__ */ new Set([
1268
1302
  "if",
@@ -1307,7 +1341,7 @@ for (let i = 0; i < MAX_WILDCARD_DEPTH; i++) {
1307
1341
  Object.freeze(tmpIndexByIndexName);
1308
1342
  var STATE_CONNECTED_CALLBACK_NAME = "$connectedCallback";
1309
1343
  var STATE_DISCONNECTED_CALLBACK_NAME = "$disconnectedCallback";
1310
- var STATE_UPDATED_CALLBACK_NAME = "$updatedCallback";
1344
+ var STATE_UPDATED_CALLBACK_NAME = "$renderedCallback";
1311
1345
  var STATE_ERROR_CALLBACK_NAME = "$errorCallback";
1312
1346
  var WEBCOMPONENT_STATE_READY_CALLBACK_NAME = "$stateReadyCallback";
1313
1347
  var STATE_BINDABLES_NAME = "$bindables";
@@ -1316,7 +1350,7 @@ var STATE_COMMAND_TOKENS_NAME = "$commandTokens";
1316
1350
  var STATE_COMMAND_NAMESPACE_NAME = "$command";
1317
1351
  var STATE_EVENT_TOKENS_NAME = "$eventTokens";
1318
1352
  var STATE_ON_NAME = "$on";
1319
- var STATE_STREAMS_NAME = "$streams";
1353
+ var STATE_STREAMS_NAME = "$stream";
1320
1354
  var STATE_WATCH_NAME = "$watch";
1321
1355
  var STATE_SCAN_NAME = "$scan";
1322
1356
  var STATE_RECURSION_NAME = "$recursion";
@@ -1366,6 +1400,7 @@ function getWcsManifest() {
1366
1400
  // 実装(Record のキー)から自動導出。手リストを持たない=ドリフトの構造的排除。
1367
1401
  filters: Object.keys(outputBuiltinFilters),
1368
1402
  filterMeta: builtinFilterMeta,
1403
+ filterAliases: builtinFilterAliases,
1369
1404
  reservedLifecycle: [
1370
1405
  STATE_CONNECTED_CALLBACK_NAME,
1371
1406
  STATE_DISCONNECTED_CALLBACK_NAME,
@@ -1392,6 +1427,9 @@ function getWcsManifest() {
1392
1427
  }
1393
1428
 
1394
1429
  // src/service/completionData.ts
1430
+ function canonicalFilterName(name) {
1431
+ return Object.prototype.hasOwnProperty.call(builtinFilterAliases, name) ? builtinFilterAliases[name] : name;
1432
+ }
1395
1433
  var BUILTIN_FILTERS = Object.entries(builtinFilterMeta).map(
1396
1434
  ([name, meta]) => ({ name, ...meta })
1397
1435
  );
@@ -1567,7 +1605,7 @@ function coversSuffix(spec, familySuffix, suffix) {
1567
1605
  }
1568
1606
 
1569
1607
  // src/service/stateAnalyzer.ts
1570
- var RESERVED_STREAMS_KEY = "$streams";
1608
+ var RESERVED_STREAMS_KEYS = /* @__PURE__ */ new Set(["$stream", "$streams"]);
1571
1609
  var RESERVED_COMMAND_TOKENS_KEY = "$commandTokens";
1572
1610
  var RESERVED_EVENT_TOKENS_KEY = "$eventTokens";
1573
1611
  var RESERVED_LIST_KEYS_KEY = "$listKeys";
@@ -1939,7 +1977,7 @@ function findNonObjectDeclaration(scriptContent, key, rejectArray = false) {
1939
1977
  return span;
1940
1978
  }
1941
1979
  function collectReservedKeyPaths(prop, paths, pendingStreamValues, pendingListKeys) {
1942
- if (prop.name === RESERVED_STREAMS_KEY && prop.kind === "data" && prop.value && isObjectLiteral(prop.value)) {
1980
+ if (RESERVED_STREAMS_KEYS.has(prop.name) && prop.kind === "data" && prop.value && isObjectLiteral(prop.value)) {
1943
1981
  const entries = parseTopLevelProperties(extractObjectContent(prop.value));
1944
1982
  for (const entry of entries) {
1945
1983
  if (entry.kind !== "data" || entry.name.startsWith("$")) continue;
@@ -3068,6 +3106,7 @@ var ja = {
3068
3106
  arrayMutation: (m, alt) => `\u914D\u5217\u306E\u7834\u58CA\u7684\u30E1\u30BD\u30C3\u30C9 "${m}" \u306F\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\uFF08\u540C\u4E00\u53C2\u7167\u306E\u81EA\u5DF1\u518D\u4EE3\u5165\u3067\u3082\u8981\u7D20\u306E\u8FFD\u52A0\u30FB\u524A\u9664\u306F\u53CD\u6620\u3055\u308C\u307E\u305B\u3093\uFF09\u3002\u975E\u7834\u58CA\u30E1\u30BD\u30C3\u30C9\u3068\u518D\u4EE3\u5165\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: ${alt}\uFF09\u3002`,
3069
3107
  arrayIndexAssign: (sp) => `\u914D\u5217\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3078\u306E\u76F4\u63A5\u4EE3\u5165\u306F\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\u3002this["${sp}"] \u306E\u3088\u3046\u306A\u30C9\u30C3\u30C8\u30D1\u30B9\u4EE3\u5165\u3001\u307E\u305F\u306F with() \u3068\u518D\u4EE3\u5165\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002`,
3070
3108
  tagMemberUnknown: (prop, tag) => `"${prop}" \u306F <${tag}> \u306E wcBindable \u30E1\u30F3\u30D0\u30FC\u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF08\u672A\u77E5\u30E1\u30F3\u30D0\u30FC\u3078\u306E\u30D0\u30A4\u30F3\u30C9\u306F\u9ED9\u3063\u3066\u7121\u8996\u3055\u308C\u307E\u3059\uFF09`,
3109
+ nameAlias: (written, canonical) => `"${written}" \u306F "${canonical}" \u306E\u65E7\u540D\u3067\u3059\u30023.x \u306E\u9593\u306F\u52D5\u304D\u307E\u3059\u304C 4.0 \u3067\u5916\u308C\u308B\u306E\u3067\u3001"${canonical}" \u3068\u66F8\u3044\u3066\u304F\u3060\u3055\u3044\uFF08@wcstack/state 3.2\uFF09`,
3071
3110
  onPrefixedMember: (member, tag) => `"${member}" \u306F <${tag}> \u306E\u30E1\u30F3\u30D0\u30FC\u3067\u3059\u304C\u3001"on" \u3067\u59CB\u307E\u308B\u540D\u524D\u306F\u30A4\u30D9\u30F3\u30C8\u675F\u7E1B\u306B\u306A\u308A\uFF08"${member.slice(2)}" \u30A4\u30D9\u30F3\u30C8\u3092\u5F85\u3064\uFF09\u3001\u5024\u306F\u5C4A\u304D\u307E\u305B\u3093\u3002\u30D7\u30ED\u30D1\u30C6\u30A3\u3068\u3057\u3066\u675F\u7E1B\u3059\u308B\u306B\u306F ".${member}:" \u3068\u66F8\u3044\u3066\u304F\u3060\u3055\u3044\uFF08@wcstack/state 3.1\uFF09`,
3072
3111
  tagCommandUnknown: (name, tag, declared) => `"${name}" \u306F <${tag}> \u306E command \u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF08\u5BA3\u8A00\u6E08\u307F: ${declared}\uFF09`,
3073
3112
  spreadNoBindable: (tag) => `'...'\uFF08spread\uFF09\u306F <${tag}> \u306B\u6709\u52B9\u306A wcBindable \u5BA3\u8A00\u304C\u5FC5\u8981\u3067\u3059 \u2014 \u3053\u306E\u30BF\u30B0\u306F\u5BA3\u8A00\u3092\u6301\u305F\u306A\u3044\u305F\u3081\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u30A8\u30E9\u30FC\u3092\u9001\u51FA\u3057\u307E\u3059`,
@@ -3258,6 +3297,7 @@ var en = {
3258
3297
  arrayMutation: (m, alt) => `Destructive array method "${m}" does not trigger a reactive update (re-assigning the same reference does not reflect added/removed elements either). Use a non-destructive method with reassignment (e.g. ${alt}).`,
3259
3298
  arrayIndexAssign: (sp) => `Assigning directly to an array index does not trigger a reactive update. Use a dot-path assignment like this["${sp}"], or with() plus reassignment.`,
3260
3299
  tagMemberUnknown: (prop, tag) => `"${prop}" is not a wcBindable member of <${tag}> (bindings to unknown members are silently ignored)`,
3300
+ nameAlias: (written, canonical) => `"${written}" is the old name of "${canonical}". It works through 3.x and goes in 4.0 \u2014 write "${canonical}" (@wcstack/state 3.2)`,
3261
3301
  onPrefixedMember: (member, tag) => `"${member}" is a member of <${tag}>, but a name starting with "on" makes an event binding (it listens for a "${member.slice(2)}" event) and the value never arrives. Write ".${member}:" to bind the property (@wcstack/state 3.1)`,
3262
3302
  tagCommandUnknown: (name, tag, declared) => `"${name}" is not a command of <${tag}> (declared: ${declared})`,
3263
3303
  spreadNoBindable: (tag) => `'...' (spread) requires <${tag}> to expose a valid wcBindable declaration \u2014 this tag declares none, so the runtime raises an error`,
@@ -3391,7 +3431,6 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale2, f
3391
3431
  structuralTemplates ??= collectStructuralTemplates(html, attrName);
3392
3432
  return structuralTemplates;
3393
3433
  };
3394
- const filterNameSet = new Set(BUILTIN_FILTERS.map((f) => f.name));
3395
3434
  for (const attr of attrs) {
3396
3435
  const bindings = splitBindingExpressions(attr.value);
3397
3436
  const nonEmptyCount = bindings.filter((b) => b.trim().length > 0).length;
@@ -3725,7 +3764,17 @@ function parseFilterSegments(expr, segments, searchStart) {
3725
3764
  }
3726
3765
  function validateFilterUsage(filter, bindingStart, msgs) {
3727
3766
  const diagnostics = [];
3728
- const info = filterMap.get(filter.name);
3767
+ const canonical = canonicalFilterName(filter.name);
3768
+ const info = filterMap.get(canonical);
3769
+ if (info && canonical !== filter.name) {
3770
+ diagnostics.push({
3771
+ code: WcsDiagnosticCode.NameAlias,
3772
+ start: bindingStart + filter.offset,
3773
+ end: bindingStart + filter.offset + filter.name.length,
3774
+ message: msgs.nameAlias(filter.name, canonical),
3775
+ severity: "info"
3776
+ });
3777
+ }
3729
3778
  if (!info) {
3730
3779
  diagnostics.push({
3731
3780
  code: WcsDiagnosticCode.FilterUnknown,
@@ -4355,8 +4404,17 @@ function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", l
4355
4404
  }
4356
4405
  for (let i = 1; i < parts.length; i++) {
4357
4406
  const filterName = parts[i].trim().replace(/\(.*$/, "");
4358
- if (filterName && !filterNameSet.has(filterName)) {
4359
- const filterOffset = item.expression.indexOf(parts[i]);
4407
+ const filterOffset = item.expression.indexOf(parts[i]) + (parts[i].length - parts[i].trimStart().length);
4408
+ const canonical = canonicalFilterName(filterName);
4409
+ if (filterName && canonical !== filterName && filterNameSet.has(canonical)) {
4410
+ diagnostics.push({
4411
+ code: WcsDiagnosticCode.NameAlias,
4412
+ start: item.exprStart + filterOffset,
4413
+ end: item.exprStart + filterOffset + filterName.length,
4414
+ message: msgs.nameAlias(filterName, canonical),
4415
+ severity: "info"
4416
+ });
4417
+ } else if (filterName && !filterNameSet.has(filterName)) {
4360
4418
  diagnostics.push({
4361
4419
  code: WcsDiagnosticCode.FilterUnknown,
4362
4420
  start: item.exprStart + filterOffset,
@@ -7114,7 +7172,8 @@ var RECURSION_APIS = ["getAll", "setAll", "resolve", "postUpdate", "trackDepende
7114
7172
  var UNSUPPORTED_API_SITE = {
7115
7173
  $resolve: "resolve",
7116
7174
  $postUpdate: "postUpdate",
7117
- $trackDependency: "trackDependency"
7175
+ $trackDependency: "trackDependency",
7176
+ $dependOn: "trackDependency"
7118
7177
  };
7119
7178
  var BRACKET_ASSIGNMENT = new RegExp(`${ROOT_BRACKET}${ASSIGN_TAIL}`, "g");
7120
7179
  var PRE_BRACKET_INCDEC = new RegExp(`${PRE_INCDEC}${ROOT_BRACKET}`, "g");
@@ -10074,16 +10133,16 @@ pp$5.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, forInit)
10074
10133
  if (prec != null && (!forInit || this.type !== types$1._in)) {
10075
10134
  if (prec > minPrec) {
10076
10135
  var logical = this.type === types$1.logicalOR || this.type === types$1.logicalAND;
10077
- var coalesce = this.type === types$1.coalesce;
10078
- if (coalesce) {
10136
+ var coalesce2 = this.type === types$1.coalesce;
10137
+ if (coalesce2) {
10079
10138
  prec = types$1.logicalAND.binop;
10080
10139
  }
10081
10140
  var op = this.value;
10082
10141
  this.next();
10083
10142
  var startPos = this.start, startLoc = this.startLoc;
10084
10143
  var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit);
10085
- var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce);
10086
- if (logical && this.type === types$1.coalesce || coalesce && (this.type === types$1.logicalOR || this.type === types$1.logicalAND)) {
10144
+ var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce2);
10145
+ if (logical && this.type === types$1.coalesce || coalesce2 && (this.type === types$1.logicalOR || this.type === types$1.logicalAND)) {
10087
10146
  this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses");
10088
10147
  }
10089
10148
  return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit);
@@ -13334,8 +13393,9 @@ function parse3(input, options) {
13334
13393
  // src/service/scriptAst.ts
13335
13394
  var PREFIX = "(async function* () {\n";
13336
13395
  var SUFFIX = "\n})";
13337
- var PATH_ARG_APIS = /* @__PURE__ */ new Set(["$getAll", "$resolve", "$trackDependency"]);
13338
- var UNTRACK_API = "$untrackDependency";
13396
+ var PATH_ARG_APIS = /* @__PURE__ */ new Set(["$getAll", "$resolve", "$dependOn", "$trackDependency"]);
13397
+ var TRACK_APIS = /* @__PURE__ */ new Set(["$dependOn", "$trackDependency"]);
13398
+ var UNTRACK_APIS = /* @__PURE__ */ new Set(["$untracked", "$untrackDependency"]);
13339
13399
  function collectGetterReads(body) {
13340
13400
  let program;
13341
13401
  try {
@@ -13560,7 +13620,7 @@ function visitCall(node, scope, out) {
13560
13620
  const { segments, base } = resolveChain(callee);
13561
13621
  if (isThisRoot(base, scope) && segments.length === 1 && segments[0].text !== null) {
13562
13622
  const api = segments[0].text;
13563
- if (api === UNTRACK_API) return;
13623
+ if (UNTRACK_APIS.has(api)) return;
13564
13624
  if (PATH_ARG_APIS.has(api)) {
13565
13625
  const first = node.arguments[0];
13566
13626
  const path = first !== void 0 && first.type !== "SpreadElement" ? literalString2(first) : null;
@@ -13568,7 +13628,7 @@ function visitCall(node, scope, out) {
13568
13628
  out.push({
13569
13629
  path,
13570
13630
  chain: null,
13571
- form: api === "$trackDependency" ? "track" : "api",
13631
+ form: TRACK_APIS.has(api) ? "track" : "api",
13572
13632
  callee: false,
13573
13633
  written: false,
13574
13634
  start: node.start - PREFIX.length,
@@ -13751,7 +13811,35 @@ function buildReferenceIndex(html, options = {}) {
13751
13811
  }
13752
13812
 
13753
13813
  // src/service/semanticValidator.ts
13754
- var STATE_UPDATED_CALLBACK = "$updatedCallback";
13814
+ var STATE_UPDATED_CALLBACKS = /* @__PURE__ */ new Set(["$renderedCallback", "$updatedCallback"]);
13815
+ var OLD_API_NAMES = { $trackDependency: "$dependOn", $untrackDependency: "$untracked" };
13816
+ var OLD_DECLARATION_KEYS = { $streams: "$stream", $updatedCallback: "$renderedCallback" };
13817
+ var OLD_API_CALL = /\.\s*(\$trackDependency|\$untrackDependency)\b/g;
13818
+ var OLD_DECLARATION_KEY = /(^|[{,\s])(\$streams|\$updatedCallback)(?=\s*[:(])/g;
13819
+ function validateNameAliases(script, scriptStart, locale2) {
13820
+ const msgs = getMessages(locale2);
13821
+ const scan = blankComments(script);
13822
+ const out = [];
13823
+ const push2 = (name, canonical, offset2) => {
13824
+ out.push({
13825
+ code: WcsDiagnosticCode.NameAlias,
13826
+ start: scriptStart + offset2,
13827
+ end: scriptStart + offset2 + name.length,
13828
+ message: msgs.nameAlias(name, canonical),
13829
+ severity: "info"
13830
+ });
13831
+ };
13832
+ OLD_API_CALL.lastIndex = 0;
13833
+ let match;
13834
+ while ((match = OLD_API_CALL.exec(scan)) !== null) {
13835
+ push2(match[1], OLD_API_NAMES[match[1]], match.index + match[0].length - match[1].length);
13836
+ }
13837
+ OLD_DECLARATION_KEY.lastIndex = 0;
13838
+ while ((match = OLD_DECLARATION_KEY.exec(scan)) !== null) {
13839
+ push2(match[2], OLD_DECLARATION_KEYS[match[2]], match.index + match[1].length);
13840
+ }
13841
+ return out;
13842
+ }
13755
13843
  var API_CALL = /\.\s*\$(getAll|setAll|resolve)\s*\(/g;
13756
13844
  function validateIndexArity(script, scriptStart, locale2) {
13757
13845
  const msgs = getMessages(locale2);
@@ -13933,13 +14021,13 @@ var PATH_TEST_LITERAL = /(?:\.\s*(?:includes|indexOf)\s*\(\s*|[!=]==\s*)(["'])((
13933
14021
  function validateUpdatedCallbackDemand(html, stateTagName, bindAttrName, locale2) {
13934
14022
  const blocks = parseWcsScriptBlocks(html, stateTagName);
13935
14023
  if (blocks.length === 0) return [];
13936
- const hasCallback = blocks.some((block) => block.content.includes(STATE_UPDATED_CALLBACK));
14024
+ const hasCallback = blocks.some((block) => [...STATE_UPDATED_CALLBACKS].some((name) => block.content.includes(name)));
13937
14025
  if (!hasCallback) return [];
13938
14026
  const msgs = getMessages(locale2);
13939
14027
  const boundPaths = collectBoundPaths(html, stateTagName, bindAttrName);
13940
14028
  const out = [];
13941
14029
  for (const block of blocks) {
13942
- const callback = analyzeCallableBodies(block.content).find((entry) => entry.name === STATE_UPDATED_CALLBACK && entry.kind === "method");
14030
+ const callback = analyzeCallableBodies(block.content).find((entry) => STATE_UPDATED_CALLBACKS.has(entry.name) && entry.kind === "method");
13943
14031
  if (callback === void 0) continue;
13944
14032
  if (block.mountPath !== null) continue;
13945
14033
  const declared = new Set(analyzeStatePaths(block.content).map((p) => p.path));
@@ -13986,6 +14074,7 @@ function validateSemantics(html, stateTagName = "wcs-state", locale2, bindAttrNa
13986
14074
  const getNestedWriteRoots = () => nestedWriteRoots ??= collectNestedWriteRoots(html, stateTagName, bindAttrName, blocks);
13987
14075
  for (const block of blocks) {
13988
14076
  out.push(...validateIndexArity(block.content, block.contentStart, locale2));
14077
+ out.push(...validateNameAliases(block.content, block.contentStart, locale2));
13989
14078
  out.push(...validateGetterCycles(block.content, block.contentStart, locale2));
13990
14079
  out.push(...validateGetterUntrackedReads(block.content, block.contentStart, getNestedWriteRoots, locale2));
13991
14080
  }
package/dist/tsc-core.cjs CHANGED
@@ -204,7 +204,11 @@ interface WcsStateApi {
204
204
  $setAll<V = any>(path: string, indexes: number[], values: readonly V[], options: { spread: true }): number;
205
205
  $postUpdate(path: string): void;
206
206
  $resolve(path: string, indexes: number[], value?: any): any;
207
+ $dependOn(path: string): void;
208
+ $untracked<T>(fn: () => T): T;
209
+ /** @deprecated $dependOn \u306E\u65E7\u540D\uFF08@wcstack/state 3.2 \u2014 4.0 \u3067\u5916\u308C\u308B\uFF09 */
207
210
  $trackDependency(path: string): void;
211
+ /** @deprecated $untracked \u306E\u65E7\u540D\uFF08@wcstack/state 3.2 \u2014 4.0 \u3067\u5916\u308C\u308B\uFF09 */
208
212
  $untrackDependency<T>(fn: () => T): T;
209
213
  $eq(path: string, key: unknown): boolean;
210
214
  $eqPath(path: string, keyPath: string): boolean;
@@ -233,6 +237,7 @@ interface WcsStateApi {
233
237
  // T \u306B\u540C\u540D\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u660E\u793A\u7684\u306B\u4E8B\u524D\u5BA3\u8A00\u3057\u3066\u3044\u308C\u3070\u5199\u3055\u306A\u3044\uFF08\u4EA4\u5DEE\u3067\u305D\u306E\u578B\u307E\u3067 any \u306B\u6F70\u3055\u306A\u3044\u305F\u3081\uFF09\u3002
234
238
  type _WcsDeclaredValues<T> =
235
239
  (T extends { $scan: infer S } ? { [K in Exclude<keyof S & string, keyof T>]: any } : {}) &
240
+ (T extends { $stream: infer S } ? { [K in Exclude<keyof S & string, keyof T>]: any } : {}) &
236
241
  (T extends { $streams: infer S } ? { [K in Exclude<keyof S & string, keyof T>]: any } : {});
237
242
  type _WcsThis<T> = T & WcsStateApi & _WcsPathAccessor<T> & _WcsDeclaredValues<T>;
238
243
  // $listKeys: { "<listPath>": "<field>" | (row) => key }\uFF08list/listKeys.ts\uFF09\u3002
@@ -567,7 +567,7 @@ function loadSchemaCore() {
567
567
  return cached;
568
568
  }
569
569
 
570
- var version = "3.1.0";
570
+ var version = "3.2.0";
571
571
  var pkg = {
572
572
  version: version};
573
573
 
package/dist/wcs-tsc.mjs CHANGED
@@ -5,7 +5,7 @@ import { tmpdir } from 'node:os';
5
5
  import { dirname, join, isAbsolute, resolve, basename } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
 
8
- var version = "3.1.0";
8
+ var version = "3.2.0";
9
9
  var pkg = {
10
10
  version: version};
11
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/typescript",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "TypeScript tooling for wcstack apps: wcs-schema generates the sidecar stateSchema from a typed state file, so wcs-validate checks data-wcs paths against real types in CI and every editor.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",