@neocompose/cli 0.68.0 → 0.68.1

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
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.68.1] - 2026-10-05
4
+
5
+ - An override of a generic class's function, as in `protected override int Apply(int next)` in a class that extends `ValueWatcher<int>`, checks its compiled body against the signature its class closes. Before, export and publish failed with "NSFunction action parameter 0 type does not match its public signature." An override can also close the param with a List, as in `Picker<List<int>>`, or forward it to its own class's param, as in `class Forward<V> : Watch<V>` or `Picker<Box<V>>`, or bind it to a multiselect enum, as in `Picker<Set<Mood>>`. A base constructor argument can forward a param inside a binding, as in `: Watch<Box<V>>(initial: initial)`, and a base bound to `Set<Mood>` takes a set. A multiselect enum member no longer satisfies an interface property typed as a single enum. Before, push failed with "compiled action return type is stale." or "Returned Box<V> is not assignable to declared return type Box".
6
+
3
7
  ## [0.68.0] - 2026-10-04
4
8
 
5
9
  - Author member subscriptions with `value.Field.OnChanged += handler` and `-=`, and persist wiring with `@listeners(Field: [handler])`. Listener arguments must be named; multiple fields may appear in any order.
package/dist/neo.mjs CHANGED
@@ -31193,7 +31193,7 @@ var init_registry = __esm({
31193
31193
  "../packages/manifest/schema-contract/registry.mjs"() {
31194
31194
  "use strict";
31195
31195
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
31196
- cliVersion: "0.68.0",
31196
+ cliVersion: "0.68.1",
31197
31197
  projectFileUploadBatchSize: 32,
31198
31198
  documentRecords: {
31199
31199
  member: {
@@ -47792,30 +47792,118 @@ function substituteMember(member, env, members, preResolvedMember) {
47792
47792
  return resolved;
47793
47793
  }
47794
47794
  function substituteNestedTypeInfo(typeInfo, env, members) {
47795
- if (typeInfo.type === 21 /* Generic */) {
47796
- const entry = env.get(typeInfo.genericParamId);
47795
+ return mapGenericTypeInfo(typeInfo, (generic) => {
47796
+ const entry = env.get(generic.genericParamId);
47797
47797
  if (entry === void 0) {
47798
47798
  throw new Error(
47799
- `substituteMember: callable type references generic param "${typeInfo.genericParamId}", which is not present in the binding environment.`
47799
+ `substituteMember: callable type references generic param "${generic.genericParamId}", which is not present in the binding environment.`
47800
47800
  );
47801
47801
  }
47802
- if (entry.kind === "unbound") return typeInfo;
47803
- const binding = memberIndexFor(members).get(entry.memberId);
47804
- if (binding === void 0) {
47805
- throw new Error(
47806
- `substituteMember: callable type binding member "${entry.memberId}" for generic param "${typeInfo.genericParamId}" does not exist in the document.`
47807
- );
47802
+ if (entry.kind === "unbound") return generic;
47803
+ return genericBindingTypeInfo(
47804
+ callableBindingMember(entry.memberId, generic.genericParamId, members),
47805
+ env,
47806
+ members
47807
+ );
47808
+ });
47809
+ }
47810
+ function substituteInheritedCallableTypeInfo(typeInfo, env, classes, members) {
47811
+ return mapGenericTypeInfo(typeInfo, (generic) => {
47812
+ const entry = env.get(generic.genericParamId);
47813
+ if (entry === void 0) return generic;
47814
+ if (entry.kind === "unbound") {
47815
+ const forwarded = forwardedParamTypeInfo(entry.paramId, classes);
47816
+ return forwarded === null ? generic : { ...forwarded, required: generic.required };
47808
47817
  }
47809
- return genericBindingTypeInfo(binding, env, members);
47818
+ const bound = openBindingTypeInfo(
47819
+ callableBindingMember(entry.memberId, generic.genericParamId, members),
47820
+ env,
47821
+ classes,
47822
+ members
47823
+ );
47824
+ return { ...bound, required: bound.required && generic.required };
47825
+ });
47826
+ }
47827
+ function forwardedParamTypeInfo(genericParamId, classes) {
47828
+ const declaration = findGenericParamDeclaration(genericParamId, classes);
47829
+ if (declaration === null) return null;
47830
+ return {
47831
+ type: 21 /* Generic */,
47832
+ required: true,
47833
+ ownerClassId: declaration.declaringClass.id,
47834
+ genericParamId
47835
+ };
47836
+ }
47837
+ function openBindingTypeInfo(member, env, classes, members) {
47838
+ const resolved = resolveMember(member, members);
47839
+ const nested = (memberId) => openBindingTypeInfo(
47840
+ callableBindingMember(memberId, resolved.name, members),
47841
+ env,
47842
+ classes,
47843
+ members
47844
+ );
47845
+ const param = (genericParamId) => {
47846
+ const entry = env.get(genericParamId);
47847
+ if (entry?.kind === "member") return nested(entry.memberId);
47848
+ if (entry?.kind === "unbound") {
47849
+ return forwardedParamTypeInfo(entry.paramId, classes);
47850
+ }
47851
+ return null;
47852
+ };
47853
+ if (isMemberGenericBase(resolved)) {
47854
+ return param(resolved.genericParamId) ?? genericBindingTypeInfo(resolved, env, members);
47810
47855
  }
47856
+ const required2 = isRequiredMember2(resolved);
47857
+ if (isMemberClassBase(resolved)) {
47858
+ const typeArguments = {};
47859
+ for (const [parameterId, argument2] of Object.entries(
47860
+ resolved.classArguments ?? {}
47861
+ )) {
47862
+ const argumentType = isForwardedGenericBinding(argument2) ? param(argument2.genericParamId) : nested(argument2.memberId);
47863
+ if (argumentType === null) {
47864
+ return genericBindingTypeInfo(resolved, env, members);
47865
+ }
47866
+ typeArguments[parameterId] = argumentType;
47867
+ }
47868
+ return {
47869
+ type: 7 /* Class */,
47870
+ required: required2,
47871
+ classId: resolved.classId,
47872
+ ...Object.keys(typeArguments).length === 0 ? {} : { typeArguments }
47873
+ };
47874
+ }
47875
+ if (isMemberListBase(resolved)) {
47876
+ return {
47877
+ type: 6 /* List */,
47878
+ required: required2,
47879
+ entryTypeInfo: nested(resolved.entryMemberId)
47880
+ };
47881
+ }
47882
+ if (isMemberDictionaryBase(resolved)) {
47883
+ return {
47884
+ type: 5 /* Dictionary */,
47885
+ required: required2,
47886
+ entryTypeInfo: nested(resolved.entryMemberId),
47887
+ ...resolved.keyEnumId == null ? {} : { keyEnumId: resolved.keyEnumId }
47888
+ };
47889
+ }
47890
+ return genericBindingTypeInfo(resolved, env, members);
47891
+ }
47892
+ function callableBindingMember(memberId, slotName, members) {
47893
+ const binding = memberIndexFor(members).get(memberId);
47894
+ if (binding === void 0) {
47895
+ throw new Error(
47896
+ `substituteMember: callable type binding member "${memberId}" for "${slotName}" does not exist in the document.`
47897
+ );
47898
+ }
47899
+ return binding;
47900
+ }
47901
+ function mapGenericTypeInfo(typeInfo, close) {
47902
+ if (typeInfo.type === 21 /* Generic */) return close(typeInfo);
47811
47903
  if (typeInfo.type === 6 /* List */ || typeInfo.type === 5 /* Dictionary */ || typeInfo.type === 9 /* Lookup */) {
47812
47904
  return {
47813
47905
  ...typeInfo,
47814
- entryTypeInfo: substituteNestedTypeInfo(
47815
- typeInfo.entryTypeInfo,
47816
- env,
47817
- members
47818
- )
47906
+ entryTypeInfo: mapGenericTypeInfo(typeInfo.entryTypeInfo, close)
47819
47907
  };
47820
47908
  }
47821
47909
  if (typeInfo.type === 7 /* Class */) {
@@ -47826,7 +47914,7 @@ function substituteNestedTypeInfo(typeInfo, env, members) {
47826
47914
  typeArguments: Object.fromEntries(
47827
47915
  Object.entries(typeArguments).map(([parameterId, argument2]) => [
47828
47916
  parameterId,
47829
- substituteNestedTypeInfo(argument2, env, members)
47917
+ mapGenericTypeInfo(argument2, close)
47830
47918
  ])
47831
47919
  )
47832
47920
  };
@@ -47834,13 +47922,9 @@ function substituteNestedTypeInfo(typeInfo, env, members) {
47834
47922
  if (typeInfo.type === 25 /* NSDelegate */) {
47835
47923
  return {
47836
47924
  ...typeInfo,
47837
- returnTypeInfo: substituteNestedTypeInfo(
47838
- typeInfo.returnTypeInfo,
47839
- env,
47840
- members
47841
- ),
47925
+ returnTypeInfo: mapGenericTypeInfo(typeInfo.returnTypeInfo, close),
47842
47926
  argumentTypes: typeInfo.argumentTypes.map(
47843
- (argument2) => substituteNestedTypeInfo(argument2, env, members)
47927
+ (argument2) => mapGenericTypeInfo(argument2, close)
47844
47928
  )
47845
47929
  };
47846
47930
  }
@@ -47848,7 +47932,7 @@ function substituteNestedTypeInfo(typeInfo, env, members) {
47848
47932
  return {
47849
47933
  ...typeInfo,
47850
47934
  argumentTypes: typeInfo.argumentTypes.map(
47851
- (argument2) => substituteNestedTypeInfo(argument2, env, members)
47935
+ (argument2) => mapGenericTypeInfo(argument2, close)
47852
47936
  )
47853
47937
  };
47854
47938
  }
@@ -47880,11 +47964,16 @@ function typeInfoFromArgumentSignature(signature) {
47880
47964
  }
47881
47965
  if (signature.type === 8 /* Enum */) {
47882
47966
  const enumSignature = signature;
47883
- return {
47967
+ const enumTypeInfo = {
47884
47968
  type: 8 /* Enum */,
47885
47969
  required: enumSignature.required,
47886
47970
  enumId: enumSignature.enumId
47887
47971
  };
47972
+ return enumSignature.multiselect ? {
47973
+ type: 9 /* Lookup */,
47974
+ required: enumSignature.required,
47975
+ entryTypeInfo: { ...enumTypeInfo, required: true }
47976
+ } : enumTypeInfo;
47888
47977
  }
47889
47978
  if (signature.type === 6 /* List */) {
47890
47979
  const listSignature = signature;
@@ -88142,6 +88231,7 @@ function compileConstructorBaseArguments(args, owner) {
88142
88231
  deleteRecordField(args.constructor, "compiledBaseArguments");
88143
88232
  return;
88144
88233
  }
88234
+ const ownerEnv = resolveGenericEnv(owner.id, args.classes);
88145
88235
  const compiledBaseArguments = baseArguments.map(
88146
88236
  (baseArgument) => {
88147
88237
  const parameter4 = baseConstructor.argumentTypes.find(
@@ -88152,10 +88242,11 @@ function compileConstructorBaseArguments(args, owner) {
88152
88242
  `Constructor "${args.constructor.id}" binds base argument "${baseArgument.name}", which base constructor "${baseConstructor.id}" does not declare.`
88153
88243
  );
88154
88244
  }
88155
- const returnTypeInfo = substituteConstructorBaseType(
88245
+ const returnTypeInfo = substituteInheritedCallableTypeInfo(
88156
88246
  parameter4,
88157
- owner,
88158
- args
88247
+ ownerEnv,
88248
+ args.classes,
88249
+ args.members
88159
88250
  );
88160
88251
  return compileUnit2(
88161
88252
  "getter",
@@ -88171,73 +88262,6 @@ function compileConstructorBaseArguments(args, owner) {
88171
88262
  );
88172
88263
  Object.assign(args.constructor, { compiledBaseArguments });
88173
88264
  }
88174
- function substituteConstructorBaseType(typeInfo, owner, args) {
88175
- if (typeInfo.type === 21 /* Generic */) {
88176
- const binding = resolveGenericEnv(owner.id, args.classes).get(
88177
- typeInfo.genericParamId
88178
- );
88179
- if (binding === void 0) return typeInfo;
88180
- if (binding.kind === "unbound") {
88181
- return {
88182
- ...typeInfo,
88183
- ownerClassId: owner.id,
88184
- genericParamId: binding.paramId
88185
- };
88186
- }
88187
- const member = args.members.find(
88188
- (candidate) => candidate.id === binding.memberId
88189
- );
88190
- if (member === void 0) {
88191
- throw new Error(
88192
- `Constructor "${args.constructor.id}" resolves generic parameter "${typeInfo.genericParamId}" to missing member "${binding.memberId}".`
88193
- );
88194
- }
88195
- return resolveMemberDeclaredTypeInfo(member, args.members) ?? typeInfo;
88196
- }
88197
- if (typeInfo.type === 25 /* NSDelegate */) {
88198
- return {
88199
- ...typeInfo,
88200
- returnTypeInfo: substituteConstructorBaseType(
88201
- typeInfo.returnTypeInfo,
88202
- owner,
88203
- args
88204
- ),
88205
- argumentTypes: typeInfo.argumentTypes.map(
88206
- (argument2) => substituteConstructorBaseType(argument2, owner, args)
88207
- )
88208
- };
88209
- }
88210
- if (typeInfo.type === 26 /* NSAction */) {
88211
- return {
88212
- ...typeInfo,
88213
- argumentTypes: typeInfo.argumentTypes.map(
88214
- (argument2) => substituteConstructorBaseType(argument2, owner, args)
88215
- )
88216
- };
88217
- }
88218
- if (typeInfo.type === 6 /* List */ || typeInfo.type === 5 /* Dictionary */ || typeInfo.type === 9 /* Lookup */) {
88219
- return {
88220
- ...typeInfo,
88221
- entryTypeInfo: substituteConstructorBaseType(
88222
- typeInfo.entryTypeInfo,
88223
- owner,
88224
- args
88225
- )
88226
- };
88227
- }
88228
- if (typeInfo.type !== 7 /* Class */ || typeInfo.typeArguments === void 0) {
88229
- return typeInfo;
88230
- }
88231
- return {
88232
- ...typeInfo,
88233
- typeArguments: Object.fromEntries(
88234
- Object.entries(typeInfo.typeArguments).map(([parameterId, argument2]) => [
88235
- parameterId,
88236
- substituteConstructorBaseType(argument2, owner, args)
88237
- ])
88238
- )
88239
- };
88240
- }
88241
88265
  function compileConstructorBaseInitializerFields(args, owner) {
88242
88266
  const fields = args.constructor.baseInitializerFields ?? [];
88243
88267
  if (fields.length === 0) {
@@ -109030,6 +109054,19 @@ function stableValue(value) {
109030
109054
  function stableTypeInfo(value) {
109031
109055
  return JSON.stringify(stableValue(value));
109032
109056
  }
109057
+ function callableTypeIdentity(value) {
109058
+ return stableTypeInfo(withoutListCapability(value));
109059
+ }
109060
+ function withoutListCapability(value) {
109061
+ if (Array.isArray(value)) return value.map(withoutListCapability);
109062
+ if (!isRecord7(value)) return value;
109063
+ const result = {};
109064
+ for (const [key, entry] of Object.entries(value)) {
109065
+ if (key === "listMemberId") continue;
109066
+ result[key] = withoutListCapability(entry);
109067
+ }
109068
+ return result;
109069
+ }
109033
109070
  function isOpaqueGeneratedIdentifier(value, neoPredicate) {
109034
109071
  return typeof value === "string" && neoPredicate(value) && isGeneratedCSharpIdentifier(value) && !isGeneratedCSharpReservedKeyword(value);
109035
109072
  }
@@ -110039,6 +110076,16 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
110039
110076
  inspectValueBody(syntheticMember2, value.value, value.classId);
110040
110077
  }
110041
110078
  function genericEnvForClass(schemaClass2) {
110079
+ const env = /* @__PURE__ */ new Map();
110080
+ for (const [paramId, binding] of genericBindingsForClass(schemaClass2)) {
110081
+ env.set(
110082
+ paramId,
110083
+ binding.kind === 1 /* Member */ ? binding.memberId : null
110084
+ );
110085
+ }
110086
+ return env;
110087
+ }
110088
+ function genericBindingsForClass(schemaClass2) {
110042
110089
  const chain = [];
110043
110090
  const seen = /* @__PURE__ */ new Set();
110044
110091
  let current = schemaClass2;
@@ -110047,25 +110094,26 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
110047
110094
  chain.push(current);
110048
110095
  current = current.extendsClassId ? classesById.get(current.extendsClassId) : void 0;
110049
110096
  }
110050
- const env = /* @__PURE__ */ new Map();
110097
+ const bindings = /* @__PURE__ */ new Map();
110051
110098
  for (let declarerIndex = 0; declarerIndex < chain.length; declarerIndex += 1) {
110052
110099
  for (const param of chain[declarerIndex]?.genericParams ?? []) {
110053
110100
  let cursor = param.id;
110054
- let terminalMemberId = null;
110101
+ let terminal2 = {
110102
+ kind: 0 /* Generic */,
110103
+ genericParamId: cursor
110104
+ };
110055
110105
  for (let level = declarerIndex; level > 0; level -= 1) {
110056
110106
  const child2 = chain[level - 1];
110057
110107
  const binding = child2?.extendsGenericBindings?.[cursor];
110058
110108
  if (!binding) break;
110059
- if (binding.kind === 1 /* Member */) {
110060
- terminalMemberId = binding.memberId;
110061
- break;
110062
- }
110109
+ terminal2 = binding;
110110
+ if (binding.kind === 1 /* Member */) break;
110063
110111
  cursor = binding.genericParamId;
110064
110112
  }
110065
- env.set(param.id, terminalMemberId);
110113
+ bindings.set(param.id, terminal2);
110066
110114
  }
110067
110115
  }
110068
- return env;
110116
+ return bindings;
110069
110117
  }
110070
110118
  function substituteMemberForClass(member, schemaClass2) {
110071
110119
  const resolved = resolveMember4(member);
@@ -110102,7 +110150,10 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
110102
110150
  const resolved = substituteMemberForClass(member, schemaClass2);
110103
110151
  const required2 = isRequiredMember2(resolved);
110104
110152
  if (resolved.kind === 10) return resolved.returnTypeInfo ?? null;
110105
- if (resolved.kind === 13 || resolved.kind === 21 || resolved.kind === 22 || resolved.kind === 23) {
110153
+ if (resolved.kind === 21) {
110154
+ return typeof resolved.genericParamId === "string" ? forwardedGenericTypeInfo(resolved.genericParamId, schemaClass2) : null;
110155
+ }
110156
+ if (resolved.kind === 13 || resolved.kind === 22 || resolved.kind === 23) {
110106
110157
  return null;
110107
110158
  }
110108
110159
  if (resolved.kind === 7) {
@@ -110111,7 +110162,15 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
110111
110162
  for (const [paramId, binding] of Object.entries(
110112
110163
  resolved.classArguments ?? {}
110113
110164
  )) {
110114
- if (binding.kind !== 1 /* Member */) return null;
110165
+ if (binding.kind !== 1 /* Member */) {
110166
+ const forwarded = forwardedGenericTypeInfo(
110167
+ binding.genericParamId,
110168
+ schemaClass2
110169
+ );
110170
+ if (!forwarded) return null;
110171
+ typeArguments[paramId] = forwarded;
110172
+ continue;
110173
+ }
110115
110174
  const bindingMember = membersById.get(binding.memberId);
110116
110175
  if (!bindingMember) return null;
110117
110176
  const bindingTypeInfo = memberTypeInfo(
@@ -110130,7 +110189,12 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
110130
110189
  };
110131
110190
  }
110132
110191
  if (resolved.kind === 8) {
110133
- return typeof resolved.enumId === "string" ? { type: 8, required: required2, enumId: resolved.enumId } : null;
110192
+ if (typeof resolved.enumId !== "string") return null;
110193
+ return resolved.selection === 1 /* Multi */ ? {
110194
+ type: 9,
110195
+ required: required2,
110196
+ entryTypeInfo: { type: 8, required: true, enumId: resolved.enumId }
110197
+ } : { type: 8, required: required2, enumId: resolved.enumId };
110134
110198
  }
110135
110199
  if (resolved.kind === 5 || resolved.kind === 6) {
110136
110200
  if (typeof resolved.entryMemberId !== "string") return null;
@@ -110234,13 +110298,36 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
110234
110298
  genericParamId: resolved.genericParamId
110235
110299
  });
110236
110300
  };
110301
+ const forwardedGenericTypeInfo = (genericParamId, schemaClass2) => {
110302
+ const terminal2 = genericBindingsForClass(schemaClass2).get(genericParamId);
110303
+ if (terminal2 === void 0) return null;
110304
+ if (terminal2.kind === 1 /* Member */) return null;
110305
+ const ownerClassId = genericParamDeclarationsById.get(
110306
+ terminal2.genericParamId
110307
+ )?.ownerClassId;
110308
+ if (ownerClassId === void 0) return null;
110309
+ return {
110310
+ type: 21,
110311
+ required: true,
110312
+ ownerClassId,
110313
+ genericParamId: terminal2.genericParamId
110314
+ };
110315
+ };
110237
110316
  const substituteTypeInfoForClass = (typeInfo, schemaClass2) => {
110238
110317
  if (!isRecord7(typeInfo)) return typeInfo;
110239
110318
  if (typeInfo.type === 21 && typeof typeInfo.genericParamId === "string") {
110240
- const bindingId = genericEnvForClass(schemaClass2).get(
110319
+ const terminal2 = genericBindingsForClass(schemaClass2).get(
110241
110320
  typeInfo.genericParamId
110242
110321
  );
110243
- const binding = bindingId ? membersById.get(bindingId) : void 0;
110322
+ if (terminal2 === void 0) return typeInfo;
110323
+ if (terminal2.kind !== 1 /* Member */) {
110324
+ const forwarded = forwardedGenericTypeInfo(
110325
+ typeInfo.genericParamId,
110326
+ schemaClass2
110327
+ );
110328
+ return forwarded ? { ...forwarded, required: typeInfo.required === true } : typeInfo;
110329
+ }
110330
+ const binding = membersById.get(terminal2.memberId);
110244
110331
  const boundType = binding ? memberTypeInfo(binding, schemaClass2) : null;
110245
110332
  return isRecord7(boundType) ? {
110246
110333
  ...boundType,
@@ -110496,7 +110583,7 @@ function assertOpaqueCompiledNSFunctionAction(member, signature, typeInfoInDecla
110496
110583
  `NSFunction "${member.id}" Void return type must be required.`
110497
110584
  );
110498
110585
  }
110499
- if (stableTypeInfo(member.action.typeInfo) !== stableTypeInfo(typeInfoInDeclaringClass(normalizedReturnType2))) {
110586
+ if (callableTypeIdentity(member.action.typeInfo) !== callableTypeIdentity(typeInfoInDeclaringClass(normalizedReturnType2))) {
110500
110587
  throw new Error(
110501
110588
  `NSFunction "${member.id}" compiled action return type is stale.`
110502
110589
  );
@@ -110524,7 +110611,7 @@ function assertOpaqueCompiledNSFunctionAction(member, signature, typeInfoInDecla
110524
110611
  `NSFunction "${member.id}" compiled action parameter ${index + 1} is stale.`
110525
110612
  );
110526
110613
  }
110527
- if (!isRecord7(parameter4.typeInfo) || stableTypeInfo(parameter4.typeInfo) !== stableTypeInfo(
110614
+ if (!isRecord7(parameter4.typeInfo) || callableTypeIdentity(parameter4.typeInfo) !== callableTypeIdentity(
110528
110615
  typeInfoInDeclaringClass(signature.argumentTypes[index])
110529
110616
  )) {
110530
110617
  throw new Error(
@@ -164154,7 +164241,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
164154
164241
  async function main() {
164155
164242
  const args = parseArgs(process.argv.slice(2));
164156
164243
  if (args.command === "--version") {
164157
- console.log("0.68.0");
164244
+ console.log("0.68.1");
164158
164245
  return;
164159
164246
  }
164160
164247
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
@@ -7975,30 +7975,36 @@ function substituteMember(member, env, members, preResolvedMember) {
7975
7975
  return resolved;
7976
7976
  }
7977
7977
  function substituteNestedTypeInfo(typeInfo, env, members) {
7978
- if (typeInfo.type === 21 /* Generic */) {
7979
- const entry = env.get(typeInfo.genericParamId);
7978
+ return mapGenericTypeInfo(typeInfo, (generic) => {
7979
+ const entry = env.get(generic.genericParamId);
7980
7980
  if (entry === void 0) {
7981
7981
  throw new Error(
7982
- `substituteMember: callable type references generic param "${typeInfo.genericParamId}", which is not present in the binding environment.`
7983
- );
7984
- }
7985
- if (entry.kind === "unbound") return typeInfo;
7986
- const binding = memberIndexFor(members).get(entry.memberId);
7987
- if (binding === void 0) {
7988
- throw new Error(
7989
- `substituteMember: callable type binding member "${entry.memberId}" for generic param "${typeInfo.genericParamId}" does not exist in the document.`
7982
+ `substituteMember: callable type references generic param "${generic.genericParamId}", which is not present in the binding environment.`
7990
7983
  );
7991
7984
  }
7992
- return genericBindingTypeInfo(binding, env, members);
7985
+ if (entry.kind === "unbound") return generic;
7986
+ return genericBindingTypeInfo(
7987
+ callableBindingMember(entry.memberId, generic.genericParamId, members),
7988
+ env,
7989
+ members
7990
+ );
7991
+ });
7992
+ }
7993
+ function callableBindingMember(memberId, slotName, members) {
7994
+ const binding = memberIndexFor(members).get(memberId);
7995
+ if (binding === void 0) {
7996
+ throw new Error(
7997
+ `substituteMember: callable type binding member "${memberId}" for "${slotName}" does not exist in the document.`
7998
+ );
7993
7999
  }
8000
+ return binding;
8001
+ }
8002
+ function mapGenericTypeInfo(typeInfo, close) {
8003
+ if (typeInfo.type === 21 /* Generic */) return close(typeInfo);
7994
8004
  if (typeInfo.type === 6 /* List */ || typeInfo.type === 5 /* Dictionary */ || typeInfo.type === 9 /* Lookup */) {
7995
8005
  return {
7996
8006
  ...typeInfo,
7997
- entryTypeInfo: substituteNestedTypeInfo(
7998
- typeInfo.entryTypeInfo,
7999
- env,
8000
- members
8001
- )
8007
+ entryTypeInfo: mapGenericTypeInfo(typeInfo.entryTypeInfo, close)
8002
8008
  };
8003
8009
  }
8004
8010
  if (typeInfo.type === 7 /* Class */) {
@@ -8009,7 +8015,7 @@ function substituteNestedTypeInfo(typeInfo, env, members) {
8009
8015
  typeArguments: Object.fromEntries(
8010
8016
  Object.entries(typeArguments).map(([parameterId, argument2]) => [
8011
8017
  parameterId,
8012
- substituteNestedTypeInfo(argument2, env, members)
8018
+ mapGenericTypeInfo(argument2, close)
8013
8019
  ])
8014
8020
  )
8015
8021
  };
@@ -8017,13 +8023,9 @@ function substituteNestedTypeInfo(typeInfo, env, members) {
8017
8023
  if (typeInfo.type === 25 /* NSDelegate */) {
8018
8024
  return {
8019
8025
  ...typeInfo,
8020
- returnTypeInfo: substituteNestedTypeInfo(
8021
- typeInfo.returnTypeInfo,
8022
- env,
8023
- members
8024
- ),
8026
+ returnTypeInfo: mapGenericTypeInfo(typeInfo.returnTypeInfo, close),
8025
8027
  argumentTypes: typeInfo.argumentTypes.map(
8026
- (argument2) => substituteNestedTypeInfo(argument2, env, members)
8028
+ (argument2) => mapGenericTypeInfo(argument2, close)
8027
8029
  )
8028
8030
  };
8029
8031
  }
@@ -8031,7 +8033,7 @@ function substituteNestedTypeInfo(typeInfo, env, members) {
8031
8033
  return {
8032
8034
  ...typeInfo,
8033
8035
  argumentTypes: typeInfo.argumentTypes.map(
8034
- (argument2) => substituteNestedTypeInfo(argument2, env, members)
8036
+ (argument2) => mapGenericTypeInfo(argument2, close)
8035
8037
  )
8036
8038
  };
8037
8039
  }
@@ -8063,11 +8065,16 @@ function typeInfoFromArgumentSignature(signature) {
8063
8065
  }
8064
8066
  if (signature.type === 8 /* Enum */) {
8065
8067
  const enumSignature = signature;
8066
- return {
8068
+ const enumTypeInfo = {
8067
8069
  type: 8 /* Enum */,
8068
8070
  required: enumSignature.required,
8069
8071
  enumId: enumSignature.enumId
8070
8072
  };
8073
+ return enumSignature.multiselect ? {
8074
+ type: 9 /* Lookup */,
8075
+ required: enumSignature.required,
8076
+ entryTypeInfo: { ...enumTypeInfo, required: true }
8077
+ } : enumTypeInfo;
8071
8078
  }
8072
8079
  if (signature.type === 6 /* List */) {
8073
8080
  const listSignature = signature;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.68.0",
3
+ "version": "0.68.1",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -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.68.0 -->
12
+ <!-- reviewed-through-cli: 0.68.1 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -110,7 +110,7 @@ wrappers.
110
110
  The marker near the top of `SKILL.md` must exactly match the package version:
111
111
 
112
112
  ```html
113
- <!-- reviewed-through-cli: 0.68.0 -->
113
+ <!-- reviewed-through-cli: 0.68.1 -->
114
114
  ```
115
115
 
116
116
  The quoted version above is checked too, so this instruction cannot go stale