@wcstack/typescript 4.0.0-rc.2 → 4.0.0-rc.4

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
@@ -572,7 +572,7 @@ function loadSchemaCore() {
572
572
  return cached;
573
573
  }
574
574
 
575
- var version = "4.0.0-rc.2";
575
+ var version = "4.0.0-rc.4";
576
576
  var pkg = {
577
577
  version: version};
578
578
 
@@ -766,32 +766,8 @@ var LINT_HINT = " Validate statically: npx @wcstack/lint <file>.";
766
766
  function raiseError(message, subject, candidates) {
767
767
  throw new Error(`[@wcstack/state] ${message}${hooks.explain?.(message, subject, candidates) ?? ""}`);
768
768
  }
769
- var CODES = [
770
- "",
771
- "binding-syntax",
772
- "template-syntax",
773
- "binding-path-missing",
774
- "binding-type-expectation",
775
- "filter-unknown",
776
- "filter-arity",
777
- "getter-cycle",
778
- "getter-depth-exceeded",
779
- "index-arity",
780
- "index-param-range",
781
- "recursion-unsupported",
782
- "token-misconfigured",
783
- "token-undeclared",
784
- "wildcard-rank",
785
- "spread-no-bindable",
786
- "declaration-alias",
787
- "name-alias"
788
- ];
789
- var codeOf = (id) => {
790
- const c = CODES[id / 100 | 0];
791
- return c ? `[wcs/${c}] ` : "";
792
- };
793
769
  function text(id, args = []) {
794
- return hooks.render?.(id, args) ?? `${codeOf(id)}#${id}${args.map((a) => ` ${typeof a === "string" ? JSON.stringify(a) : String(a)}`).join("")}`;
770
+ return hooks.render?.(id, args) ?? `#${id}${args.map((a) => ` ${typeof a === "string" ? JSON.stringify(a) : String(a)}`).join("")}`;
795
771
  }
796
772
  function raise(id, args, subject, candidates) {
797
773
  raiseError(text(id, args), subject, candidates);
@@ -819,7 +795,21 @@ var FORMATS_FILTER_NAMES = [
819
795
  "time",
820
796
  "datetime",
821
797
  "ymd",
822
- "hms"
798
+ "hms",
799
+ "add",
800
+ "sub",
801
+ "mul",
802
+ "div",
803
+ "mod",
804
+ "abs",
805
+ "clamp",
806
+ "int",
807
+ "float",
808
+ "defaults",
809
+ "coalesce",
810
+ "number",
811
+ "string",
812
+ "nullIfEmpty"
823
813
  ];
824
814
  var definitions = /* @__PURE__ */ new Map();
825
815
  function hasFilter(name) {
@@ -1011,6 +1001,30 @@ function parseStatePart(statePart) {
1011
1001
  }
1012
1002
  var MAX_DRAIN_PASSES = 32;
1013
1003
  var MAX_RENDER_CHAIN = 100;
1004
+ var CODES = [
1005
+ "",
1006
+ "binding-syntax",
1007
+ "template-syntax",
1008
+ "binding-path-missing",
1009
+ "binding-type-expectation",
1010
+ "filter-unknown",
1011
+ "filter-arity",
1012
+ "getter-cycle",
1013
+ "getter-depth-exceeded",
1014
+ "index-arity",
1015
+ "index-param-range",
1016
+ "recursion-unsupported",
1017
+ "token-misconfigured",
1018
+ "token-undeclared",
1019
+ "wildcard-rank",
1020
+ "spread-no-bindable",
1021
+ "declaration-alias",
1022
+ "name-alias"
1023
+ ];
1024
+ var codeOf = (id) => {
1025
+ const c = CODES[id / 100 | 0];
1026
+ return c ? `[wcs/${c}] ` : "";
1027
+ };
1014
1028
  var MOVED = ["enableMustache", "sameValueGuard", "enableDirectionalInitialSync"];
1015
1029
  var element = (tag, at2) => `<${tag}${at2.map((a, i) => i % 2 ? `="${a}"` : ` ${a}`).join("")}>`;
1016
1030
  var CSP_GUIDE = "https://github.com/wcstack/wcstack/blob/main/docs/csp.md";
@@ -1211,6 +1225,10 @@ var SENTENCES = {
1211
1225
  50
1212
1226
  /* ConnectedFailed */
1213
1227
  ]: (tag, ...at2) => `${element(tag, at2)} $connectedCallback failed.`,
1228
+ [
1229
+ 51
1230
+ /* DisconnectedFailed */
1231
+ ]: (tag, ...at2) => `${element(tag, at2)} $disconnectedCallback failed.`,
1214
1232
  [
1215
1233
  101
1216
1234
  /* BindTextNoColon */
@@ -1686,26 +1704,26 @@ function findStartTagRegions(html) {
1686
1704
  let lower2 = null;
1687
1705
  let i = 0;
1688
1706
  while (i < html.length) {
1689
- const lt = html.indexOf("<", i);
1690
- if (lt === -1) break;
1691
- const next = html[lt + 1];
1692
- if (html.startsWith("<!--", lt)) {
1693
- const close = html.indexOf("-->", lt + 4);
1707
+ const lt2 = html.indexOf("<", i);
1708
+ if (lt2 === -1) break;
1709
+ const next = html[lt2 + 1];
1710
+ if (html.startsWith("<!--", lt2)) {
1711
+ const close = html.indexOf("-->", lt2 + 4);
1694
1712
  i = close === -1 ? html.length : close + 3;
1695
1713
  continue;
1696
1714
  }
1697
1715
  if (next === "!" || next === "?" || next === "/") {
1698
- const close = html.indexOf(">", lt + 1);
1716
+ const close = html.indexOf(">", lt2 + 1);
1699
1717
  i = close === -1 ? html.length : close + 1;
1700
1718
  continue;
1701
1719
  }
1702
1720
  if (next === void 0 || !/[A-Za-z]/.test(next)) {
1703
- i = lt + 1;
1721
+ i = lt2 + 1;
1704
1722
  continue;
1705
1723
  }
1706
- let n = lt + 1;
1724
+ let n = lt2 + 1;
1707
1725
  while (n < html.length && /[^\s/>]/.test(html[n])) n++;
1708
- const tagName = asciiLowerCase(html.slice(lt + 1, n));
1726
+ const tagName = asciiLowerCase(html.slice(lt2 + 1, n));
1709
1727
  let j = n;
1710
1728
  let quote = null;
1711
1729
  while (j < html.length) {
@@ -1719,10 +1737,10 @@ function findStartTagRegions(html) {
1719
1737
  }
1720
1738
  j++;
1721
1739
  }
1722
- const gt = j < html.length ? j : html.length;
1723
- const selfClosing = html[gt - 1] === "/";
1724
- out.push({ tagName, start: n, end: selfClosing ? gt - 1 : gt });
1725
- i = gt + 1;
1740
+ const gt2 = j < html.length ? j : html.length;
1741
+ const selfClosing = html[gt2 - 1] === "/";
1742
+ out.push({ tagName, start: n, end: selfClosing ? gt2 - 1 : gt2 });
1743
+ i = gt2 + 1;
1726
1744
  if (tagName === "script" || tagName === "style") {
1727
1745
  const close = (lower2 ??= asciiLowerCase(html)).indexOf(`</${tagName}`, i);
1728
1746
  i = close === -1 ? html.length : close;
@@ -1766,8 +1784,8 @@ function matchRawTextElement(html, lower2, pos) {
1766
1784
  return null;
1767
1785
  }
1768
1786
  function afterCloseTag(html, closeStart) {
1769
- const gt = html.indexOf(">", closeStart);
1770
- return gt === -1 ? html.length : gt + 1;
1787
+ const gt2 = html.indexOf(">", closeStart);
1788
+ return gt2 === -1 ? html.length : gt2 + 1;
1771
1789
  }
1772
1790
  function parseWcsStateElements(html, stateTagName = "wcs-state") {
1773
1791
  const elements = [];
@@ -1873,22 +1891,22 @@ function collectTemplateTags(html) {
1873
1891
  const tags = [];
1874
1892
  let pos = 0;
1875
1893
  while (pos < html.length) {
1876
- const lt = html.indexOf("<", pos);
1877
- if (lt === -1) break;
1878
- if (html.startsWith("<!--", lt)) {
1879
- const commentEnd = html.indexOf("-->", lt + 4);
1894
+ const lt2 = html.indexOf("<", pos);
1895
+ if (lt2 === -1) break;
1896
+ if (html.startsWith("<!--", lt2)) {
1897
+ const commentEnd = html.indexOf("-->", lt2 + 4);
1880
1898
  if (commentEnd === -1) break;
1881
1899
  pos = commentEnd + 3;
1882
1900
  continue;
1883
1901
  }
1884
- const raw = matchRawTextElement(html, lower2, lt);
1902
+ const raw = matchRawTextElement(html, lower2, lt2);
1885
1903
  if (raw !== null) {
1886
1904
  pos = raw.closed ? afterCloseTag(html, raw.contentEnd) : html.length;
1887
1905
  continue;
1888
1906
  }
1889
- const tag = /^<(\/?)template(?=[\s/>])/i.exec(html.slice(lt, lt + 11));
1890
- if (tag !== null) tags.push({ at: lt, close: tag[1] === "/" });
1891
- pos = lt + 1;
1907
+ const tag = /^<(\/?)template(?=[\s/>])/i.exec(html.slice(lt2, lt2 + 11));
1908
+ if (tag !== null) tags.push({ at: lt2, close: tag[1] === "/" });
1909
+ pos = lt2 + 1;
1892
1910
  }
1893
1911
  return tags;
1894
1912
  }
@@ -2032,32 +2050,8 @@ var hooks2 = {};
2032
2050
  function raiseError2(message, subject, candidates) {
2033
2051
  throw new Error(`[@wcstack/state] ${message}${hooks2.explain?.(message, subject, candidates) ?? ""}`);
2034
2052
  }
2035
- var CODES2 = [
2036
- "",
2037
- "binding-syntax",
2038
- "template-syntax",
2039
- "binding-path-missing",
2040
- "binding-type-expectation",
2041
- "filter-unknown",
2042
- "filter-arity",
2043
- "getter-cycle",
2044
- "getter-depth-exceeded",
2045
- "index-arity",
2046
- "index-param-range",
2047
- "recursion-unsupported",
2048
- "token-misconfigured",
2049
- "token-undeclared",
2050
- "wildcard-rank",
2051
- "spread-no-bindable",
2052
- "declaration-alias",
2053
- "name-alias"
2054
- ];
2055
- var codeOf2 = (id) => {
2056
- const c = CODES2[id / 100 | 0];
2057
- return c ? `[wcs/${c}] ` : "";
2058
- };
2059
2053
  function text2(id, args = []) {
2060
- return hooks2.render?.(id, args) ?? `${codeOf2(id)}#${id}${args.map((a) => ` ${typeof a === "string" ? JSON.stringify(a) : String(a)}`).join("")}`;
2054
+ return hooks2.render?.(id, args) ?? `#${id}${args.map((a) => ` ${typeof a === "string" ? JSON.stringify(a) : String(a)}`).join("")}`;
2061
2055
  }
2062
2056
  function raise2(id, args, subject, candidates) {
2063
2057
  raiseError2(text2(id, args), subject, candidates);
@@ -2161,42 +2155,6 @@ var numeric = (name, op) => ({
2161
2155
  var truthy = () => (value) => !!value;
2162
2156
  var falsy = () => (value) => !value;
2163
2157
  var boolean = () => (value) => Boolean(value);
2164
- var abs = () => (value) => {
2165
- if (typeof value !== "number") {
2166
- valueMustBeNumber("abs");
2167
- }
2168
- return Math.abs(value);
2169
- };
2170
- var clamp = (options) => {
2171
- const min = requiredNumberOption(options, 0, "clamp");
2172
- const max = requiredNumberOption(options, 1, "clamp");
2173
- return (value) => {
2174
- if (typeof value !== "number") {
2175
- valueMustBeNumber("clamp");
2176
- }
2177
- return Math.min(Math.max(value, min), max);
2178
- };
2179
- };
2180
- var number = () => (value) => Number(value);
2181
- var string = () => (value) => String(value);
2182
- var int = () => (value) => parseInt(String(value), 10);
2183
- var float = () => (value) => parseFloat(String(value));
2184
- var defaults = (options, literals) => {
2185
- const opt = options?.[0] ?? optionsRequired("defaults");
2186
- const fallback = firstLiteral(opt, literals);
2187
- return (value) => {
2188
- if (!value) {
2189
- return fallback;
2190
- }
2191
- return value;
2192
- };
2193
- };
2194
- var coalesce = (options, literals) => {
2195
- const opt = options?.[0] ?? optionsRequired("coalesce");
2196
- const fallback = firstLiteral(opt, literals);
2197
- return (value) => value ?? fallback;
2198
- };
2199
- var nullIfEmpty = () => (value) => value === "" ? null : value;
2200
2158
  var coreFilters = {
2201
2159
  eq: { factory: eq, arity: [1, 1] },
2202
2160
  ne: { factory: ne, arity: [1, 1] },
@@ -2205,23 +2163,9 @@ var coreFilters = {
2205
2163
  le: numeric("le", (value, opt) => value <= opt),
2206
2164
  gt: numeric("gt", (value, opt) => value > opt),
2207
2165
  ge: numeric("ge", (value, opt) => value >= opt),
2208
- add: numeric("add", (value, opt) => value + opt),
2209
- sub: numeric("sub", (value, opt) => value - opt),
2210
- mul: numeric("mul", (value, opt) => value * opt),
2211
- div: numeric("div", (value, opt) => value / opt),
2212
- mod: numeric("mod", (value, opt) => value % opt),
2213
- abs: { factory: abs, arity: [0, 0] },
2214
- clamp: { factory: clamp, arity: [2, 2] },
2215
- int: { factory: int, arity: [0, 0] },
2216
- float: { factory: float, arity: [0, 0] },
2217
2166
  falsy: { factory: falsy, arity: [0, 0] },
2218
2167
  truthy: { factory: truthy, arity: [0, 0] },
2219
- defaults: { factory: defaults, arity: [1, 1] },
2220
- coalesce: { factory: coalesce, arity: [1, 1] },
2221
- boolean: { factory: boolean, arity: [0, 0] },
2222
- number: { factory: number, arity: [0, 0] },
2223
- string: { factory: string, arity: [0, 0] },
2224
- nullIfEmpty: { factory: nullIfEmpty, arity: [0, 0] }
2168
+ boolean: { factory: boolean, arity: [0, 0] }
2225
2169
  };
2226
2170
  var nullishPassthrough = (factory) => (options) => {
2227
2171
  const filterFn = factory(options);
@@ -2406,7 +2350,44 @@ var hms = (options) => {
2406
2350
  return `${hours}${opt}${minutes}${opt}${seconds}`;
2407
2351
  };
2408
2352
  };
2409
- var formatFilters = {
2353
+ var abs = () => (value) => {
2354
+ if (typeof value !== "number") {
2355
+ valueMustBeNumber("abs");
2356
+ }
2357
+ return Math.abs(value);
2358
+ };
2359
+ var clamp = (options) => {
2360
+ const min = requiredNumberOption(options, 0, "clamp");
2361
+ const max = requiredNumberOption(options, 1, "clamp");
2362
+ return (value) => {
2363
+ if (typeof value !== "number") {
2364
+ valueMustBeNumber("clamp");
2365
+ }
2366
+ return Math.min(Math.max(value, min), max);
2367
+ };
2368
+ };
2369
+ var number = () => (value) => Number(value);
2370
+ var string = () => (value) => String(value);
2371
+ var int = () => (value) => parseInt(String(value), 10);
2372
+ var float = () => (value) => parseFloat(String(value));
2373
+ var defaults = (options, literals) => {
2374
+ const opt = options?.[0] ?? optionsRequired("defaults");
2375
+ const fallback = firstLiteral(opt, literals);
2376
+ return (value) => {
2377
+ if (!value) {
2378
+ return fallback;
2379
+ }
2380
+ return value;
2381
+ };
2382
+ };
2383
+ var coalesce = (options, literals) => {
2384
+ const opt = options?.[0] ?? optionsRequired("coalesce");
2385
+ const fallback = firstLiteral(opt, literals);
2386
+ return (value) => value ?? fallback;
2387
+ };
2388
+ var nullIfEmpty = () => (value) => value === "" ? null : value;
2389
+ var { eq: eq2, ne: ne2, not: not2, lt, le, gt, ge, falsy: falsy2, truthy: truthy2, boolean: boolean2 } = coreFilters;
2390
+ var registered = {
2410
2391
  toFixed: { factory: toFixed, arity: [0, 1] },
2411
2392
  locale: { factory: locale, arity: [0, 1] },
2412
2393
  // The `String(value)` family passes an absent value through (B8 — see nullishPassthrough)
@@ -2432,8 +2413,36 @@ var formatFilters = {
2432
2413
  time: { factory: time, arity: [0, 1] },
2433
2414
  datetime: { factory: datetime, arity: [0, 1] },
2434
2415
  ymd: { factory: ymd, arity: [0, 1] },
2435
- hms: { factory: hms, arity: [0, 1] }
2416
+ hms: { factory: hms, arity: [0, 1] },
2417
+ // the core set of 4.0.0-rc.3 (the core's own: eq ne not lt le gt ge falsy truthy boolean)
2418
+ eq: eq2,
2419
+ ne: ne2,
2420
+ not: not2,
2421
+ lt,
2422
+ le,
2423
+ gt,
2424
+ ge,
2425
+ add: numeric("add", (value, opt) => value + opt),
2426
+ sub: numeric("sub", (value, opt) => value - opt),
2427
+ mul: numeric("mul", (value, opt) => value * opt),
2428
+ div: numeric("div", (value, opt) => value / opt),
2429
+ mod: numeric("mod", (value, opt) => value % opt),
2430
+ abs: { factory: abs, arity: [0, 0] },
2431
+ clamp: { factory: clamp, arity: [2, 2] },
2432
+ int: { factory: int, arity: [0, 0] },
2433
+ float: { factory: float, arity: [0, 0] },
2434
+ falsy: falsy2,
2435
+ truthy: truthy2,
2436
+ defaults: { factory: defaults, arity: [1, 1] },
2437
+ coalesce: { factory: coalesce, arity: [1, 1] },
2438
+ boolean: boolean2,
2439
+ number: { factory: number, arity: [0, 0] },
2440
+ string: { factory: string, arity: [0, 0] },
2441
+ nullIfEmpty: { factory: nullIfEmpty, arity: [0, 0] }
2436
2442
  };
2443
+ var formatFilters = /* @__PURE__ */ Object.fromEntries(
2444
+ /* @__PURE__ */ Object.entries(registered).filter(([name]) => !(name in coreFilters))
2445
+ );
2437
2446
  var STRUCTURAL_BINDING_TYPE_SET2 = /* @__PURE__ */ new Set([
2438
2447
  "if",
2439
2448
  "elseif",
package/dist/tsc-core.cjs CHANGED
@@ -64,8 +64,8 @@ function matchRawTextElement(html, lower2, pos) {
64
64
  return null;
65
65
  }
66
66
  function afterCloseTag(html, closeStart) {
67
- const gt = html.indexOf(">", closeStart);
68
- return gt === -1 ? html.length : gt + 1;
67
+ const gt2 = html.indexOf(">", closeStart);
68
+ return gt2 === -1 ? html.length : gt2 + 1;
69
69
  }
70
70
  function parseWcsStateElements(html, stateTagName = "wcs-state") {
71
71
  const elements = [];
@@ -221,32 +221,8 @@ var hooks = {};
221
221
  function raiseError(message, subject, candidates) {
222
222
  throw new Error(`[@wcstack/state] ${message}${hooks.explain?.(message, subject, candidates) ?? ""}`);
223
223
  }
224
- var CODES = [
225
- "",
226
- "binding-syntax",
227
- "template-syntax",
228
- "binding-path-missing",
229
- "binding-type-expectation",
230
- "filter-unknown",
231
- "filter-arity",
232
- "getter-cycle",
233
- "getter-depth-exceeded",
234
- "index-arity",
235
- "index-param-range",
236
- "recursion-unsupported",
237
- "token-misconfigured",
238
- "token-undeclared",
239
- "wildcard-rank",
240
- "spread-no-bindable",
241
- "declaration-alias",
242
- "name-alias"
243
- ];
244
- var codeOf = (id) => {
245
- const c = CODES[id / 100 | 0];
246
- return c ? `[wcs/${c}] ` : "";
247
- };
248
224
  function text(id, args = []) {
249
- return hooks.render?.(id, args) ?? `${codeOf(id)}#${id}${args.map((a) => ` ${typeof a === "string" ? JSON.stringify(a) : String(a)}`).join("")}`;
225
+ return hooks.render?.(id, args) ?? `#${id}${args.map((a) => ` ${typeof a === "string" ? JSON.stringify(a) : String(a)}`).join("")}`;
250
226
  }
251
227
  function raise(id, args, subject, candidates) {
252
228
  raiseError(text(id, args), subject, candidates);
@@ -350,42 +326,6 @@ var numeric = (name, op) => ({
350
326
  var truthy = () => (value) => !!value;
351
327
  var falsy = () => (value) => !value;
352
328
  var boolean = () => (value) => Boolean(value);
353
- var abs = () => (value) => {
354
- if (typeof value !== "number") {
355
- valueMustBeNumber("abs");
356
- }
357
- return Math.abs(value);
358
- };
359
- var clamp = (options) => {
360
- const min = requiredNumberOption(options, 0, "clamp");
361
- const max = requiredNumberOption(options, 1, "clamp");
362
- return (value) => {
363
- if (typeof value !== "number") {
364
- valueMustBeNumber("clamp");
365
- }
366
- return Math.min(Math.max(value, min), max);
367
- };
368
- };
369
- var number = () => (value) => Number(value);
370
- var string = () => (value) => String(value);
371
- var int = () => (value) => parseInt(String(value), 10);
372
- var float = () => (value) => parseFloat(String(value));
373
- var defaults = (options, literals) => {
374
- const opt = options?.[0] ?? optionsRequired("defaults");
375
- const fallback = firstLiteral(opt, literals);
376
- return (value) => {
377
- if (!value) {
378
- return fallback;
379
- }
380
- return value;
381
- };
382
- };
383
- var coalesce = (options, literals) => {
384
- const opt = options?.[0] ?? optionsRequired("coalesce");
385
- const fallback = firstLiteral(opt, literals);
386
- return (value) => value ?? fallback;
387
- };
388
- var nullIfEmpty = () => (value) => value === "" ? null : value;
389
329
  var coreFilters = {
390
330
  eq: { factory: eq, arity: [1, 1] },
391
331
  ne: { factory: ne, arity: [1, 1] },
@@ -394,23 +334,9 @@ var coreFilters = {
394
334
  le: numeric("le", (value, opt) => value <= opt),
395
335
  gt: numeric("gt", (value, opt) => value > opt),
396
336
  ge: numeric("ge", (value, opt) => value >= opt),
397
- add: numeric("add", (value, opt) => value + opt),
398
- sub: numeric("sub", (value, opt) => value - opt),
399
- mul: numeric("mul", (value, opt) => value * opt),
400
- div: numeric("div", (value, opt) => value / opt),
401
- mod: numeric("mod", (value, opt) => value % opt),
402
- abs: { factory: abs, arity: [0, 0] },
403
- clamp: { factory: clamp, arity: [2, 2] },
404
- int: { factory: int, arity: [0, 0] },
405
- float: { factory: float, arity: [0, 0] },
406
337
  falsy: { factory: falsy, arity: [0, 0] },
407
338
  truthy: { factory: truthy, arity: [0, 0] },
408
- defaults: { factory: defaults, arity: [1, 1] },
409
- coalesce: { factory: coalesce, arity: [1, 1] },
410
- boolean: { factory: boolean, arity: [0, 0] },
411
- number: { factory: number, arity: [0, 0] },
412
- string: { factory: string, arity: [0, 0] },
413
- nullIfEmpty: { factory: nullIfEmpty, arity: [0, 0] }
339
+ boolean: { factory: boolean, arity: [0, 0] }
414
340
  };
415
341
  var nullishPassthrough = (factory) => (options) => {
416
342
  const filterFn = factory(options);
@@ -595,7 +521,44 @@ var hms = (options) => {
595
521
  return `${hours}${opt}${minutes}${opt}${seconds}`;
596
522
  };
597
523
  };
598
- var formatFilters = {
524
+ var abs = () => (value) => {
525
+ if (typeof value !== "number") {
526
+ valueMustBeNumber("abs");
527
+ }
528
+ return Math.abs(value);
529
+ };
530
+ var clamp = (options) => {
531
+ const min = requiredNumberOption(options, 0, "clamp");
532
+ const max = requiredNumberOption(options, 1, "clamp");
533
+ return (value) => {
534
+ if (typeof value !== "number") {
535
+ valueMustBeNumber("clamp");
536
+ }
537
+ return Math.min(Math.max(value, min), max);
538
+ };
539
+ };
540
+ var number = () => (value) => Number(value);
541
+ var string = () => (value) => String(value);
542
+ var int = () => (value) => parseInt(String(value), 10);
543
+ var float = () => (value) => parseFloat(String(value));
544
+ var defaults = (options, literals) => {
545
+ const opt = options?.[0] ?? optionsRequired("defaults");
546
+ const fallback = firstLiteral(opt, literals);
547
+ return (value) => {
548
+ if (!value) {
549
+ return fallback;
550
+ }
551
+ return value;
552
+ };
553
+ };
554
+ var coalesce = (options, literals) => {
555
+ const opt = options?.[0] ?? optionsRequired("coalesce");
556
+ const fallback = firstLiteral(opt, literals);
557
+ return (value) => value ?? fallback;
558
+ };
559
+ var nullIfEmpty = () => (value) => value === "" ? null : value;
560
+ var { eq: eq2, ne: ne2, not: not2, lt, le, gt, ge, falsy: falsy2, truthy: truthy2, boolean: boolean2 } = coreFilters;
561
+ var registered = {
599
562
  toFixed: { factory: toFixed, arity: [0, 1] },
600
563
  locale: { factory: locale, arity: [0, 1] },
601
564
  // The `String(value)` family passes an absent value through (B8 — see nullishPassthrough)
@@ -621,8 +584,36 @@ var formatFilters = {
621
584
  time: { factory: time, arity: [0, 1] },
622
585
  datetime: { factory: datetime, arity: [0, 1] },
623
586
  ymd: { factory: ymd, arity: [0, 1] },
624
- hms: { factory: hms, arity: [0, 1] }
587
+ hms: { factory: hms, arity: [0, 1] },
588
+ // the core set of 4.0.0-rc.3 (the core's own: eq ne not lt le gt ge falsy truthy boolean)
589
+ eq: eq2,
590
+ ne: ne2,
591
+ not: not2,
592
+ lt,
593
+ le,
594
+ gt,
595
+ ge,
596
+ add: numeric("add", (value, opt) => value + opt),
597
+ sub: numeric("sub", (value, opt) => value - opt),
598
+ mul: numeric("mul", (value, opt) => value * opt),
599
+ div: numeric("div", (value, opt) => value / opt),
600
+ mod: numeric("mod", (value, opt) => value % opt),
601
+ abs: { factory: abs, arity: [0, 0] },
602
+ clamp: { factory: clamp, arity: [2, 2] },
603
+ int: { factory: int, arity: [0, 0] },
604
+ float: { factory: float, arity: [0, 0] },
605
+ falsy: falsy2,
606
+ truthy: truthy2,
607
+ defaults: { factory: defaults, arity: [1, 1] },
608
+ coalesce: { factory: coalesce, arity: [1, 1] },
609
+ boolean: boolean2,
610
+ number: { factory: number, arity: [0, 0] },
611
+ string: { factory: string, arity: [0, 0] },
612
+ nullIfEmpty: { factory: nullIfEmpty, arity: [0, 0] }
625
613
  };
614
+ var formatFilters = /* @__PURE__ */ Object.fromEntries(
615
+ /* @__PURE__ */ Object.entries(registered).filter(([name]) => !(name in coreFilters))
616
+ );
626
617
  var STRUCTURAL_BINDING_TYPE_SET = /* @__PURE__ */ new Set([
627
618
  "if",
628
619
  "elseif",
@@ -573,7 +573,7 @@ function loadSchemaCore() {
573
573
  return cached;
574
574
  }
575
575
 
576
- var version = "4.0.0-rc.2";
576
+ var version = "4.0.0-rc.4";
577
577
  var pkg = {
578
578
  version: version};
579
579
 
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 = "4.0.0-rc.2";
8
+ var version = "4.0.0-rc.4";
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": "4.0.0-rc.2",
3
+ "version": "4.0.0-rc.4",
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",