@wcstack/typescript 4.0.2 → 4.0.3

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.2";
575
+ var version = "4.0.3";
576
576
  var pkg = {
577
577
  version: version};
578
578
 
@@ -3148,7 +3148,9 @@ function analyzeStatePaths(scriptContent) {
3148
3148
  }
3149
3149
  if (prop.kind === "getter") {
3150
3150
  if (!paths.some((p) => p.path === prop.name)) {
3151
- paths.push({ path: prop.name, kind: hasRecursionWildcard(prop.name) ? "recursive" : "computed" });
3151
+ const recursive = hasRecursionWildcard(prop.name);
3152
+ const settable = !recursive && effective !== "data" && effective.set;
3153
+ paths.push({ path: prop.name, kind: recursive ? "recursive" : "computed", ...settable ? { settable } : {} });
3152
3154
  }
3153
3155
  continue;
3154
3156
  }
@@ -10991,7 +10993,9 @@ var ja = {
10991
10993
  triggerSeededTruthy: (path) => `trigger \u30D0\u30A4\u30F3\u30C9\u5148 "${path}" \u304C true \u3067\u30B7\u30FC\u30C9\u3055\u308C\u3066\u3044\u307E\u3059\u3002trigger \u306F\u30A8\u30C3\u30B8\u691C\u51FA\u306A\u3057\uFF08truthy \u66F8\u304D\u8FBC\u307F\u3067\u5373\u767A\u706B\u30FBmanual \u3082\u30D0\u30A4\u30D1\u30B9\uFF09\u306E\u305F\u3081\u3001\u30D0\u30A4\u30F3\u30C9\u6642\u306B\u5373\u767A\u706B\u3057\u307E\u3059\u3002false \u3067\u30B7\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044`,
10992
10994
  storageSeedClobber: (path, raw) => `<wcs-storage> \u306E value \u30D0\u30A4\u30F3\u30C9\u5148 "${path}" \u304C ${raw} \u3067\u30B7\u30FC\u30C9\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u8AAD\u307F\u8FBC\u307F\u306E\u305F\u3073\u306B\u521D\u671F\u66F8\u304D\u623B\u3057\u304C\u4FDD\u5B58\u5024\u3092\u4E0A\u66F8\u304D\u3057\u307E\u3059 \u2014 \u30D0\u30A4\u30F3\u30C9\u306B #init=element \u3092\u4ED8\u3051\u3066\uFF08\`value#init=element: ${path}\`\uFF09\u4FDD\u5B58\u5024\u3092\u52DD\u305F\u305B\u3001\u30B9\u30ED\u30C3\u30C8\u306F null\uFF08\u7A7A\u306E\u30AD\u30FC\u304C\u8AAD\u3080\u5024\uFF09\u3067\u30B7\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044`,
10993
10995
  storageInitSeed: (path, raw) => `<wcs-storage> \u306E value \u30D0\u30A4\u30F3\u30C9\u5148 "${path}" \u304C ${shortSeed(raw)} \u3067\u30B7\u30FC\u30C9\u3055\u308C\u3066\u3044\u307E\u3059\u304C\u3001#init=element \u306F\u8981\u7D20\u306E\u5024\u3092\u3053\u306E\u30B9\u30ED\u30C3\u30C8\u3078\u5F15\u304D\u8FBC\u307F\u307E\u3059\u3002\u521D\u56DE\uFF08\u7A7A\u306E\u30AD\u30FC\uFF09\u306F null \u306A\u306E\u3067\u3001\u30B7\u30FC\u30C9\u306F null \u306B\u7F6E\u304D\u63DB\u308F\u308A\u307E\u3059 \u2014 null \u3067\u30B7\u30FC\u30C9\u3057\u3066\u8AAD\u3080\u5074\u3067\u65E2\u5B9A\u5024\u3092\u88DC\u3046\uFF08\`this.${path} ?? \u2026\`\uFF09\u304B\u3001null \u3092\u7121\u8996\u3059\u308B setter \u3092\u6301\u3064\u30A2\u30AF\u30BB\u30B5\u30DA\u30A2\u3092\u675F\u306D\u3066\u304F\u3060\u3055\u3044`,
10996
+ storagePairClobber: (path) => `<wcs-storage> \u306E value \u3092 #init=element \u306A\u3057\u3067\u30A2\u30AF\u30BB\u30B5\u30DA\u30A2 "${path}" \u306B\u675F\u306D\u3066\u3044\u307E\u3059\u3002state \u306E\u5074\u304C\u5148\u306B\u66F8\u304F\u306E\u3067\u3001\u8AAD\u307F\u8FBC\u307F\u306E\u305F\u3073\u306B getter \u306E\u6700\u521D\u306E\u5024\u304C\u4FDD\u5B58\u5024\u306E\u4E0A\u306B\u4FDD\u5B58\u3055\u308C\u3001setter \u306F\u4FDD\u5B58\u5024\u3092\u53D7\u3051\u53D6\u308C\u307E\u305B\u3093 \u2014 #init=element \u3092\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044\uFF08\`value#init=element: ${path}\`\uFF09`,
10994
10997
  inputNestedWrite: (tag, input, path, example) => `<${tag}> \u306E\u5165\u529B "${input}" \u306B "${path}" \u3092\u675F\u306D\u3066\u3044\u307E\u3059\u304C\u3001\u30DA\u30FC\u30B8\u306F\u305D\u306E\u4E0B\uFF08"${example}"\uFF09\u3078\u66F8\u304D\u8FBC\u3093\u3067\u3044\u307E\u3059\u3002\u675F\u7E1B\u306F "${path}" \u81EA\u8EAB\u3078\u306E\u4EE3\u5165\u3067\u3057\u304B\u5F53\u3066\u76F4\u3055\u308C\u306A\u3044\u306E\u3067\u3001\u4E0B\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306F <${tag}> \u306B\u5C4A\u304D\u307E\u305B\u3093 \u2014 \u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u30D1\u30B9\u3067\u8AAD\u3093\u3067\u65B0\u3057\u3044\u5024\u3092\u8FD4\u3059 getter\uFF08\`this["${example}"]\`\u30FB\`$getAll\`\uFF09\u3092\u675F\u306D\u308B\u304B\u3001\u4E0B\u3078\u66F8\u304B\u305A\u306B "${path}" \u3092\u5DEE\u3057\u66FF\u3048\u3066\u304F\u3060\u3055\u3044`,
10998
+ inputNestedWriteOneShot: (tag, input, path, example) => `<${tag}> \u306E\u5165\u529B "${input}" \u306B "${path}" \u3092\u675F\u306D\u3066\u3044\u307E\u3059\u304C\u3001\u30DA\u30FC\u30B8\u306F\u305D\u306E\u4E0B\uFF08"${example}"\uFF09\u3078\u66F8\u304D\u8FBC\u3093\u3067\u3044\u307E\u3059\u3002\u675F\u7E1B\u306F "${path}" \u81EA\u8EAB\u3078\u306E\u4EE3\u5165\u3067\u3057\u304B\u5F53\u3066\u76F4\u3055\u308C\u305A\u3001<${tag}> \u306F\u8981\u6C42\u306E\u305F\u3073\u306B "${input}" \u3092 null \u306B\u623B\u3059\u306E\u3067\u3001\u6B21\u306E\u8981\u6C42\u306F "${input}" \u306A\u3057\u3067\u9001\u3089\u308C\u307E\u3059 \u2014 \u8981\u6C42\u3092\u59CB\u3081\u308B\u30CF\u30F3\u30C9\u30E9\u3067\u65B0\u3057\u3044\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u4F5C\u3063\u3066\u4EE3\u5165\u3057\uFF08\`this.submitBody = { \u2026 }\`\uFF09\u3001\u305D\u308C\u3092\u675F\u306D\u3066\u304F\u3060\u3055\u3044`,
10995
10999
  devtoolsAfterState: () => `@wcstack/devtools/auto \u306F @wcstack/state/auto \u3088\u308A\u5148\u306B\u8AAD\u307F\u8FBC\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u5F8C\u3060\u3068\u914D\u7DDA\u53F0\u5E33\u304C\u30E9\u30A4\u30D6\u3067 captured \u3055\u308C\u307E\u305B\u3093\uFF09`,
10996
11000
  baseHrefMissing: () => `@wcstack/router \u3092\u4F7F\u3046 SPA \u306B\u306F <head> \u5185\u306E <base href="/"> \u304C\u5FC5\u8981\u3067\u3059\uFF08\u7121\u3044\u3068\u30C7\u30A3\u30FC\u30D7\u30EA\u30F3\u30AF\u3067 basename \u304C\u8AA4\u5C0E\u51FA\u3055\u308C\u307E\u3059\uFF09`,
10997
11001
  signalsDualEntry: () => `@wcstack/signals \u3068 @wcstack/signals/dom \u304C\u540C\u4E00\u30DA\u30FC\u30B8\u304B\u3089 import \u3055\u308C\u3066\u3044\u307E\u3059\u3002CDN \u3067\u306F\u5404\u30A8\u30F3\u30C8\u30EA\u304C\u81EA\u5DF1\u5B8C\u7D50\u30D0\u30F3\u30C9\u30EB\u306E\u305F\u3081\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u30B3\u30A2\u304C\u4E8C\u91CD\u5316\u3057\u3001\u5883\u754C\u3067\u53CD\u5FDC\u304C\u58CA\u308C\u307E\u3059 \u2014 \u3059\u3079\u3066 /dom \u30A8\u30F3\u30C8\u30EA\u304B\u3089 import \u3057\u3066\u304F\u3060\u3055\u3044`,
@@ -11179,7 +11183,9 @@ var en = {
11179
11183
  triggerSeededTruthy: (path) => `The trigger-bound slot "${path}" is seeded with true. trigger has no edge detection (any truthy write fires, and it bypasses manual), so it fires immediately at bind. Seed it with false`,
11180
11184
  storageSeedClobber: (path, raw) => `The <wcs-storage> value-bound slot "${path}" is seeded with ${raw}. The initial write-back overwrites the persisted value on every load \u2014 add #init=element to the binding (\`value#init=element: ${path}\`) so the stored value wins, and seed the slot with null (what an empty key loads as)`,
11181
11185
  storageInitSeed: (path, raw) => `The <wcs-storage> value-bound slot "${path}" is seeded with ${shortSeed(raw)}, but #init=element pulls the element's value into it. On a first visit (an empty key) that is null, so the seed is replaced by null \u2014 seed it with null and supply the default where you read it (\`this.${path} ?? \u2026\`), or bind an accessor pair whose setter ignores null`,
11186
+ storagePairClobber: (path) => `The <wcs-storage> value is bound to the accessor pair "${path}" without #init=element. The state's side goes first, so on every load the getter's starting value is saved over the stored one, and the setter never receives it \u2014 add #init=element (\`value#init=element: ${path}\`)`,
11182
11187
  inputNestedWrite: (tag, input, path, example) => `"${path}" is bound to the input "${input}" of <${tag}>, but the page writes below it ("${example}"). A binding is re-applied only when "${path}" itself is assigned, so those writes never reach <${tag}> \u2014 bind a getter that reads the fields by path (\`this["${example}"]\`, \`$getAll\`) and returns a new value, or replace "${path}" instead of writing below it`,
11188
+ inputNestedWriteOneShot: (tag, input, path, example) => `"${path}" is bound to the input "${input}" of <${tag}>, but the page writes below it ("${example}"). A binding is re-applied only when "${path}" itself is assigned, and <${tag}> resets "${input}" to null after every request, so the next request goes without it \u2014 build a new object in the handler that starts the request (\`this.submitBody = { \u2026 }\`) and bind that`,
11183
11189
  devtoolsAfterState: () => `Load @wcstack/devtools/auto BEFORE @wcstack/state/auto (otherwise the wiring ledger is not captured live)`,
11184
11190
  baseHrefMissing: () => `An SPA using @wcstack/router needs <base href="/"> in <head> (without it, deep links misderive the basename)`,
11185
11191
  signalsDualEntry: () => `Both @wcstack/signals and @wcstack/signals/dom are imported on this page. On a CDN each entry is a self-contained bundle, so the reactive core is duplicated and reactivity breaks at the seam \u2014 import everything from the single /dom entry`,
@@ -14188,7 +14194,8 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
14188
14194
  }
14189
14195
  }
14190
14196
  if (tagName === "wcs-storage" && property === "value" && !hasManual && parsed.path && !/(?:^|,)init=(?:element|auto)\b/.test(modifiers)) {
14191
- const cand = findDataSlot(getPaths(), parsed.path);
14197
+ const paths = getPaths();
14198
+ const cand = findDataSlot(paths, parsed.path);
14192
14199
  if (cand?.rawInitial !== void 0 && EMPTYISH_SEEDS.has(normalizeSeed(cand.rawInitial))) {
14193
14200
  diagnostics.push({
14194
14201
  code: WcsDiagnosticCode.StorageSeedClobber,
@@ -14199,6 +14206,16 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
14199
14206
  statePath: parsed.path,
14200
14207
  message: msgs.storageSeedClobber(parsed.path, cand.rawInitial)
14201
14208
  });
14209
+ } else if (cand === void 0 && paths.some((c) => c.kind === "computed" && c.settable && c.path === parsed.path)) {
14210
+ diagnostics.push({
14211
+ code: WcsDiagnosticCode.StorageSeedClobber,
14212
+ start,
14213
+ end,
14214
+ severity: "warning",
14215
+ tag: tagName,
14216
+ statePath: parsed.path,
14217
+ message: msgs.storagePairClobber(parsed.path)
14218
+ });
14202
14219
  }
14203
14220
  }
14204
14221
  if (tagName === "wcs-storage" && property === "value" && parsed.path && /(?:^|,)init=element\b/.test(modifiers)) {
@@ -14356,10 +14373,10 @@ function validateDocumentEnv(html, locale2) {
14356
14373
  const msgs = getMessages(locale2);
14357
14374
  const scanText = blankHtmlComments(html);
14358
14375
  const autos = findWcstackAutoScripts(scanText);
14359
- const stateIndex = autos.findIndex((a) => a.pkg === "state");
14376
+ const stateIndex = autos.findIndex((a) => a.pkgs.includes("state"));
14360
14377
  if (stateIndex !== -1) {
14361
14378
  for (const later of autos.slice(stateIndex + 1)) {
14362
- if (later.pkg !== "devtools") continue;
14379
+ if (!later.pkgs.includes("devtools")) continue;
14363
14380
  diagnostics.push({
14364
14381
  code: WcsDiagnosticCode.ScriptOrder,
14365
14382
  start: later.start,
@@ -14369,7 +14386,7 @@ function validateDocumentEnv(html, locale2) {
14369
14386
  });
14370
14387
  }
14371
14388
  }
14372
- const router = autos.find((a) => a.pkg === "router");
14389
+ const router = autos.find((a) => a.pkgs.includes("router") && (!a.bundle || /<wcs-router\b/i.test(scanText)));
14373
14390
  if (router && !/<base\b[^>]*\bhref\s*=/i.test(scanText)) {
14374
14391
  diagnostics.push({
14375
14392
  code: WcsDiagnosticCode.BaseHrefMissing,
@@ -14394,6 +14411,9 @@ function validateDocumentEnv(html, locale2) {
14394
14411
  }
14395
14412
  return diagnostics;
14396
14413
  }
14414
+ var SCOPED_AUTO = /@wcstack\/([a-z0-9-]+)(?:@[^/"'\s]+)?\/(?:auto\b|dist\/(?:split\/)?auto(?:\.min)?\.js\b)/;
14415
+ var BUNDLE_AUTO = /(?:^|\/)wcstack(?:@[^/"'\s]+)?\/(?:auto\b|dist\/auto\.min\.js\b)/;
14416
+ var BUNDLE_PACKAGES = ["state", "router", "fetch", "storage", "autoloader"];
14397
14417
  function findWcstackAutoScripts(html) {
14398
14418
  const out = [];
14399
14419
  const scriptRegex = /<script\b(?:"[^"]*"|'[^']*'|[^>"'])*>/gi;
@@ -14401,10 +14421,12 @@ function findWcstackAutoScripts(html) {
14401
14421
  while ((match = scriptRegex.exec(html)) !== null) {
14402
14422
  const src = extractSrc(match[0]);
14403
14423
  if (!src) continue;
14404
- const pkgMatch = /@wcstack\/([a-z0-9-]+)\/auto\b/.exec(src.value);
14405
- if (!pkgMatch) continue;
14424
+ const pkgMatch = SCOPED_AUTO.exec(src.value);
14425
+ const bundle = pkgMatch === null && BUNDLE_AUTO.test(src.value);
14426
+ if (pkgMatch === null && !bundle) continue;
14406
14427
  out.push({
14407
- pkg: pkgMatch[1],
14428
+ pkgs: bundle ? BUNDLE_PACKAGES : [pkgMatch[1]],
14429
+ bundle,
14408
14430
  start: match.index + src.offsetInTag,
14409
14431
  end: match.index + src.offsetInTag + src.value.length
14410
14432
  });
@@ -15863,7 +15885,8 @@ function validateGetterUntrackedReads(script, scriptStart, nestedWriteRoots, loc
15863
15885
  return out;
15864
15886
  }
15865
15887
  var NESTED_WRITE_INPUTS = {
15866
- "wcs-storage": { inputs: ["value"], exemptWhenManual: true }
15888
+ "wcs-storage": { inputs: ["value"], exemptWhenManual: true },
15889
+ "wcs-fetch": { inputs: ["body"], exemptWhenManual: false, oneShot: true }
15867
15890
  };
15868
15891
  var MANUAL_ATTRIBUTE = /(?:^|\s)manual(?:\s|=|$)/i;
15869
15892
  function validateInputNestedWrites(html, stateTagName, bindAttrName, nestedWriteRoots, locale2) {
@@ -15885,6 +15908,7 @@ function validateInputNestedWrites(html, stateTagName, bindAttrName, nestedWrite
15885
15908
  if (!NESTED_WRITE_INPUTS[tag.tagName].inputs.includes(input)) continue;
15886
15909
  const example = nestedWriteRoots().get(occ.path);
15887
15910
  if (example === void 0) continue;
15911
+ const message = NESTED_WRITE_INPUTS[tag.tagName].oneShot ? msgs.inputNestedWriteOneShot(tag.tagName, input, occ.path, example) : msgs.inputNestedWrite(tag.tagName, input, occ.path, example);
15888
15912
  out.push({
15889
15913
  code: WcsDiagnosticCode.InputNestedWrite,
15890
15914
  start: occ.pathRange.start,
@@ -15892,7 +15916,7 @@ function validateInputNestedWrites(html, stateTagName, bindAttrName, nestedWrite
15892
15916
  severity: "warning",
15893
15917
  tag: tag.tagName,
15894
15918
  statePath: occ.path,
15895
- message: msgs.inputNestedWrite(tag.tagName, input, occ.path, example)
15919
+ message
15896
15920
  });
15897
15921
  }
15898
15922
  return out;
@@ -573,7 +573,7 @@ function loadSchemaCore() {
573
573
  return cached;
574
574
  }
575
575
 
576
- var version = "4.0.2";
576
+ var version = "4.0.3";
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.2";
8
+ var version = "4.0.3";
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.2",
3
+ "version": "4.0.3",
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",