@vesk/vesk-cli 0.2.50-canary.11 → 0.2.50-canary.12

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.
Files changed (2) hide show
  1. package/dist/cli.js +164 -6
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -147,7 +147,10 @@ var init_errors = __esm({
147
147
  suggestions;
148
148
  nextSteps;
149
149
  tip;
150
+ /** The V-diagnostic code, e.g. `V0501`. */
150
151
  code;
152
+ /** The rendered code frame. Used to be written into `code`, which silently replaced the V-code. */
153
+ frame;
151
154
  constructor(message, opts = {}) {
152
155
  super(message);
153
156
  this.name = "VeskError";
@@ -157,7 +160,8 @@ var init_errors = __esm({
157
160
  this.suggestions = opts.suggestions || [];
158
161
  this.nextSteps = opts.nextSteps || [];
159
162
  this.tip = opts.tip || "";
160
- if (opts.code !== void 0) this.code = opts.code;
163
+ if (opts.code !== void 0 && !opts.code.includes("\n")) this.code = opts.code;
164
+ if (opts.frame !== void 0) this.frame = opts.frame;
161
165
  }
162
166
  static notFound(name, candidates = [], context = {}) {
163
167
  const allCandidates = [.../* @__PURE__ */ new Set([...candidates, ...VESK_BUILTINS])];
@@ -236,6 +240,84 @@ var init_errors = __esm({
236
240
  }
237
241
  );
238
242
  }
243
+ /**
244
+ * A browser-only global used in code the SERVER evaluates.
245
+ *
246
+ * On the server these are either absent (`window is not defined`) or, worse,
247
+ * silently present-but-wrong (`navigator` exists in modern Node, so
248
+ * `navigator.onLine` is `undefined` and a page renders as if it were offline).
249
+ * A raw `ReferenceError` at request time is the worst possible report: it
250
+ * names neither the component nor the fix. This points at the line.
251
+ */
252
+ static ssrUnsafeGlobal(name, context = {}) {
253
+ return new _VeskError(
254
+ `\`${name}\` is browser-only, and this component body runs during SSR.`,
255
+ {
256
+ ...context,
257
+ code: context.code || "V0501",
258
+ suggestions: [
259
+ `Wrap the part that needs the DOM in a {#client} block.`,
260
+ `Move the code into an event handler \u2014 handlers never run on the server.`,
261
+ `Do the setup in on_destroy(), which the compiler only emits on the client.`
262
+ ],
263
+ nextSteps: [
264
+ `component ${context.inComponent ?? "this component"}: wrap the \`${name}\` access in {#client}...{/client}.`,
265
+ `Or guard it: if (typeof ${name} !== 'undefined') { ... }`
266
+ ],
267
+ tip: "SSR renders this component before the client exists. Reading a browser global here either throws during the request or (for `navigator`) silently returns undefined."
268
+ }
269
+ );
270
+ }
271
+ /**
272
+ * The second name from `track()` called as a function.
273
+ *
274
+ * `const &[count, setCount] = track(0)` returns a CELL, not a setter function, so
275
+ * `setCount(1)` throws `setCount is not a function` from generated code with
276
+ * no line of user code in the message. The cell is the writer: `.set(v)`.
277
+ */
278
+ static cellCalledAsFunction(name, context = {}) {
279
+ return new _VeskError(
280
+ `\`${name}\` is a cell, not a function \u2014 cells are written with \`.set()\`.`,
281
+ {
282
+ ...context,
283
+ code: context.code || "V0502",
284
+ suggestions: [
285
+ `Use \`${name}.set(...)\` instead of \`${name}(...)\`.`,
286
+ `Or use the tracked spelling inside an event handler: set(${context.value ?? "value"}, ...)`
287
+ ],
288
+ nextSteps: [
289
+ `const &[${context.value ?? "value"}, ${name}] = track(0) \u2192 \`${name}.set(v)\``,
290
+ "The value read in markup is the first name; the second is the cell object."
291
+ ],
292
+ tip: `\`track()\` returns [value, cell]. \`${name}\` is the cell half.`
293
+ }
294
+ );
295
+ }
296
+ /**
297
+ * `set(value, …)` used outside a rewritten expression.
298
+ *
299
+ * The compiler rewrites `set(count, v)` to `countCell.set(v)` inside JSX and
300
+ * event handlers — but a bare statement in the component body is NOT
301
+ * rewritten, so the runtime `set` receives the value and throws
302
+ * "Cannot read properties of undefined". Pass the CELL, not the value.
303
+ */
304
+ static setWithValueName(name, context = {}) {
305
+ return new _VeskError(
306
+ `\`set(${name}, \u2026)\` needs the CELL, and \`${name}\` is the value half of track().`,
307
+ {
308
+ ...context,
309
+ code: context.code || "V0503",
310
+ suggestions: [
311
+ `Use \`set(${context.cell ?? "cell"}, \u2026)\` or \`${context.cell ?? "cell"}.set(\u2026)\`.`,
312
+ `Or move the set() into an event handler, where the compiler rewrites it for you.`
313
+ ],
314
+ nextSteps: [
315
+ `const &[${name}, ${context.cell ?? "cell"}] = track(0) \u2192 \`${context.cell ?? "cell"}.set(v)\``
316
+ ],
317
+ tip: "set(cell, value) is only rewritten inside JSX and handlers; in a body statement it reaches the runtime untouched."
318
+ }
319
+ );
320
+ }
239
321
  static serverBlockInClient(compName, context = {}) {
240
322
  return new _VeskError(
241
323
  `{#server} block found in client island "${compName}". Client islands render on both server and client, so {#server} blocks have no effect.`,
@@ -21282,7 +21364,7 @@ function validateBlocks(compName, isClient, body, file, source) {
21282
21364
  const { line, column } = offsetToLineCol2(source, pos);
21283
21365
  opts.line = line;
21284
21366
  opts.column = column;
21285
- opts.code = codeFrame(source, line, column);
21367
+ opts.frame = codeFrame(source, line, column);
21286
21368
  }
21287
21369
  throw VeskError.serverBlockInClient(compName, opts);
21288
21370
  }
@@ -21294,7 +21376,7 @@ function validateBlocks(compName, isClient, body, file, source) {
21294
21376
  const { line, column } = offsetToLineCol2(source, pos);
21295
21377
  opts.line = line;
21296
21378
  opts.column = column;
21297
- opts.code = codeFrame(source, line, column);
21379
+ opts.frame = codeFrame(source, line, column);
21298
21380
  }
21299
21381
  throw VeskError.clientBlockInServer(compName, opts);
21300
21382
  }
@@ -38543,7 +38625,10 @@ var init_errors2 = __esm({
38543
38625
  suggestions;
38544
38626
  nextSteps;
38545
38627
  tip;
38628
+ /** The V-diagnostic code, e.g. `V0501`. */
38546
38629
  code;
38630
+ /** The rendered code frame. Used to be written into `code`, which silently replaced the V-code. */
38631
+ frame;
38547
38632
  constructor(message, opts = {}) {
38548
38633
  super(message);
38549
38634
  this.name = "VeskError";
@@ -38553,8 +38638,10 @@ var init_errors2 = __esm({
38553
38638
  this.suggestions = opts.suggestions || [];
38554
38639
  this.nextSteps = opts.nextSteps || [];
38555
38640
  this.tip = opts.tip || "";
38556
- if (opts.code !== void 0)
38641
+ if (opts.code !== void 0 && !opts.code.includes("\n"))
38557
38642
  this.code = opts.code;
38643
+ if (opts.frame !== void 0)
38644
+ this.frame = opts.frame;
38558
38645
  }
38559
38646
  static notFound(name, candidates = [], context = {}) {
38560
38647
  const allCandidates = [.../* @__PURE__ */ new Set([...candidates, ...VESK_BUILTINS2])];
@@ -38627,6 +38714,75 @@ var init_errors2 = __esm({
38627
38714
  tip: "Use plain objects for data and factory functions for constructors inside .vsk files."
38628
38715
  });
38629
38716
  }
38717
+ /**
38718
+ * A browser-only global used in code the SERVER evaluates.
38719
+ *
38720
+ * On the server these are either absent (`window is not defined`) or, worse,
38721
+ * silently present-but-wrong (`navigator` exists in modern Node, so
38722
+ * `navigator.onLine` is `undefined` and a page renders as if it were offline).
38723
+ * A raw `ReferenceError` at request time is the worst possible report: it
38724
+ * names neither the component nor the fix. This points at the line.
38725
+ */
38726
+ static ssrUnsafeGlobal(name, context = {}) {
38727
+ return new _VeskError(`\`${name}\` is browser-only, and this component body runs during SSR.`, {
38728
+ ...context,
38729
+ code: context.code || "V0501",
38730
+ suggestions: [
38731
+ `Wrap the part that needs the DOM in a {#client} block.`,
38732
+ `Move the code into an event handler \u2014 handlers never run on the server.`,
38733
+ `Do the setup in on_destroy(), which the compiler only emits on the client.`
38734
+ ],
38735
+ nextSteps: [
38736
+ `component ${context.inComponent ?? "this component"}: wrap the \`${name}\` access in {#client}...{/client}.`,
38737
+ `Or guard it: if (typeof ${name} !== 'undefined') { ... }`
38738
+ ],
38739
+ tip: "SSR renders this component before the client exists. Reading a browser global here either throws during the request or (for `navigator`) silently returns undefined."
38740
+ });
38741
+ }
38742
+ /**
38743
+ * The second name from `track()` called as a function.
38744
+ *
38745
+ * `const &[count, setCount] = track(0)` returns a CELL, not a setter function, so
38746
+ * `setCount(1)` throws `setCount is not a function` from generated code with
38747
+ * no line of user code in the message. The cell is the writer: `.set(v)`.
38748
+ */
38749
+ static cellCalledAsFunction(name, context = {}) {
38750
+ return new _VeskError(`\`${name}\` is a cell, not a function \u2014 cells are written with \`.set()\`.`, {
38751
+ ...context,
38752
+ code: context.code || "V0502",
38753
+ suggestions: [
38754
+ `Use \`${name}.set(...)\` instead of \`${name}(...)\`.`,
38755
+ `Or use the tracked spelling inside an event handler: set(${context.value ?? "value"}, ...)`
38756
+ ],
38757
+ nextSteps: [
38758
+ `const &[${context.value ?? "value"}, ${name}] = track(0) \u2192 \`${name}.set(v)\``,
38759
+ "The value read in markup is the first name; the second is the cell object."
38760
+ ],
38761
+ tip: `\`track()\` returns [value, cell]. \`${name}\` is the cell half.`
38762
+ });
38763
+ }
38764
+ /**
38765
+ * `set(value, …)` used outside a rewritten expression.
38766
+ *
38767
+ * The compiler rewrites `set(count, v)` to `countCell.set(v)` inside JSX and
38768
+ * event handlers — but a bare statement in the component body is NOT
38769
+ * rewritten, so the runtime `set` receives the value and throws
38770
+ * "Cannot read properties of undefined". Pass the CELL, not the value.
38771
+ */
38772
+ static setWithValueName(name, context = {}) {
38773
+ return new _VeskError(`\`set(${name}, \u2026)\` needs the CELL, and \`${name}\` is the value half of track().`, {
38774
+ ...context,
38775
+ code: context.code || "V0503",
38776
+ suggestions: [
38777
+ `Use \`set(${context.cell ?? "cell"}, \u2026)\` or \`${context.cell ?? "cell"}.set(\u2026)\`.`,
38778
+ `Or move the set() into an event handler, where the compiler rewrites it for you.`
38779
+ ],
38780
+ nextSteps: [
38781
+ `const &[${name}, ${context.cell ?? "cell"}] = track(0) \u2192 \`${context.cell ?? "cell"}.set(v)\``
38782
+ ],
38783
+ tip: "set(cell, value) is only rewritten inside JSX and handlers; in a body statement it reaches the runtime untouched."
38784
+ });
38785
+ }
38630
38786
  static serverBlockInClient(compName, context = {}) {
38631
38787
  return new _VeskError(`{#server} block found in client island "${compName}". Client islands render on both server and client, so {#server} blocks have no effect.`, {
38632
38788
  ...context,
@@ -63380,12 +63536,14 @@ if (cmd === "build") {
63380
63536
  const l = err.line;
63381
63537
  const c = err.column;
63382
63538
  const code = err.code;
63539
+ const frame = err.frame;
63383
63540
  let out = `vesk build: error \u2014 ${err.message}`;
63541
+ if (code) out = `vesk build: [${code}] ${err.message}`;
63384
63542
  if (f) out += `
63385
63543
  File: ${f}${l ? `:${l}${c ? `:${c}` : ""}` : ""}`;
63386
- if (code) out += `
63544
+ if (frame) out += `
63387
63545
 
63388
- ${code}`;
63546
+ ${frame}`;
63389
63547
  console.error(out);
63390
63548
  if (err.stack && !String(err.stack).includes(err.message)) console.error(err.stack);
63391
63549
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/vesk-cli",
3
- "version": "0.2.50-canary.11",
3
+ "version": "0.2.50-canary.12",
4
4
  "type": "module",
5
5
  "description": "Vesk — compiler-first framework for the post-VDOM web. vesk dev, vesk build.",
6
6
  "bin": {
@@ -8,10 +8,10 @@
8
8
  },
9
9
  "main": "./dist/cli.js",
10
10
  "dependencies": {
11
- "@vesk/adapter": "^0.2.50-canary.11",
12
- "@vesk/compiler": "^0.2.50-canary.11",
13
- "@vesk/plugin-tailwind": "^0.2.50-canary.11",
14
- "@vesk/runtime": "^0.2.50-canary.11",
11
+ "@vesk/adapter": "^0.2.50-canary.12",
12
+ "@vesk/compiler": "^0.2.50-canary.12",
13
+ "@vesk/plugin-tailwind": "^0.2.50-canary.12",
14
+ "@vesk/runtime": "^0.2.50-canary.12",
15
15
  "esrap": "^2.3.0",
16
16
  "typescript": "^5.8.0",
17
17
  "ws": "^8.18.0",