@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.
- package/dist/cli.js +164 -6
- 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.
|
|
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.
|
|
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 (
|
|
63544
|
+
if (frame) out += `
|
|
63387
63545
|
|
|
63388
|
-
${
|
|
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.
|
|
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.
|
|
12
|
-
"@vesk/compiler": "^0.2.50-canary.
|
|
13
|
-
"@vesk/plugin-tailwind": "^0.2.50-canary.
|
|
14
|
-
"@vesk/runtime": "^0.2.50-canary.
|
|
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",
|