@neocompose/cli 0.70.4 → 0.71.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.70.4",
3
+ "version": "0.71.0",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,19 +34,19 @@
34
34
  "node": ">=22.0.0"
35
35
  },
36
36
  "dependencies": {
37
- "@inquirer/prompts": "^8.5.2",
38
- "convex": "^1.45.0",
37
+ "@inquirer/prompts": "^8.7.3",
38
+ "convex": "^1.46.0",
39
39
  "fflate": "^0.8.3",
40
- "ignore": "^7.0.6",
41
- "valibot": "^1.4.2"
40
+ "ignore": "^7.0.12",
41
+ "valibot": "^1.5.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@formatjs/icu-messageformat-parser": "^3.5.21",
45
45
  "@neocompose/manifest": "file:../packages/manifest",
46
46
  "@neocompose/neoscript-language": "file:../packages/neoscript-language",
47
- "esbuild": "^0.28.1",
48
- "prettier": "^3.9.5",
49
- "uuid": "^14.0.1"
47
+ "esbuild": "^0.28.2",
48
+ "prettier": "^3.9.9",
49
+ "uuid": "^14.0.2"
50
50
  },
51
51
  "repository": {
52
52
  "type": "git",
@@ -9,7 +9,7 @@ description: >-
9
9
  `@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
10
10
  ---
11
11
 
12
- <!-- reviewed-through-cli: 0.70.4 -->
12
+ <!-- reviewed-through-cli: 0.71.0 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -57,6 +57,11 @@ CLI 0.61 adds `while` and `do / while` loops, ordinal string `Replace`,
57
57
  ordered-list `Insert`, and method calls whose results may be discarded.
58
58
  See the [NeoScript reference](neoscript.md) for authoring syntax and limits.
59
59
 
60
+ CLI 0.71 adds collection queries, negative declaration patterns, and native
61
+ Debug output with authored stack traces. Compiled test caches include the
62
+ relative spec path because source coordinates are part of the compiled body.
63
+ Keep Debug output on stderr, including during JSON test runs.
64
+
60
65
  ## Shared implementation contract
61
66
 
62
67
  Manifest contracts, document comparison, normalization, and three-way merge
@@ -110,7 +115,7 @@ wrappers.
110
115
  The marker near the top of `SKILL.md` must exactly match the package version:
111
116
 
112
117
  ```html
113
- <!-- reviewed-through-cli: 0.70.4 -->
118
+ <!-- reviewed-through-cli: 0.71.0 -->
114
119
  ```
115
120
 
116
121
  The quoted version above is checked too, so this instruction cannot go stale
@@ -8,11 +8,12 @@ runtime ownership, evaluation, and migrations.
8
8
  - Inline bodies and snippets
9
9
  - Nullability and ownership
10
10
  - Numeric builtins
11
- - List builtins
11
+ - Collection builtins
12
12
  - Conditional and logical operators
13
13
  - Loops and transfer
14
14
  - Switch
15
15
  - Try/catch
16
+ - Debug output
16
17
  - Evaluation and migrations
17
18
 
18
19
  ## Inline bodies and snippets
@@ -187,12 +188,17 @@ every path that falls through matched the pattern, including when the guard's
187
188
  other paths return from a nested block:
188
189
 
189
190
  ```neo
190
- if (!(item is BedItem bedItem)) {
191
+ if (item is not BedItem bedItem) {
191
192
  throw "Expected a bed item";
192
193
  }
193
194
  return bedItem.Name;
194
195
  ```
195
196
 
197
+ `value is not SomeClass` negates a type test. An optional binding, as in
198
+ `value is not SomeClass item`, exists only where the test is known to be false:
199
+ the `else` branch, the right side of `||`, or after a rejecting guard. The
200
+ operand is evaluated once. `not` remains a normal identifier elsewhere.
201
+
196
202
  Use `SpriteInfo.Empty` when a required sprite should intentionally render no
197
203
  image. It is the canonical non-null empty sprite: it has no backing file and
198
204
  uses slice index zero.
@@ -252,6 +258,34 @@ materializing a filtered list. The same Count forms work on Dictionary and Set
252
258
  collections; dictionary predicates may accept `(key, value)` just like the
253
259
  other collection callbacks.
254
260
 
261
+ Use `Any()` or `Any((item) => predicate)` to check for a match, and
262
+ `All((item) => predicate)` to check every entry. Both short-circuit; an empty
263
+ collection has `Any() == false` and `All(...) == true`.
264
+
265
+ `Last`, `LastOrDefault`, `Single`, and `SingleOrDefault` accept zero arguments
266
+ or one predicate. `Last` throws when no entry matches. `Single` throws unless
267
+ exactly one matches; `SingleOrDefault` still throws for multiple matches.
268
+ The `OrDefault` forms return nullable entries and use `null` for no match.
269
+
270
+ Build eager, read-only list results with `SelectMany((item) => item.Children)`,
271
+ `OrderBy((item) => item.Name)`, `OrderByDescending((item) => item.Score)`,
272
+ `Skip(count)`, `Take(count)`, `SkipWhile((item) => predicate)`,
273
+ `TakeWhile((item) => predicate)`, `Reverse()`, and `Concat(other)`.
274
+ `SelectMany` requires a non-null list or set from its selector. Sorting is
275
+ stable, evaluates each key once, uses ordinal string comparison, and accepts
276
+ bool, int, float, decimal, or string keys, including nullable keys. Null sorts
277
+ first ascending and last descending. Negative skip/take counts
278
+ behave as zero. Reference entries keep their identity and storage permissions;
279
+ a read-only result does not grant additional write access to its entries.
280
+
281
+ ```neo
282
+ return this.Beds
283
+ .SelectMany((bed) => bed.Plants)
284
+ .Where((plant) => plant.Ready)
285
+ .OrderBy((plant) => plant.Name)
286
+ .Take(10);
287
+ ```
288
+
255
289
  Use `items.IndexOf(value)` to return the zero-based index of the first equal
256
290
  list entry, or `-1` when the value is absent. `IndexOf` is list-only and uses
257
291
  the same equality as `Contains`.
@@ -414,6 +448,26 @@ Do not use typed exception classes, parameterless catch, `finally`, `using`,
414
448
  patterns, or host-exception recovery. Completed writes before an error are not
415
449
  rolled back.
416
450
 
451
+ ## Debug output
452
+
453
+ Use `Debug.Log(message)`, `Debug.LogWarning(message)`, and
454
+ `Debug.LogError(message)` as void statements. `Debug.Assert(condition, message)`
455
+ logs an assertion failure when its non-null bool condition is false. Errors
456
+ and failed assertions log without throwing. Both assertion arguments are
457
+ evaluated once even when the condition passes; disabling a host sink also
458
+ preserves argument evaluation.
459
+
460
+ ```neo
461
+ Debug.Log($"Loaded {this.Items.Count} items");
462
+ Debug.Assert(this.Items.Any(), "Expected at least one item");
463
+ ```
464
+
465
+ Messages include authored NeoScript line/column locations and stack frames
466
+ when source metadata is available. Browser consoles and Unity use the matching
467
+ severity; CLI logs go to stderr so JSON stdout stays machine-readable. Getter
468
+ re-evaluation may emit the same log again. `Debug` is a builtin qualifier,
469
+ not a type; an authored local or Class named `Debug` takes precedence.
470
+
417
471
  ## Evaluation and migrations
418
472
 
419
473
  `neo script eval` uses authored values and the same evaluator as the web app.