@needle-tools/needle-component-compiler 3.0.15 → 3.0.17

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/Changelog.md CHANGED
@@ -4,6 +4,24 @@ All notable changes to this package will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [3.0.17] - 2026-04-17
8
+ ### Added
9
+ - Support for string literal union types (e.g. `axis: "x" | "y" | "z" = "y"`)
10
+ - C#: emits as `string` field with default value
11
+ - Blender: emits as `enum` with string options and correct default value
12
+
13
+ ### Fixed
14
+ - Blender: emit default values for `new` expressions with arguments (e.g. `new Vector3(0, 1, 0)` now emits `"value": [0, 1, 0]`)
15
+ - Blender: emit actual values for primitive array initializers (e.g. `speeds: number[] = [1, 2, 3]` now emits `"value": [1, 2, 3]` instead of `[]`)
16
+ - Blender: format enum `options` array with one entry per line, matching `builtin.component.json` style
17
+
18
+ ## [3.0.16] - 2026-03-24
19
+ ### Fixed
20
+ - Fix array literal initializers (`= []`, `= [1, 2, 3]`) emitting C# 12 collection expressions not supported by Unity
21
+ - Empty arrays: initializer is omitted
22
+ - Non-empty primitive arrays: emit `new float[] { 1f, 2f, 3f }` syntax
23
+ - Non-empty non-primitive arrays: initializer is omitted
24
+
7
25
  ## [3.0.15] - 2026-03-23
8
26
  ### Fixed
9
27
  - Fix non-void method stubs producing uncompilable C# (`CS0161: not all code paths return a value`) by emitting `{ return default; }` instead of `{}`
package/dist/Compiler.js CHANGED
@@ -392,6 +392,20 @@ var Compiler = /** @class */ (function () {
392
392
  }
393
393
  // Union types: Object3D | null | undefined → resolve the first concrete member
394
394
  if (ts.isUnionTypeNode(typeNode)) {
395
+ // Check if all non-null/undefined members are string literals (e.g. "none" | "XY" | "XZ")
396
+ var concreteMembers = typeNode.types.filter(function (m) {
397
+ return m.kind !== ts.SyntaxKind.NullKeyword &&
398
+ m.kind !== ts.SyntaxKind.UndefinedKeyword &&
399
+ m.kind !== ts.SyntaxKind.VoidKeyword;
400
+ });
401
+ if (concreteMembers.length > 0 && concreteMembers.every(function (m) { return ts.isLiteralTypeNode(m) && ts.isStringLiteral(m.literal); })) {
402
+ // Synthesize a virtual enum from the string literal values
403
+ var options = concreteMembers.map(function (m) { return m.literal.getText().replace(/^['"]|['"]$/g, ""); });
404
+ var syntheticName = "__strlit_" + options.join("_");
405
+ var members = options.map(function (o) { return ({ name: o, value: o }); });
406
+ writer.registerEnum(syntheticName, members);
407
+ return this.resolveTypeFromString(syntheticName, writer);
408
+ }
395
409
  for (var _b = 0, _c = typeNode.types; _b < _c.length; _b++) {
396
410
  var member = _c[_b];
397
411
  if (member.kind !== ts.SyntaxKind.NullKeyword &&
@@ -136,17 +136,29 @@ var BlenderWriter = /** @class */ (function (_super) {
136
136
  if (enumMembers && enumMembers.length > 0) {
137
137
  this.writer.beginBlock("\"" + name + "\": {");
138
138
  this.writer.writeLine("\"type\": \"enum\",");
139
- // Resolve default value: try to match explicit initializer (e.g. "lighttype.spot")
139
+ // Resolve default value: try to match explicit initializer (e.g. "lighttype.spot" or bare "none")
140
140
  var enumValue = enumMembers[0].value;
141
- if (initialValue && initialValue.includes(".")) {
142
- var memberKey_1 = initialValue.split(".").pop();
143
- var found = enumMembers.find(function (m) { return m.name.toLowerCase() === memberKey_1; });
144
- if (found !== undefined)
145
- enumValue = found.value;
141
+ if (initialValue) {
142
+ if (initialValue.includes(".")) {
143
+ var memberKey_1 = initialValue.split(".").pop();
144
+ var found = enumMembers.find(function (m) { return m.name.toLowerCase() === memberKey_1; });
145
+ if (found !== undefined)
146
+ enumValue = found.value;
147
+ }
148
+ else {
149
+ // Bare value (string literal union default, e.g. "none")
150
+ var found = enumMembers.find(function (m) { return m.name.toLowerCase() === initialValue.toLowerCase() || String(m.value).toLowerCase() === initialValue.toLowerCase(); });
151
+ if (found !== undefined)
152
+ enumValue = found.value;
153
+ }
146
154
  }
147
155
  this.writer.writeLine("\"value\": " + JSON.stringify(enumValue) + ",");
148
156
  var options = enumMembers.map(function (m) { return m.name; });
149
- this.writer.writeLine("\"options\": " + JSON.stringify(options));
157
+ this.writer.beginBlock("\"options\": [");
158
+ for (var i = 0; i < options.length; i++) {
159
+ this.writer.writeLine(JSON.stringify(options[i]) + ",");
160
+ }
161
+ this.writer.endBlock("]");
150
162
  this.writer.endBlock("},");
151
163
  return;
152
164
  }
@@ -160,20 +172,41 @@ var BlenderWriter = /** @class */ (function (_super) {
160
172
  this.writer.beginBlock("\"" + name + "\": {");
161
173
  this.writer.writeLine("\"type\": \"" + type + "\",");
162
174
  if (initialValue && !isArray) {
163
- if (initialValue.startsWith("new "))
175
+ if (initialValue.startsWith("new ")) {
176
+ // Extract constructor args: "new Vector3(1, 2, 3)" → [1, 2, 3]
177
+ var argsMatch = initialValue.match(/\(([^)]*)\)/);
178
+ var argsStr = argsMatch ? argsMatch[1].trim() : "";
179
+ if (argsStr.length > 0) {
180
+ var args = argsStr.split(",").map(function (a) { return a.trim(); });
181
+ this.writer.writeLine("\"value\": [" + args.join(", ") + "],");
182
+ }
164
183
  initialValue = undefined;
184
+ }
165
185
  switch (type) {
166
186
  case "bool":
167
- initialValue = initialValue.toLowerCase();
187
+ initialValue = initialValue === null || initialValue === void 0 ? void 0 : initialValue.toLowerCase();
168
188
  break;
169
189
  case "string":
170
- initialValue = "\"" + initialValue + "\"";
190
+ initialValue = initialValue ? "\"" + initialValue + "\"" : undefined;
171
191
  }
172
192
  if (initialValue)
173
193
  this.writer.writeLine("\"value\": " + initialValue + ",");
174
194
  }
175
195
  if (isArray) {
176
- this.writer.writeLine("\"value\": [],");
196
+ if (initialValue && initialValue.startsWith("[") && initialValue !== "[]") {
197
+ // For string arrays, re-quote each element: [a, b, c] → ["a", "b", "c"]
198
+ if (type === "string") {
199
+ var inner = initialValue.slice(1, -1);
200
+ var elements = inner.split(",").map(function (e) { return "\"" + e.trim() + "\""; });
201
+ this.writer.writeLine("\"value\": [" + elements.join(", ") + "],");
202
+ }
203
+ else {
204
+ this.writer.writeLine("\"value\": " + initialValue + ",");
205
+ }
206
+ }
207
+ else {
208
+ this.writer.writeLine("\"value\": [],");
209
+ }
177
210
  }
178
211
  if (tooltip) {
179
212
  this.writer.writeLine("\"description\": \"" + tooltip.replace(/"/g, "'") + "\"");
@@ -133,6 +133,9 @@ var CSharpWriter = /** @class */ (function (_super) {
133
133
  var _a, _b, _c, _d, _e;
134
134
  if (!typescriptTypeName)
135
135
  return undefined;
136
+ // String literal union synthetic enums (e.g. __strlit_none_XY_XZ) → string
137
+ if (typescriptTypeName.startsWith("__strlit_"))
138
+ return "string";
136
139
  // Strip THREE. prefix for lookup fallback
137
140
  var stripped = typescriptTypeName.startsWith("THREE.") ? typescriptTypeName.substring(6) : typescriptTypeName;
138
141
  // Check built-in TYPE_MAP first (TS→C# mapping)
@@ -245,6 +248,29 @@ var CSharpWriter = /** @class */ (function (_super) {
245
248
  if (initialValue === "null") {
246
249
  // keep null for reference types, skip for value types
247
250
  }
251
+ else if (isArray && initialValue === "[]") {
252
+ // Skip empty array initializers — C# 12 collection expressions (= [])
253
+ // are not supported by Unity's C# version
254
+ }
255
+ else if (isArray && initialValue.startsWith("[")) {
256
+ // Convert [1, 2, 3] → new float[] { 1f, 2f, 3f }
257
+ // Only emit prefilled arrays for primitive types that can be expressed as literals
258
+ if (csharpType === "float" || csharpType === "bool" || csharpType === "string") {
259
+ var inner = initialValue.slice(1, -1);
260
+ var elements = inner.split(",").map(function (e) {
261
+ var v = e.trim();
262
+ if (csharpType === "float")
263
+ return "".concat(v, "f");
264
+ if (csharpType === "bool")
265
+ return v.toLowerCase();
266
+ if (csharpType === "string")
267
+ return "\"".concat(v, "\"");
268
+ return v;
269
+ });
270
+ assignment = " = new ".concat(csharpType, "[] { ").concat(elements.join(", "), " }");
271
+ }
272
+ // For non-primitive types, skip the initializer entirely
273
+ }
248
274
  else if (csharpType === "float") {
249
275
  assignment = " = ".concat(initialValue, "f");
250
276
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/needle-component-compiler",
3
- "version": "3.0.15",
3
+ "version": "3.0.17",
4
4
  "description": "Compile Editor components for Needle Engine for C# and Blender",
5
5
  "main": "dist/index.js",
6
6
  "bin": "dist/cli.js",