@neocompose/cli 0.71.4 → 0.72.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.
@@ -880,10 +880,10 @@ import { parentPort } from "node:worker_threads";
880
880
 
881
881
  // ../src/models/members/member-storage.ts
882
882
  function isMemberStorageKind(value) {
883
- return value === 0 /* Inherit */ || value === 1 /* Immutable */ || value === 2 /* Save */ || value === 3 /* Session */ || value === 4 /* Writable */;
883
+ return value === 0 /* Inherit */ || value === 1 /* Immutable */ || value === 2 /* Save */ || value === 3 /* Session */ || value === 4 /* Writable */ || value === 5 /* User */;
884
884
  }
885
885
  function isEffectiveMemberStorage(value) {
886
- return value === 1 /* Immutable */ || value === 2 /* Save */ || value === 3 /* Session */;
886
+ return value === 1 /* Immutable */ || value === 2 /* Save */ || value === 3 /* Session */ || value === 5 /* User */;
887
887
  }
888
888
  function isClassAllowedStorage(value) {
889
889
  if (!isMemberStorageKind(value)) return false;
@@ -894,7 +894,7 @@ function childEffectiveStorage(declared, parent) {
894
894
  case 0 /* Inherit */:
895
895
  return parent;
896
896
  case 4 /* Writable */:
897
- return parent === 2 /* Save */ ? 2 /* Save */ : 3 /* Session */;
897
+ return parent === 2 /* Save */ || parent === 5 /* User */ ? parent : 3 /* Session */;
898
898
  default:
899
899
  return declared;
900
900
  }
@@ -1124,6 +1124,176 @@ function memberKindSupportsDistribution(kind) {
1124
1124
  return memberKindSupportsStorage(kind);
1125
1125
  }
1126
1126
 
1127
+ // node_modules/uuid/dist-node/regex.js
1128
+ var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
1129
+
1130
+ // node_modules/uuid/dist-node/validate.js
1131
+ function validate(uuid) {
1132
+ return typeof uuid === "string" && regex_default.test(uuid);
1133
+ }
1134
+ var validate_default = validate;
1135
+
1136
+ // node_modules/uuid/dist-node/parse.js
1137
+ function parse(uuid) {
1138
+ if (!validate_default(uuid)) {
1139
+ throw TypeError("Invalid UUID");
1140
+ }
1141
+ let v;
1142
+ return Uint8Array.of((v = parseInt(uuid.slice(0, 8), 16)) >>> 24, v >>> 16 & 255, v >>> 8 & 255, v & 255, (v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(24, 36), 16)) / 1099511627776 & 255, v / 4294967296 & 255, v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255);
1143
+ }
1144
+ var parse_default = parse;
1145
+
1146
+ // node_modules/uuid/dist-node/stringify.js
1147
+ var byteToHex = [];
1148
+ for (let i = 0; i < 256; ++i) {
1149
+ byteToHex.push((i + 256).toString(16).slice(1));
1150
+ }
1151
+ function unsafeStringify(arr, offset = 0) {
1152
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
1153
+ }
1154
+
1155
+ // node_modules/uuid/dist-node/rng.js
1156
+ var rnds8 = new Uint8Array(16);
1157
+ function rng() {
1158
+ return crypto.getRandomValues(rnds8);
1159
+ }
1160
+
1161
+ // node_modules/uuid/dist-node/v35.js
1162
+ function stringToBytes(str) {
1163
+ str = unescape(encodeURIComponent(str));
1164
+ const bytes = new Uint8Array(str.length);
1165
+ for (let i = 0; i < str.length; ++i) {
1166
+ bytes[i] = str.charCodeAt(i);
1167
+ }
1168
+ return bytes;
1169
+ }
1170
+ var DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
1171
+ var URL2 = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
1172
+ function v35(version, hash, value, namespace, buf, offset) {
1173
+ const valueBytes = typeof value === "string" ? stringToBytes(value) : value;
1174
+ const namespaceBytes = typeof namespace === "string" ? parse_default(namespace) : namespace;
1175
+ if (typeof namespace === "string") {
1176
+ namespace = parse_default(namespace);
1177
+ }
1178
+ if (namespace?.length !== 16) {
1179
+ throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");
1180
+ }
1181
+ let bytes = new Uint8Array(16 + valueBytes.length);
1182
+ bytes.set(namespaceBytes);
1183
+ bytes.set(valueBytes, namespaceBytes.length);
1184
+ bytes = hash(bytes);
1185
+ bytes[6] = bytes[6] & 15 | version;
1186
+ bytes[8] = bytes[8] & 63 | 128;
1187
+ if (buf) {
1188
+ offset ??= 0;
1189
+ if (offset < 0 || offset + 16 > buf.length) {
1190
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
1191
+ }
1192
+ for (let i = 0; i < 16; ++i) {
1193
+ buf[offset + i] = bytes[i];
1194
+ }
1195
+ return buf;
1196
+ }
1197
+ return unsafeStringify(bytes);
1198
+ }
1199
+
1200
+ // node_modules/uuid/dist-node/v4.js
1201
+ function v4(options, buf, offset) {
1202
+ if (!buf && !options && crypto.randomUUID) {
1203
+ return crypto.randomUUID();
1204
+ }
1205
+ return _v4(options, buf, offset);
1206
+ }
1207
+ function _v4(options, buf, offset) {
1208
+ options = options || {};
1209
+ const rnds = options.random ?? options.rng?.() ?? rng();
1210
+ if (rnds.length < 16) {
1211
+ throw new Error("Random bytes length must be >= 16");
1212
+ }
1213
+ rnds[6] = rnds[6] & 15 | 64;
1214
+ rnds[8] = rnds[8] & 63 | 128;
1215
+ if (buf) {
1216
+ offset = offset || 0;
1217
+ if (offset < 0 || offset + 16 > buf.length) {
1218
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
1219
+ }
1220
+ for (let i = 0; i < 16; ++i) {
1221
+ buf[offset + i] = rnds[i];
1222
+ }
1223
+ return buf;
1224
+ }
1225
+ return unsafeStringify(rnds);
1226
+ }
1227
+ var v4_default = v4;
1228
+
1229
+ // node_modules/uuid/dist-node/sha1.js
1230
+ import { createHash } from "node:crypto";
1231
+ function sha1(bytes) {
1232
+ if (Array.isArray(bytes)) {
1233
+ bytes = Buffer.from(bytes);
1234
+ } else if (typeof bytes === "string") {
1235
+ bytes = Buffer.from(bytes, "utf8");
1236
+ }
1237
+ return createHash("sha1").update(bytes).digest();
1238
+ }
1239
+ var sha1_default = sha1;
1240
+
1241
+ // node_modules/uuid/dist-node/v5.js
1242
+ function v5(value, namespace, buf, offset) {
1243
+ return v35(80, sha1_default, value, namespace, buf, offset);
1244
+ }
1245
+ v5.DNS = DNS;
1246
+ v5.URL = URL2;
1247
+ var v5_default = v5;
1248
+
1249
+ // ../src/models/project/project-root-members.ts
1250
+ var PROJECT_ROOTS = [
1251
+ {
1252
+ key: "Assets",
1253
+ choice: "assets",
1254
+ projectField: "rootAssetsMemberId",
1255
+ label: "Assets",
1256
+ storage: 1 /* Immutable */
1257
+ },
1258
+ {
1259
+ key: "Save",
1260
+ choice: "save",
1261
+ projectField: "rootSaveFileMemberId",
1262
+ label: "Save",
1263
+ storage: 2 /* Save */
1264
+ },
1265
+ {
1266
+ key: "Session",
1267
+ choice: "session",
1268
+ projectField: "rootSessionMemberId",
1269
+ label: "Session",
1270
+ storage: 3 /* Session */
1271
+ },
1272
+ {
1273
+ key: "User",
1274
+ choice: "user",
1275
+ projectField: "rootUserMemberId",
1276
+ label: "User",
1277
+ storage: 5 /* User */
1278
+ }
1279
+ ];
1280
+ function projectRootMemberIds(project) {
1281
+ return PROJECT_ROOTS.map((root) => project[root.projectField]);
1282
+ }
1283
+ function buildRootStorageMap(project) {
1284
+ const map = /* @__PURE__ */ new Map();
1285
+ for (const root of PROJECT_ROOTS) {
1286
+ map.set(project[root.projectField], root.storage);
1287
+ }
1288
+ return map;
1289
+ }
1290
+ function projectRootMembersInDisplayOrder(project) {
1291
+ return PROJECT_ROOTS.map((root) => ({
1292
+ root,
1293
+ memberId: project[root.projectField]
1294
+ }));
1295
+ }
1296
+
1127
1297
  // ../src/models/core/structural-narrow.ts
1128
1298
  function isObject(value) {
1129
1299
  if (typeof value !== "object") return false;
@@ -4889,6 +5059,7 @@ var ProjectSchemaIndex = class {
4889
5059
  */
4890
5060
  resolvedMembers = /* @__PURE__ */ new WeakMap();
4891
5061
  ancestryByClassId = /* @__PURE__ */ new Map();
5062
+ effectivePlacementsByClassId = /* @__PURE__ */ new Map();
4892
5063
  ancestorIdsByClassId = /* @__PURE__ */ new Map();
4893
5064
  get classes() {
4894
5065
  return this.source.classes;
@@ -4944,12 +5115,19 @@ var ProjectSchemaIndex = class {
4944
5115
  return chain;
4945
5116
  }
4946
5117
  effectiveSchemaPlacement(classId, schemaKey) {
4947
- for (const ownerClass of this.inheritanceChain(classId)) {
4948
- if (typeof ownerClass.schema[schemaKey] === "string") {
4949
- return { ownerClass, schemaKey };
5118
+ let placements = this.effectivePlacementsByClassId.get(classId);
5119
+ if (placements === void 0) {
5120
+ const flattened = /* @__PURE__ */ new Map();
5121
+ for (const ownerClass of this.inheritanceChain(classId)) {
5122
+ for (const key of Object.keys(ownerClass.schema)) {
5123
+ if (!flattened.has(key) && typeof ownerClass.schema[key] === "string")
5124
+ flattened.set(key, { ownerClass, schemaKey: key });
5125
+ }
4950
5126
  }
5127
+ this.effectivePlacementsByClassId.set(classId, flattened);
5128
+ placements = flattened;
4951
5129
  }
4952
- return null;
5130
+ return placements.get(schemaKey) ?? null;
4953
5131
  }
4954
5132
  effectiveMemberId(classId, schemaKey) {
4955
5133
  const placement = this.effectiveSchemaPlacement(classId, schemaKey);
@@ -5053,33 +5231,12 @@ function classIndexFor(classes) {
5053
5231
  function memberIndexFor(members) {
5054
5232
  return projectSchemaIndexFor({ classes: NO_CLASSES, members }).membersById;
5055
5233
  }
5056
- function createMergeMemo() {
5057
- const byClasses = /* @__PURE__ */ new WeakMap();
5058
- return (classId, classIndex, memberIndex, compute) => {
5059
- let byMembers = byClasses.get(classIndex);
5060
- if (byMembers === void 0) {
5061
- byMembers = /* @__PURE__ */ new WeakMap();
5062
- byClasses.set(classIndex, byMembers);
5063
- }
5064
- let byClassId = byMembers.get(memberIndex);
5065
- if (byClassId === void 0) {
5066
- byClassId = /* @__PURE__ */ new Map();
5067
- byMembers.set(memberIndex, byClassId);
5068
- }
5069
- const cached = byClassId.get(classId);
5070
- if (cached !== void 0) return [...cached];
5071
- const computed = compute();
5072
- byClassId.set(classId, computed);
5073
- return [...computed];
5074
- };
5075
- }
5076
- var instanceSurfaceMemo = createMergeMemo();
5077
- var storedInstanceMemo = createMergeMemo();
5078
- var readOnlyMemberMemo = createMergeMemo();
5079
- var staticMemberMemo = createMergeMemo();
5080
5234
  function resolveInheritanceChain(classId, classes, draft) {
5081
5235
  return [...indexClasses(classes).inheritanceChain(classId, draft)];
5082
5236
  }
5237
+ function resolveInheritanceChainFromIndex(classId, classIndex, draft) {
5238
+ return resolveChainFromIndex(classId, classIndex, draft);
5239
+ }
5083
5240
  function resolveChainFromIndex(classId, index, draft) {
5084
5241
  const chain = [];
5085
5242
  const visited = /* @__PURE__ */ new Set();
@@ -5133,50 +5290,70 @@ function mergeSchemas(chain) {
5133
5290
  }
5134
5291
  return merged;
5135
5292
  }
5136
- function mergeInstanceSurfaceSchema(classId, classes, members) {
5137
- return instanceSurfaceFromIndex(classId, indexSchema(classes, members));
5138
- }
5139
- function mergeInstanceSurfaceSchemaFromIndexes(classId, classIndex, memberIndex) {
5140
- return instanceSurfaceFromIndexes(classId, classIndex, memberIndex);
5293
+ var resolvedClassSchemas = /* @__PURE__ */ new WeakMap();
5294
+ function resolvedClassSchemaFromIndexes(classId, classIndex, memberIndex) {
5295
+ let byMembers = resolvedClassSchemas.get(classIndex);
5296
+ if (byMembers === void 0) {
5297
+ byMembers = /* @__PURE__ */ new WeakMap();
5298
+ resolvedClassSchemas.set(classIndex, byMembers);
5299
+ }
5300
+ let byClass = byMembers.get(memberIndex);
5301
+ if (byClass === void 0) {
5302
+ byClass = /* @__PURE__ */ new Map();
5303
+ byMembers.set(memberIndex, byClass);
5304
+ }
5305
+ const cached = byClass.get(classId);
5306
+ if (cached !== void 0) return cached;
5307
+ const chain = resolveChainFromIndex(classId, classIndex);
5308
+ const surface = [];
5309
+ const stored = [];
5310
+ const readOnly = [];
5311
+ const statics = [];
5312
+ const surfaceByKey = /* @__PURE__ */ new Map();
5313
+ const storedByKey = /* @__PURE__ */ new Map();
5314
+ for (const entry of mergeSchemas(chain)) {
5315
+ const member = memberIndex.get(entry.memberId);
5316
+ if (member !== void 0 && isStaticMember(member)) {
5317
+ statics.push({ ...entry, declaringClassId: entry.ownerClassId });
5318
+ continue;
5319
+ }
5320
+ surface.push(entry);
5321
+ surfaceByKey.set(entry.schemaKey, entry);
5322
+ if (member !== void 0 && isReadOnlyMember(member)) readOnly.push(entry);
5323
+ else {
5324
+ stored.push(entry);
5325
+ storedByKey.set(entry.schemaKey, entry);
5326
+ }
5327
+ }
5328
+ const node = {
5329
+ surface,
5330
+ stored,
5331
+ readOnly,
5332
+ statics,
5333
+ surfaceByKey,
5334
+ storedByKey
5335
+ };
5336
+ byClass.set(classId, node);
5337
+ return node;
5141
5338
  }
5142
- function instanceSurfaceFromIndex(classId, index) {
5143
- return instanceSurfaceFromIndexes(
5339
+ function resolvedClassSchema(classId, classes, members) {
5340
+ const index = indexSchema(classes, members);
5341
+ return resolvedClassSchemaFromIndexes(
5144
5342
  classId,
5145
5343
  index.classesById,
5146
5344
  index.membersById
5147
5345
  );
5148
5346
  }
5149
- function instanceSurfaceFromIndexes(classId, classIndex, memberIndex) {
5150
- return instanceSurfaceMemo(classId, classIndex, memberIndex, () => {
5151
- const instanceEntries = [];
5152
- for (const entry of mergeSchemas(
5153
- resolveChainFromIndex(classId, classIndex)
5154
- )) {
5155
- const member = memberIndex.get(entry.memberId);
5156
- if (member === void 0 || !isStaticMember(member)) {
5157
- instanceEntries.push(entry);
5158
- }
5159
- }
5160
- return instanceEntries;
5161
- });
5347
+ function mergeInstanceSurfaceSchema(classId, classes, members) {
5348
+ return [...resolvedClassSchema(classId, classes, members).surface];
5349
+ }
5350
+ function mergeInstanceSurfaceSchemaFromIndexes(classId, classIndex, memberIndex) {
5351
+ return [
5352
+ ...resolvedClassSchemaFromIndexes(classId, classIndex, memberIndex).surface
5353
+ ];
5162
5354
  }
5163
5355
  function mergeStoredInstanceSchema(classId, classes, members) {
5164
- const index = indexSchema(classes, members);
5165
- return storedInstanceMemo(
5166
- classId,
5167
- index.classesById,
5168
- index.membersById,
5169
- () => {
5170
- const storedEntries = [];
5171
- for (const entry of instanceSurfaceFromIndex(classId, index)) {
5172
- const member = index.member(entry.memberId);
5173
- if (member === void 0 || !isReadOnlyMember(member)) {
5174
- storedEntries.push(entry);
5175
- }
5176
- }
5177
- return storedEntries;
5178
- }
5179
- );
5356
+ return [...resolvedClassSchema(classId, classes, members).stored];
5180
5357
  }
5181
5358
  function findSchemaPlacement(memberId, classes) {
5182
5359
  return indexClasses(classes).firstSchemaPlacement(memberId);
@@ -5207,6 +5384,9 @@ function resolveMember(member, members) {
5207
5384
  index.resolvedMembers.set(member, resolved);
5208
5385
  return resolved;
5209
5386
  }
5387
+ function resolveMemberFromIndex(member, memberIndex) {
5388
+ return resolveMemberWithIndex(member, () => memberIndex);
5389
+ }
5210
5390
  function resolveMemberWithIndex(member, memberIndex) {
5211
5391
  const chain = [];
5212
5392
  const visited = /* @__PURE__ */ new Set();
@@ -5291,128 +5471,6 @@ function descendantClassIdsInChildIndex(classId, childrenByClassId) {
5291
5471
  return result;
5292
5472
  }
5293
5473
 
5294
- // node_modules/uuid/dist-node/regex.js
5295
- var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
5296
-
5297
- // node_modules/uuid/dist-node/validate.js
5298
- function validate(uuid) {
5299
- return typeof uuid === "string" && regex_default.test(uuid);
5300
- }
5301
- var validate_default = validate;
5302
-
5303
- // node_modules/uuid/dist-node/parse.js
5304
- function parse(uuid) {
5305
- if (!validate_default(uuid)) {
5306
- throw TypeError("Invalid UUID");
5307
- }
5308
- let v;
5309
- return Uint8Array.of((v = parseInt(uuid.slice(0, 8), 16)) >>> 24, v >>> 16 & 255, v >>> 8 & 255, v & 255, (v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(24, 36), 16)) / 1099511627776 & 255, v / 4294967296 & 255, v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255);
5310
- }
5311
- var parse_default = parse;
5312
-
5313
- // node_modules/uuid/dist-node/stringify.js
5314
- var byteToHex = [];
5315
- for (let i = 0; i < 256; ++i) {
5316
- byteToHex.push((i + 256).toString(16).slice(1));
5317
- }
5318
- function unsafeStringify(arr, offset = 0) {
5319
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
5320
- }
5321
-
5322
- // node_modules/uuid/dist-node/rng.js
5323
- var rnds8 = new Uint8Array(16);
5324
- function rng() {
5325
- return crypto.getRandomValues(rnds8);
5326
- }
5327
-
5328
- // node_modules/uuid/dist-node/v35.js
5329
- function stringToBytes(str) {
5330
- str = unescape(encodeURIComponent(str));
5331
- const bytes = new Uint8Array(str.length);
5332
- for (let i = 0; i < str.length; ++i) {
5333
- bytes[i] = str.charCodeAt(i);
5334
- }
5335
- return bytes;
5336
- }
5337
- var DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
5338
- var URL2 = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
5339
- function v35(version, hash, value, namespace, buf, offset) {
5340
- const valueBytes = typeof value === "string" ? stringToBytes(value) : value;
5341
- const namespaceBytes = typeof namespace === "string" ? parse_default(namespace) : namespace;
5342
- if (typeof namespace === "string") {
5343
- namespace = parse_default(namespace);
5344
- }
5345
- if (namespace?.length !== 16) {
5346
- throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");
5347
- }
5348
- let bytes = new Uint8Array(16 + valueBytes.length);
5349
- bytes.set(namespaceBytes);
5350
- bytes.set(valueBytes, namespaceBytes.length);
5351
- bytes = hash(bytes);
5352
- bytes[6] = bytes[6] & 15 | version;
5353
- bytes[8] = bytes[8] & 63 | 128;
5354
- if (buf) {
5355
- offset ??= 0;
5356
- if (offset < 0 || offset + 16 > buf.length) {
5357
- throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
5358
- }
5359
- for (let i = 0; i < 16; ++i) {
5360
- buf[offset + i] = bytes[i];
5361
- }
5362
- return buf;
5363
- }
5364
- return unsafeStringify(bytes);
5365
- }
5366
-
5367
- // node_modules/uuid/dist-node/v4.js
5368
- function v4(options, buf, offset) {
5369
- if (!buf && !options && crypto.randomUUID) {
5370
- return crypto.randomUUID();
5371
- }
5372
- return _v4(options, buf, offset);
5373
- }
5374
- function _v4(options, buf, offset) {
5375
- options = options || {};
5376
- const rnds = options.random ?? options.rng?.() ?? rng();
5377
- if (rnds.length < 16) {
5378
- throw new Error("Random bytes length must be >= 16");
5379
- }
5380
- rnds[6] = rnds[6] & 15 | 64;
5381
- rnds[8] = rnds[8] & 63 | 128;
5382
- if (buf) {
5383
- offset = offset || 0;
5384
- if (offset < 0 || offset + 16 > buf.length) {
5385
- throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
5386
- }
5387
- for (let i = 0; i < 16; ++i) {
5388
- buf[offset + i] = rnds[i];
5389
- }
5390
- return buf;
5391
- }
5392
- return unsafeStringify(rnds);
5393
- }
5394
- var v4_default = v4;
5395
-
5396
- // node_modules/uuid/dist-node/sha1.js
5397
- import { createHash } from "node:crypto";
5398
- function sha1(bytes) {
5399
- if (Array.isArray(bytes)) {
5400
- bytes = Buffer.from(bytes);
5401
- } else if (typeof bytes === "string") {
5402
- bytes = Buffer.from(bytes, "utf8");
5403
- }
5404
- return createHash("sha1").update(bytes).digest();
5405
- }
5406
- var sha1_default = sha1;
5407
-
5408
- // node_modules/uuid/dist-node/v5.js
5409
- function v5(value, namespace, buf, offset) {
5410
- return v35(80, sha1_default, value, namespace, buf, offset);
5411
- }
5412
- v5.DNS = DNS;
5413
- v5.URL = URL2;
5414
- var v5_default = v5;
5415
-
5416
5474
  // ../src/models/system-record-id.ts
5417
5475
  var SYSTEM_RECORD_ID_PREFIX = "system_";
5418
5476
  function isSystemRecordId(id) {
@@ -7440,8 +7498,9 @@ function clonePlain(value, path, visiting) {
7440
7498
  );
7441
7499
  }
7442
7500
  const clone = {};
7443
- for (const [key, entry] of Object.entries(value)) {
7444
- const child = clonePlain(entry, `${path}.${key}`, visiting);
7501
+ const record4 = value;
7502
+ for (const key of Object.keys(record4)) {
7503
+ const child = clonePlain(record4[key], `${path}.${key}`, visiting);
7445
7504
  if (key === "__proto__") setOwnField(clone, key, child);
7446
7505
  else clone[key] = child;
7447
7506
  }
@@ -7486,15 +7545,27 @@ var WORLD_SYSTEM_SCHEMA_FIELD_SITES_BY_MEMBER_ID = new Map(
7486
7545
  );
7487
7546
 
7488
7547
  // ../src/models/classes/generics.ts
7548
+ var genericBindingsByClassIndex = /* @__PURE__ */ new WeakMap();
7489
7549
  function resolveGenericEnv(classId, classes, draft) {
7490
- const chain = resolveInheritanceChain(classId, classes, draft);
7491
- const env = /* @__PURE__ */ new Map();
7492
- for (let i = 0; i < chain.length; i++) {
7493
- for (const param of chain[i].genericParams ?? []) {
7494
- env.set(param.id, resolveParamAtChainIndex(chain, i, param.id));
7550
+ const index = classIndexFor(classes);
7551
+ let byClass = genericBindingsByClassIndex.get(index);
7552
+ let bindings = draft === void 0 ? byClass?.get(classId) : void 0;
7553
+ if (bindings === void 0) {
7554
+ const chain = resolveInheritanceChainFromIndex(classId, index, draft);
7555
+ const env = /* @__PURE__ */ new Map();
7556
+ for (let i = 0; i < chain.length; i++) {
7557
+ for (const param of chain[i].genericParams ?? []) {
7558
+ env.set(param.id, resolveParamAtChainIndex(chain, i, param.id));
7559
+ }
7560
+ }
7561
+ bindings = [...env];
7562
+ if (draft === void 0) {
7563
+ byClass ??= /* @__PURE__ */ new Map();
7564
+ byClass.set(classId, bindings);
7565
+ genericBindingsByClassIndex.set(index, byClass);
7495
7566
  }
7496
7567
  }
7497
- return env;
7568
+ return new Map(bindings.map(([id, entry]) => [id, { ...entry }]));
7498
7569
  }
7499
7570
  function resolveParamAtChainIndex(chain, declarerIndex, paramId) {
7500
7571
  let cursor = paramId;
@@ -8233,6 +8304,9 @@ function buildUnorderedListMembershipIndex(values) {
8233
8304
  // ../src/models/members/member-value-id.ts
8234
8305
  var NEO_MEMBER_VALUE_NAMESPACE = "7f2b9c14-58d6-5a07-b3e1-4c9d0a6f8b25";
8235
8306
  var NEO_VIRTUAL_VALUE_NAMESPACE = "3e8ca0b3-e3f1-5d5f-bf2f-6ab5ee3896d0";
8307
+ var virtualNamespaceBytes = parse_default(NEO_VIRTUAL_VALUE_NAMESPACE);
8308
+ var virtualIdentityEncoder = new TextEncoder();
8309
+ var SURROGATE_CODE_UNIT = /[\ud800-\udfff]/;
8236
8310
  function derivedMemberValueId(memberId) {
8237
8311
  return inSystemRecordNamespaceOf(
8238
8312
  memberId,
@@ -8240,12 +8314,11 @@ function derivedMemberValueId(memberId) {
8240
8314
  );
8241
8315
  }
8242
8316
  function virtualValueId(instanceRootId, sourceIdentity2) {
8317
+ const identity = `${withoutSystemRecordIdPrefix(instanceRootId)}:${sourceIdentity2}`;
8318
+ const bytes = SURROGATE_CODE_UNIT.test(identity) ? identity : virtualIdentityEncoder.encode(identity);
8243
8319
  return inSystemRecordNamespaceOf(
8244
8320
  instanceRootId,
8245
- v5_default(
8246
- `${withoutSystemRecordIdPrefix(instanceRootId)}:${sourceIdentity2}`,
8247
- NEO_VIRTUAL_VALUE_NAMESPACE
8248
- )
8321
+ v5_default(bytes, virtualNamespaceBytes)
8249
8322
  );
8250
8323
  }
8251
8324
  function virtualSourceIdentityHead(sourceIdentity2) {
@@ -8999,7 +9072,7 @@ function constructionMembers(classId, context) {
8999
9072
  raw,
9000
9073
  env,
9001
9074
  document2.members,
9002
- resolveMember(raw, document2.members)
9075
+ document2.resolvedMember?.(raw) ?? resolveMember(raw, document2.members)
9003
9076
  ),
9004
9077
  id: raw.id
9005
9078
  };
@@ -10231,11 +10304,11 @@ function withIndexedDefaultValueDocument(document2, options = {}) {
10231
10304
  storedInstanceSchema: (classId) => {
10232
10305
  const cached = cache.storedSchemaByClassId.get(classId);
10233
10306
  if (cached !== void 0) return cached;
10234
- const schema = mergeStoredInstanceSchema(
10307
+ const schema = resolvedClassSchema(
10235
10308
  classId,
10236
10309
  document2.classes,
10237
10310
  document2.members
10238
- );
10311
+ ).stored;
10239
10312
  cache.storedSchemaByClassId.set(classId, schema);
10240
10313
  return schema;
10241
10314
  },
@@ -10260,7 +10333,7 @@ function withIndexedDefaultValueDocument(document2, options = {}) {
10260
10333
  },
10261
10334
  memberDefaultSettlesConstruction: (member, environment) => {
10262
10335
  cache.memberDefaultConstructionChecker ??= createMemberDefaultConstructionChecker({
10263
- ...document2,
10336
+ ...indexed,
10264
10337
  constructors: document2.constructors ?? []
10265
10338
  });
10266
10339
  return cache.memberDefaultConstructionChecker(member, environment);
@@ -11031,7 +11104,9 @@ function cloneDefaultValueForMemberCore(args, sourceValue) {
11031
11104
  members: args.document.members,
11032
11105
  constructors: args.document.constructors ?? [],
11033
11106
  values: args.document.values,
11034
- valueById: args.document.valueById
11107
+ valueById: args.document.valueById,
11108
+ memberById: args.document.memberById,
11109
+ resolvedMember: args.document.resolvedMember
11035
11110
  },
11036
11111
  args.genericEnv
11037
11112
  )) {
@@ -11177,9 +11252,9 @@ function formatDefaultReferenceLocation(memberName, key) {
11177
11252
  return `${memberName}[${key}]`;
11178
11253
  }
11179
11254
  function getSchemaEntryMap(document2, classId) {
11180
- return new Map(
11181
- (document2.storedInstanceSchema?.(classId) ?? mergeStoredInstanceSchema(classId, document2.classes, document2.members)).map((entry) => [entry.schemaKey, entry])
11182
- );
11255
+ const node = resolvedClassSchema(classId, document2.classes, document2.members);
11256
+ const entries = document2.storedInstanceSchema?.(classId);
11257
+ return entries === void 0 || entries === node.stored ? node.storedByKey : new Map(entries.map((entry) => [entry.schemaKey, entry]));
11183
11258
  }
11184
11259
  function cloneMemberValueBase(body) {
11185
11260
  return {
@@ -11753,6 +11828,38 @@ var EffectiveStorageResolver = class {
11753
11828
  (id) => this.schemaIndex.member(id)
11754
11829
  );
11755
11830
  resolving = /* @__PURE__ */ new Set();
11831
+ allowedByClassId = /* @__PURE__ */ new Map();
11832
+ userClasses;
11833
+ /**
11834
+ * `resolveAllowedStorage` over this context, memoized along each extends
11835
+ * chain so a whole-document pass stays O(classes).
11836
+ */
11837
+ allowedStorage(classId) {
11838
+ const cached = this.allowedByClassId.get(classId);
11839
+ if (cached !== void 0) return cached;
11840
+ this.allowedByClassId.set(classId, null);
11841
+ const schemaClass2 = this.schemaIndex.classesById.get(classId);
11842
+ let resolved = null;
11843
+ if (schemaClass2?.allowedStorage != null) {
11844
+ resolved = schemaClass2.allowedStorage;
11845
+ } else if (schemaClass2?.extendsClassId !== void 0) {
11846
+ resolved = this.allowedStorage(schemaClass2.extendsClassId);
11847
+ }
11848
+ this.allowedByClassId.set(classId, resolved);
11849
+ return resolved;
11850
+ }
11851
+ /** P104 §1.3: classes whose resolved `allowedStorage` is `User`. */
11852
+ userClassIds() {
11853
+ if (this.userClasses === void 0) {
11854
+ this.userClasses = /* @__PURE__ */ new Set();
11855
+ for (const schemaClass2 of this.ctx.classes) {
11856
+ if (this.allowedStorage(schemaClass2.id) === 5 /* User */) {
11857
+ this.userClasses.add(schemaClass2.id);
11858
+ }
11859
+ }
11860
+ }
11861
+ return this.userClasses;
11862
+ }
11756
11863
  /** Declared storage of `memberId`, resolved through the extends chain. */
11757
11864
  declaredStorage(memberId) {
11758
11865
  return declaredMemberStorageFromIndex(
@@ -11796,7 +11903,7 @@ var EffectiveStorageResolver = class {
11796
11903
  result.add(declared);
11797
11904
  } else if (isStaticMember(this.schemaIndex.member(memberId))) {
11798
11905
  const declaringClassId = this.schemaIndex.firstSchemaPlacement(memberId)?.ownerClass.id;
11799
- const constraint = declaringClassId === void 0 ? null : resolveAllowedStorage(declaringClassId, this.ctx.classes);
11906
+ const constraint = declaringClassId === void 0 ? null : this.allowedStorage(declaringClassId);
11800
11907
  result.add(
11801
11908
  childEffectiveStorage(
11802
11909
  declared,
@@ -11899,6 +12006,11 @@ var EffectiveStorageResolver = class {
11899
12006
  member(memberId) {
11900
12007
  return this.schemaIndex.member(memberId);
11901
12008
  }
12009
+ /** `Owner.Member` for a schema member, else the member's own name. */
12010
+ placementLabel(member) {
12011
+ const owner = this.schemaIndex.firstSchemaPlacement(member.id)?.ownerClass;
12012
+ return owner === void 0 ? member.name : `${owner.name}.${member.name}`;
12013
+ }
11902
12014
  buildParentEdges() {
11903
12015
  const addEdge = (childId, parentId) => {
11904
12016
  const existing = this.parentIdsByMemberId.get(childId);
@@ -12831,44 +12943,6 @@ function visitTypedAggregateRowReferences(value, rawType, visitor) {
12831
12943
  }
12832
12944
  }
12833
12945
 
12834
- // ../src/models/project/project-root-members.ts
12835
- var PROJECT_ROOTS = [
12836
- {
12837
- key: "Assets",
12838
- choice: "assets",
12839
- projectField: "rootAssetsMemberId",
12840
- label: "Assets",
12841
- storage: 1 /* Immutable */
12842
- },
12843
- {
12844
- key: "Save",
12845
- choice: "save",
12846
- projectField: "rootSaveFileMemberId",
12847
- label: "Save",
12848
- storage: 2 /* Save */
12849
- },
12850
- {
12851
- key: "Session",
12852
- choice: "session",
12853
- projectField: "rootSessionMemberId",
12854
- label: "Session",
12855
- storage: 3 /* Session */
12856
- }
12857
- ];
12858
- function buildRootStorageMap(project) {
12859
- const map = /* @__PURE__ */ new Map();
12860
- for (const root of PROJECT_ROOTS) {
12861
- map.set(project[root.projectField], root.storage);
12862
- }
12863
- return map;
12864
- }
12865
- function projectRootMembersInDisplayOrder(project) {
12866
- return PROJECT_ROOTS.map((root) => ({
12867
- root,
12868
- memberId: project[root.projectField]
12869
- }));
12870
- }
12871
-
12872
12946
  // ../src/runtime/neoscript/initializer-dependencies.ts
12873
12947
  var PendingInitializerDependency = class extends NSGetterRuntimeError {
12874
12948
  constructor(valueId) {
@@ -12955,6 +13029,7 @@ function isRecordValue(value) {
12955
13029
  }
12956
13030
  function resolveOwnerMembersForValues(document2, targetValueIds, additionalRoots, rootOwners, rootKinds, traversalExtension) {
12957
13031
  const resolved = /* @__PURE__ */ new Map();
13032
+ let complete = false;
12958
13033
  if (targetValueIds.size === 0) return resolved;
12959
13034
  const valuesById = new Map(document2.values.map((value) => [value.id, value]));
12960
13035
  const membersById = new Map(
@@ -13014,7 +13089,9 @@ function resolveOwnerMembersForValues(document2, targetValueIds, additionalRoots
13014
13089
  resolved.set(valueId, member);
13015
13090
  rootOwners?.set(valueId, rootOwner);
13016
13091
  rootKinds?.set(valueId, rootKind);
13092
+ complete = traversalExtension === void 0 && resolved.size === targetValueIds.size;
13017
13093
  }
13094
+ if (complete) return;
13018
13095
  if (visited.has(valueId)) return;
13019
13096
  visited.add(valueId);
13020
13097
  const value = valuesById.get(valueId);
@@ -13061,6 +13138,7 @@ function resolveOwnerMembersForValues(document2, targetValueIds, additionalRoots
13061
13138
  );
13062
13139
  const env = overlayStamp(instanceEnv, body.genericBindings);
13063
13140
  for (const entry of merged) {
13141
+ if (complete) break;
13064
13142
  if (entry.memberId === null) continue;
13065
13143
  const childValueId = body.value[entry.schemaKey];
13066
13144
  if (childValueId === void 0) continue;
@@ -13080,6 +13158,7 @@ function resolveOwnerMembersForValues(document2, targetValueIds, additionalRoots
13080
13158
  const entryMember = trySubstituteMember(entryMemberRecord, entryEnv);
13081
13159
  if (entryMember === null) return;
13082
13160
  for (const childValueId of Object.values(body.value)) {
13161
+ if (complete) break;
13083
13162
  searchRow(entryMember, childValueId, rootOwner, entryEnv, rootKind);
13084
13163
  }
13085
13164
  return;
@@ -13093,12 +13172,14 @@ function resolveOwnerMembersForValues(document2, targetValueIds, additionalRoots
13093
13172
  if (listKindOf(member) === 1 /* Unordered */) {
13094
13173
  if (body.id === null) return;
13095
13174
  for (const row of rowsByContainerId.get(body.id) ?? []) {
13175
+ if (complete) break;
13096
13176
  searchRow(entryMember, row.id, rootOwner, entryEnv, rootKind);
13097
13177
  }
13098
13178
  return;
13099
13179
  }
13100
13180
  if (!Array.isArray(body.value)) return;
13101
13181
  for (const childValueId of body.value) {
13182
+ if (complete) break;
13102
13183
  if (typeof childValueId !== "string") continue;
13103
13184
  searchRow(entryMember, childValueId, rootOwner, entryEnv, rootKind);
13104
13185
  }
@@ -13116,6 +13197,7 @@ function resolveOwnerMembersForValues(document2, targetValueIds, additionalRoots
13116
13197
  );
13117
13198
  }
13118
13199
  for (const root of additionalRoots ?? []) {
13200
+ if (complete) break;
13119
13201
  searchRootMember(
13120
13202
  root.member,
13121
13203
  root.valueId,
@@ -13124,10 +13206,12 @@ function resolveOwnerMembersForValues(document2, targetValueIds, additionalRoots
13124
13206
  );
13125
13207
  }
13126
13208
  for (const member of document2.members) {
13209
+ if (complete) break;
13127
13210
  if (typeof member.valueId !== "string") continue;
13128
13211
  searchRootMember(member, member.valueId, "instance");
13129
13212
  }
13130
13213
  for (const member of document2.members) {
13214
+ if (complete) break;
13131
13215
  const defaultBody = member.defaultValue;
13132
13216
  if (defaultBody === void 0) continue;
13133
13217
  if (defaultBody === null) continue;
@@ -18751,6 +18835,11 @@ function effectiveStaticStorage(memberId, ctx) {
18751
18835
  `Static member '${memberId}' did not resolve to exactly one effective storage class.`
18752
18836
  );
18753
18837
  }
18838
+ if (storage === 5 /* User */) {
18839
+ throw new NSGetterRuntimeError(
18840
+ `Static member '${memberId}' belongs to a User class. User classes can't declare static stored members.`
18841
+ );
18842
+ }
18754
18843
  return storage;
18755
18844
  }
18756
18845
  function staticBindingTargetId(member, ctx) {
@@ -19503,6 +19592,10 @@ function listenerReceiverOnOwner(memberId, ownerReceiver, ctx) {
19503
19592
  return ownerReceiver;
19504
19593
  }
19505
19594
  function invokeActionListeners(listeners, args, ctx, frame, ownerReceiver, callSiteId) {
19595
+ if (ctx.assertActionInvocable !== void 0) {
19596
+ const ownerRowId = findKnownRowIdByValueReference(ownerReceiver, ctx);
19597
+ if (ownerRowId !== null) ctx.assertActionInvocable(ownerRowId);
19598
+ }
19506
19599
  for (let index = 0; index < listeners.length; index += 1) {
19507
19600
  try {
19508
19601
  invokeDelegateValue(
@@ -21167,17 +21260,9 @@ function classIdForValueRow(row, ctx) {
21167
21260
  function rootMemberForValueRow(row, ctx) {
21168
21261
  if (typeof ctx.rootValue !== "object" || ctx.rootValue === null) return null;
21169
21262
  const rootRecord = ctx.rootValue;
21170
- const project = ctx.vm.project;
21171
- if (rootRecord.Assets === row.value) {
21172
- return evalMemberById(ctx.vm, project.rootAssetsMemberId);
21173
- }
21174
- if (rootRecord.Save === row.value) {
21175
- return evalMemberById(ctx.vm, project.rootSaveFileMemberId);
21176
- }
21177
- if (rootRecord.Session === row.value) {
21178
- return evalMemberById(ctx.vm, project.rootSessionMemberId);
21179
- }
21180
- return null;
21263
+ const root = PROJECT_ROOTS.find((root2) => rootRecord[root2.key] === row.value);
21264
+ if (root === void 0) return null;
21265
+ return evalMemberById(ctx.vm, ctx.vm.project[root.projectField]);
21181
21266
  }
21182
21267
  function memberForCustomSchemaValue(classId, schemaKey, ctx) {
21183
21268
  const memberId = cachedMergedSchemaMemberId(classId, schemaKey, ctx);
@@ -21192,6 +21277,7 @@ function memberIdFromSyntheticDefaultValueId(valueId) {
21192
21277
  }
21193
21278
  function resolveLocalizedTextId(value, ctx) {
21194
21279
  ctx.localizedTextDependencies?.add(value);
21280
+ ctx.vm.localizedTextDependencies?.add(value);
21195
21281
  const mainLocale = ctx.vm.localizationConfig?.mainLocale;
21196
21282
  if (mainLocale === void 0) return value;
21197
21283
  const text = ctx.vm.databaseVM?.localizedTextById?.(value) ?? ctx.vm.localizedTexts?.find((candidate) => candidate.id === value) ?? null;
@@ -22705,11 +22791,12 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
22705
22791
  return cacheDescriptor({ schemaClass: schemaClass2, fields, instanceEnv, classArguments: classArguments2 });
22706
22792
  }
22707
22793
  function assertConstructorFieldSlotWritable(args) {
22708
- const surfaceEntry = mergeInstanceSurfaceSchema(
22794
+ const index = evaluatorSchemaIndex(args.ctx);
22795
+ const surfaceEntry = resolvedClassSchemaFromIndexes(
22709
22796
  args.settledClassId,
22710
- args.ctx.vm.classes,
22711
- args.ctx.vm.members
22712
- ).find((entry) => entry.schemaKey === args.schemaKey);
22797
+ index.classesById,
22798
+ index.membersById
22799
+ ).surfaceByKey.get(args.schemaKey);
22713
22800
  if (surfaceEntry === void 0) return;
22714
22801
  if (isReadOnlyMember(evalMemberById(args.ctx.vm, surfaceEntry.memberId)) !== true) {
22715
22802
  return;
@@ -25824,12 +25911,25 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
25824
25911
  const active = /* @__PURE__ */ new Set();
25825
25912
  const clonedBySourceId = /* @__PURE__ */ new Map();
25826
25913
  ctx.onUnattributableValueRead?.(`class-clone:${sourceId}`);
25827
- const constructorArgumentCandidates = evaluatorValues(ctx);
25914
+ const priorRuntimeRows = [...ctx.__runtimeSessionValues.values()];
25915
+ const priorOverlayRows = [...ctx.__valueOverlay?.values() ?? []];
25916
+ const priorPersistedRows = ctx.__valueOverlay instanceof LazyValueOverlay ? ctx.__valueOverlay.sourceRowsSnapshot() : ctx.vm.values;
25917
+ const priorRemovedIds = new Set(ctx.__removedValueIds);
25828
25918
  let constructorArgumentReferenceCounts = null;
25829
25919
  function constructorArgumentReferenceCount(valueId) {
25830
25920
  if (constructorArgumentReferenceCounts === null) {
25831
25921
  constructorArgumentReferenceCounts = /* @__PURE__ */ new Map();
25832
- for (const candidate of constructorArgumentCandidates) {
25922
+ const shadowedIds = /* @__PURE__ */ new Set();
25923
+ const candidates = [];
25924
+ for (const row of [...priorRuntimeRows, ...priorOverlayRows]) {
25925
+ shadowedIds.add(row.id);
25926
+ if (!priorRemovedIds.has(row.id)) candidates.push(row);
25927
+ }
25928
+ for (const row of priorPersistedRows) {
25929
+ if (!shadowedIds.has(row.id) && !priorRemovedIds.has(row.id))
25930
+ candidates.push(row);
25931
+ }
25932
+ for (const candidate of candidates) {
25833
25933
  for (const argument2 of ownedConstructorArgumentValues(candidate, ctx)) {
25834
25934
  constructorArgumentReferenceCounts.set(
25835
25935
  argument2.id,
@@ -26017,9 +26117,18 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
26017
26117
  ).id;
26018
26118
  });
26019
26119
  ctx.onUnattributableValueRead?.(containerEntriesRead(sourceRow.id));
26020
- for (const child of evaluatorValues(ctx)) {
26021
- if (child.containerId !== sourceRow.id) continue;
26022
- cloneRow2(child, entryMember, id, entryTypeInfo);
26120
+ for (const childId of evaluatorUnorderedListEntryIds(
26121
+ sourceRow.id,
26122
+ ctx
26123
+ )) {
26124
+ if (typeof childId !== "string") continue;
26125
+ const child = evalValueById(
26126
+ ctx,
26127
+ childId,
26128
+ ctx.__runtimeSessionValues,
26129
+ ctx.__valueOverlay
26130
+ );
26131
+ if (child !== null) cloneRow2(child, entryMember, id, entryTypeInfo);
26023
26132
  }
26024
26133
  }
26025
26134
  }
@@ -27332,12 +27441,12 @@ function collectReturnStatements(statements) {
27332
27441
  var SourceText = class {
27333
27442
  text;
27334
27443
  lineStarts;
27444
+ #lastPositionLine = 0;
27335
27445
  constructor(text) {
27336
27446
  this.text = text;
27337
27447
  const starts = [0];
27338
- for (let index = 0; index < text.length; index++) {
27339
- if (text.charCodeAt(index) === 10) starts.push(index + 1);
27340
- }
27448
+ for (let index = text.indexOf("\n"); index !== -1; index = text.indexOf("\n", index + 1))
27449
+ starts.push(index + 1);
27341
27450
  this.lineStarts = starts;
27342
27451
  }
27343
27452
  get lineCount() {
@@ -27345,6 +27454,11 @@ var SourceText = class {
27345
27454
  }
27346
27455
  positionAt(rawOffset) {
27347
27456
  const offset = clamp(rawOffset, 0, this.text.length);
27457
+ const previousLine = this.#lastPositionLine;
27458
+ const previousStart = this.lineStarts[previousLine];
27459
+ const nextStart = this.lineStarts[previousLine + 1];
27460
+ if (offset >= previousStart && (nextStart === void 0 || offset < nextStart))
27461
+ return { line: previousLine, character: offset - previousStart };
27348
27462
  let low = 0;
27349
27463
  let high = this.lineStarts.length;
27350
27464
  while (low < high) {
@@ -27354,6 +27468,7 @@ var SourceText = class {
27354
27468
  else low = middle + 1;
27355
27469
  }
27356
27470
  const line = Math.max(0, low - 1);
27471
+ this.#lastPositionLine = line;
27357
27472
  return {
27358
27473
  line,
27359
27474
  character: offset - (this.lineStarts[line] ?? 0)
@@ -27397,6 +27512,13 @@ var TYPE_SET = /* @__PURE__ */ new Set([
27397
27512
  var OPERATORS = [...NEOSCRIPT_OPERATORS].sort(
27398
27513
  (left, right) => right.length - left.length
27399
27514
  );
27515
+ var OPERATORS_BY_FIRST_CHARACTER = /* @__PURE__ */ new Map();
27516
+ for (const operator of OPERATORS) {
27517
+ const first = operator[0];
27518
+ const candidates = OPERATORS_BY_FIRST_CHARACTER.get(first) ?? [];
27519
+ candidates.push(operator);
27520
+ OPERATORS_BY_FIRST_CHARACTER.set(first, candidates);
27521
+ }
27400
27522
  var PUNCTUATION = /* @__PURE__ */ new Set([
27401
27523
  ";",
27402
27524
  ",",
@@ -27546,7 +27668,7 @@ function lex(sourceValue) {
27546
27668
  emit(makeToken(kind, start, cursor));
27547
27669
  continue;
27548
27670
  }
27549
- const operator = OPERATORS.find(
27671
+ const operator = OPERATORS_BY_FIRST_CHARACTER.get(char)?.find(
27550
27672
  (candidate) => sourceValue.startsWith(candidate, cursor)
27551
27673
  );
27552
27674
  if (operator) {
@@ -29304,7 +29426,7 @@ function asASTBinaryOp(text) {
29304
29426
  }
29305
29427
  function grammarTokens(lexed, start, end) {
29306
29428
  const lexicalError = lexed.diagnostics.find(
29307
- (diagnostic) => diagnostic.severity === "error" && lexed.source.offsetAt(diagnostic.range.start) >= start && lexed.source.offsetAt(diagnostic.range.start) <= end
29429
+ (diagnostic) => diagnostic.severity === "error" && lexed.source.offsetAt(diagnostic.range.start) >= start && lexed.source.offsetAt(diagnostic.range.start) < end
29308
29430
  );
29309
29431
  if (lexicalError) {
29310
29432
  throw new CompileError(lexicalError.message, {
@@ -29312,12 +29434,22 @@ function grammarTokens(lexed, start, end) {
29312
29434
  column: lexicalError.range.start.character + 1
29313
29435
  });
29314
29436
  }
29315
- return [
29316
- ...lexed.roots.filter(
29317
- (token) => token.kind !== "comment" && token.kind !== "eof" && token.start >= start && token.end <= end
29318
- ),
29319
- eofToken(end, lexed.source.positionAt(end))
29320
- ];
29437
+ let low = 0;
29438
+ let high = lexed.roots.length;
29439
+ while (low < high) {
29440
+ const middle = low + high >>> 1;
29441
+ if (lexed.roots[middle].start < start) low = middle + 1;
29442
+ else high = middle;
29443
+ }
29444
+ const tokens = [];
29445
+ for (let index = low; index < lexed.roots.length; index++) {
29446
+ const token = lexed.roots[index];
29447
+ if (token.start > end) break;
29448
+ if (token.kind !== "comment" && token.kind !== "eof" && token.end <= end)
29449
+ tokens.push(token);
29450
+ }
29451
+ tokens.push(eofToken(end, lexed.source.positionAt(end)));
29452
+ return tokens;
29321
29453
  }
29322
29454
  function eofToken(offset, position) {
29323
29455
  return {
@@ -29815,61 +29947,11 @@ function expandStoredInstance(args) {
29815
29947
  `Virtual expansion root "${args.instanceRoot.id}" is missing required constructor arguments.`
29816
29948
  );
29817
29949
  }
29818
- const constructorArguments = requiredConstructor === null ? [] : requiredConstructor.argumentTypes.flatMap((typeInfo, index) => {
29819
- const parameterId = constructorActionParameterId(
29820
- requiredConstructor,
29821
- index
29822
- );
29823
- if (!Object.hasOwn(storedArgs, parameterId)) {
29824
- if (!typeInfo.required) return [];
29825
- throw new VirtualExpansionUnsupportedError(
29826
- `Virtual expansion root "${args.instanceRoot.id}" is missing creation data for constructor parameter "${typeInfo.name}" (${parameterId}).`
29827
- );
29828
- }
29829
- return [
29830
- {
29831
- name: typeInfo.name,
29832
- valuePointer: storedArgumentPointer(
29833
- storedArgs[parameterId],
29834
- typeInfo
29835
- )
29836
- }
29837
- ];
29838
- });
29839
- const constructionPointer = (fields = []) => typeof instanceRoot.instanceVariantId === "string" ? {
29840
- type: "function" /* function */,
29841
- function: {
29842
- type: "variantInitialize" /* variantInitialize */,
29843
- info: {
29844
- variantPointer: {
29845
- type: "variant" /* variant */,
29846
- classId,
29847
- variantId: instanceRoot.instanceVariantId,
29848
- rowValueId: instanceRoot.instanceVariantRowValueId ?? null
29849
- },
29850
- schemaClassInfo: {
29851
- type: 7 /* Class */,
29852
- required: true,
29853
- classId
29854
- }
29855
- }
29856
- }
29857
- } : {
29858
- type: "function" /* function */,
29859
- function: {
29860
- type: "declaredConstructor" /* declaredConstructor */,
29861
- info: {
29862
- schemaClassInfo: {
29863
- type: 7 /* Class */,
29864
- required: true,
29865
- classId
29866
- },
29867
- constructorId: recordedConstructorId,
29868
- args: constructorArguments,
29869
- fields
29870
- }
29871
- }
29872
- };
29950
+ const constructorArguments = storedConstructorReplayArguments(
29951
+ requiredConstructor,
29952
+ storedArgs,
29953
+ instanceRoot.id
29954
+ );
29873
29955
  const {
29874
29956
  value: _value,
29875
29957
  classId: _classId,
@@ -29891,21 +29973,15 @@ function expandStoredInstance(args) {
29891
29973
  );
29892
29974
  const replayMember = closedRootMember === rootMember ? rootMember : { ...closedRootMember, classId };
29893
29975
  const replay = (fields) => {
29894
- const compiled = {
29895
- compilerRevision: NEOSCRIPT_COMPILER_REVISION,
29896
- parameters: evaluatorEnvelopeParameters(),
29897
- instructions: [
29898
- {
29899
- type: "return" /* return */,
29900
- pointer: constructionPointer(fields)
29901
- }
29902
- ],
29903
- typeInfo: { type: 7 /* Class */, required: true, classId }
29904
- };
29905
- const init = {
29906
- code: `virtual-replay:${args.instanceRoot.id}`,
29907
- compiled
29908
- };
29976
+ const init = storedConstructorReplayInitializer({
29977
+ classId,
29978
+ constructorId: recordedConstructorId,
29979
+ arguments: constructorArguments,
29980
+ fields,
29981
+ variantId: instanceRoot.instanceVariantId,
29982
+ variantRowValueId: instanceRoot.instanceVariantRowValueId,
29983
+ code: `virtual-replay:${args.instanceRoot.id}`
29984
+ });
29909
29985
  return trackMaterialization(
29910
29986
  () => materializeInitializerValue({
29911
29987
  evaluateInitializer: args.evaluateInitializer,
@@ -30073,11 +30149,11 @@ function resolveVirtualInstanceGraph(args) {
30073
30149
  const classId = effective.classId ?? indexed.member.classId;
30074
30150
  const constructedChildren = materialized === null ? /* @__PURE__ */ new Map() : settledAggregateChildren(materialized, classId, pathKey);
30075
30151
  const effectiveRecord = {};
30076
- const schema = mergeStoredInstanceSchema(
30152
+ const schema = resolvedClassSchema(
30077
30153
  classId,
30078
30154
  args.document.classes,
30079
30155
  args.document.members
30080
- );
30156
+ ).stored;
30081
30157
  for (const entry of schema) {
30082
30158
  const childPath = appendVirtualValuePath(pathKey, {
30083
30159
  kind: "class",
@@ -30512,10 +30588,10 @@ function resolveVirtualInstanceGraph(args) {
30512
30588
  };
30513
30589
  }
30514
30590
  function mergeExpandedAndMaterializedRow(expanded, materialized) {
30515
- const expandedClone = cloneRow(expanded);
30516
- if (materialized === null) return expandedClone;
30517
- const materializedClone = cloneRow(materialized);
30518
- const merged = isLiteralValueContent(materialized) ? overlayLiteralValueContent(expandedClone, materializedClone) : { ...expandedClone, ...materializedClone };
30591
+ if (materialized === null) return cloneRow(expanded);
30592
+ const merged = cloneRow(
30593
+ isLiteralValueContent(materialized) ? overlayLiteralValueContent(expanded, materialized) : { ...expanded, ...materialized }
30594
+ );
30519
30595
  if (merged.sourceValueId === materialized.id) delete merged.sourceValueId;
30520
30596
  return merged;
30521
30597
  }
@@ -30824,11 +30900,11 @@ function indexExpansion(args) {
30824
30900
  instanceEnv.set(paramId, { kind: "member", memberId });
30825
30901
  }
30826
30902
  }
30827
- const schema = mergeStoredInstanceSchema(
30903
+ const schema = resolvedClassSchema(
30828
30904
  classId,
30829
30905
  args.document.classes,
30830
30906
  args.document.members
30831
- );
30907
+ ).stored;
30832
30908
  for (const entry of schema) {
30833
30909
  const childId = record4[entry.schemaKey];
30834
30910
  const childMember = membersById.get(entry.memberId);
@@ -31146,6 +31222,69 @@ function canonicalJson(value) {
31146
31222
  }
31147
31223
  return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${canonicalJson(entry)}`).join(",")}}`;
31148
31224
  }
31225
+ function storedConstructorReplayArguments(constructor, storedArgs, rootId) {
31226
+ return constructor === null ? [] : constructor.argumentTypes.flatMap((typeInfo, index) => {
31227
+ const parameterId = constructorActionParameterId(constructor, index);
31228
+ if (!Object.hasOwn(storedArgs, parameterId)) {
31229
+ if (!typeInfo.required) return [];
31230
+ throw new VirtualExpansionUnsupportedError(
31231
+ `Virtual expansion root "${rootId}" is missing creation data for constructor parameter "${typeInfo.name}" (${parameterId}).`
31232
+ );
31233
+ }
31234
+ return [
31235
+ {
31236
+ name: typeInfo.name,
31237
+ valuePointer: storedArgumentPointer(
31238
+ storedArgs[parameterId],
31239
+ typeInfo
31240
+ )
31241
+ }
31242
+ ];
31243
+ });
31244
+ }
31245
+ function storedConstructorReplayInitializer(args) {
31246
+ const schemaClassInfo = {
31247
+ type: 7 /* Class */,
31248
+ required: true,
31249
+ classId: args.classId,
31250
+ ...args.typeArguments === void 0 ? {} : { typeArguments: args.typeArguments }
31251
+ };
31252
+ const pointer = typeof args.variantId === "string" ? {
31253
+ type: "function" /* function */,
31254
+ function: {
31255
+ type: "variantInitialize" /* variantInitialize */,
31256
+ info: {
31257
+ variantPointer: {
31258
+ type: "variant" /* variant */,
31259
+ classId: args.classId,
31260
+ variantId: args.variantId,
31261
+ rowValueId: args.variantRowValueId ?? null
31262
+ },
31263
+ schemaClassInfo
31264
+ }
31265
+ }
31266
+ } : {
31267
+ type: "function" /* function */,
31268
+ function: {
31269
+ type: "declaredConstructor" /* declaredConstructor */,
31270
+ info: {
31271
+ schemaClassInfo,
31272
+ constructorId: args.constructorId,
31273
+ args: args.arguments,
31274
+ fields: args.fields ?? []
31275
+ }
31276
+ }
31277
+ };
31278
+ return {
31279
+ code: args.code,
31280
+ compiled: {
31281
+ compilerRevision: NEOSCRIPT_COMPILER_REVISION,
31282
+ parameters: evaluatorEnvelopeParameters(),
31283
+ instructions: [{ type: "return" /* return */, pointer }],
31284
+ typeInfo: schemaClassInfo
31285
+ }
31286
+ };
31287
+ }
31149
31288
  function storedArgumentPointer(value, typeInfo) {
31150
31289
  if ((typeInfo.type === 7 /* Class */ || typeInfo.type === 22 /* Interface */ || typeInfo.type === 6 /* List */ || typeInfo.type === 5 /* Dictionary */) && typeof value === "string") {
31151
31290
  return { type: "reference" /* reference */, valueId: value };
@@ -31520,6 +31659,11 @@ function createHeadlessVirtualInstanceResolver(args) {
31520
31659
  return knownGraph === void 0 ? emptyRows : expandRoot(knownGraph.instanceRootId, void 0);
31521
31660
  };
31522
31661
  return {
31662
+ storedClassGraph: (rootId, member) => {
31663
+ expandRoot(rootId, member);
31664
+ const graph = graphByValueId.get(rootId);
31665
+ return graph?.instanceRootId === rootId ? graph : null;
31666
+ },
31523
31667
  virtualInstanceRowsForValue,
31524
31668
  valueById: (id) => expandedRowById.get(id) ?? null,
31525
31669
  rowForValueReference: (value) => expandedRowByRecord.get(value) ?? null,
@@ -31866,6 +32010,7 @@ function evaluateMemberInitializer(args) {
31866
32010
  interfaces: args.document.interfaces,
31867
32011
  localizedTexts: args.document.localizedTexts,
31868
32012
  localizationConfig: args.document.localizationConfig,
32013
+ localizedTextDependencies: args.document.localizedTextDependencies,
31869
32014
  // P67 §4: `Variants.X.Initialize()` and the P75 variant-construction
31870
32015
  // replay both resolve the graph through `ctx.vm.variants`; omitting
31871
32016
  // these made every variant-constructed instance refuse with
@@ -32051,6 +32196,70 @@ function headlessVirtualInstanceLookups(document2, options = {}) {
32051
32196
  return lookups;
32052
32197
  }
32053
32198
 
32199
+ // ../src/common/immutable-json.ts
32200
+ var immutable = /* @__PURE__ */ new WeakSet();
32201
+ function isFrozenJsonData(value) {
32202
+ return immutable.has(value);
32203
+ }
32204
+ function memoizeFrozenJsonGuard(isValid) {
32205
+ const accepted = /* @__PURE__ */ new WeakSet();
32206
+ return (value) => {
32207
+ if (value === null || typeof value !== "object" || !isFrozenJsonData(value))
32208
+ return isValid(value);
32209
+ if (accepted.has(value)) return true;
32210
+ if (!isValid(value)) return false;
32211
+ accepted.add(value);
32212
+ return true;
32213
+ };
32214
+ }
32215
+
32216
+ // ../packages/manifest/src/value-comparison.ts
32217
+ function isObjectRecord(value) {
32218
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32219
+ }
32220
+
32221
+ // ../src/database/canonical-json.ts
32222
+ function canonicalJsonStringify(value) {
32223
+ return JSON.stringify(toCanonicalJsonValue(value));
32224
+ }
32225
+ function toCanonicalJsonValue(value) {
32226
+ if (value === null) return null;
32227
+ if (value === void 0) return void 0;
32228
+ if (value instanceof Date) return value.toISOString();
32229
+ if (typeof value === "string") return value;
32230
+ if (typeof value === "boolean") return value;
32231
+ if (typeof value === "number") {
32232
+ if (!Number.isFinite(value)) {
32233
+ throw new Error("Cannot canonicalize a non-finite number.");
32234
+ }
32235
+ return value;
32236
+ }
32237
+ if (typeof value === "bigint") {
32238
+ throw new Error("Cannot canonicalize bigint values.");
32239
+ }
32240
+ if (typeof value === "symbol") {
32241
+ throw new Error("Cannot canonicalize symbol values.");
32242
+ }
32243
+ if (typeof value === "function") {
32244
+ throw new Error("Cannot canonicalize function values.");
32245
+ }
32246
+ if (Array.isArray(value)) {
32247
+ return value.map((item) => {
32248
+ const canonicalItem = toCanonicalJsonValue(item);
32249
+ if (canonicalItem === void 0) return null;
32250
+ return canonicalItem;
32251
+ });
32252
+ }
32253
+ const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
32254
+ const canonicalObject = {};
32255
+ for (const [key, entryValue] of entries) {
32256
+ const canonicalValue = toCanonicalJsonValue(entryValue);
32257
+ if (canonicalValue === void 0) continue;
32258
+ canonicalObject[key] = canonicalValue;
32259
+ }
32260
+ return canonicalObject;
32261
+ }
32262
+
32054
32263
  // ../packages/neoscript-language/src/syntax-index.ts
32055
32264
  var OPEN_TO_CLOSE = /* @__PURE__ */ new Map([
32056
32265
  ["(", ")"],
@@ -33328,6 +33537,136 @@ function isCollectionQueryName(name) {
33328
33537
  return Object.hasOwn(COLLECTION_QUERY_METHODS, name);
33329
33538
  }
33330
33539
 
33540
+ // ../packages/neoscript-language/src/project-source-lifecycle-hooks.ts
33541
+ var UNITY_LIFECYCLE_INTERFACE_PREFIX = "INeoUnity";
33542
+ function isUnityLifecycleInterfaceName(name) {
33543
+ return name.startsWith(UNITY_LIFECYCLE_INTERFACE_PREFIX);
33544
+ }
33545
+
33546
+ // ../packages/neoscript-language/src/user-safe-types.ts
33547
+ var USER_DATA_WRITE_ERROR = "Only User code can change User data. C# changes it through the generated user client.";
33548
+ function userUnsafeTypeName(type, project) {
33549
+ return userSafeTypeCheck(project).unsafeName(type);
33550
+ }
33551
+ var checks = /* @__PURE__ */ new WeakMap();
33552
+ function userSafeTypeCheck(project) {
33553
+ let check2 = checks.get(project);
33554
+ if (check2 === void 0) {
33555
+ check2 = new UserSafeTypeCheck(project);
33556
+ checks.set(project, check2);
33557
+ }
33558
+ return check2;
33559
+ }
33560
+ function userUnsafeTypeMessage(typeName, site) {
33561
+ return `User code can't use \`${typeName}\` in ${site}, because it isn't a User class.`;
33562
+ }
33563
+ var UserSafeTypeCheck = class {
33564
+ constructor(project) {
33565
+ this.project = project;
33566
+ }
33567
+ project;
33568
+ /** Final interface verdicts. */
33569
+ interfaces = /* @__PURE__ */ new Map();
33570
+ /**
33571
+ * Interfaces whose verdict waits on their cycle (Tarjan's SCC stack),
33572
+ * by stack position. One on the stack reads as safe until its cycle ends.
33573
+ */
33574
+ pending = /* @__PURE__ */ new Map();
33575
+ stack = [];
33576
+ /** The lowest stack position the current interface's check consulted. */
33577
+ lowestConsulted = Infinity;
33578
+ symbolUnsafeName(symbol) {
33579
+ for (const parameter3 of symbol.parameters ?? []) {
33580
+ const name = this.unsafeName(parameter3.type);
33581
+ if (name !== null) return name;
33582
+ }
33583
+ if (symbol.returnType !== void 0) {
33584
+ const name = this.unsafeName(symbol.returnType);
33585
+ if (name !== null) return name;
33586
+ }
33587
+ return this.unsafeName(symbol.type);
33588
+ }
33589
+ unsafeName(type) {
33590
+ switch (type.kind) {
33591
+ case "primitive":
33592
+ return null;
33593
+ case "typeParameter":
33594
+ return type.constraint === void 0 ? null : this.unsafeName(type.constraint);
33595
+ case "list":
33596
+ case "set":
33597
+ return this.unsafeName(type.elementType);
33598
+ case "dictionary":
33599
+ return this.unsafeName(type.keyType) ?? this.unsafeName(type.valueType);
33600
+ case "delegate":
33601
+ return this.firstUnsafe(type.parameterTypes) ?? this.unsafeName(type.returnType);
33602
+ case "action":
33603
+ return this.firstUnsafe(type.parameterTypes);
33604
+ case "named":
33605
+ return this.namedUnsafeName(type.typeId) ?? this.firstUnsafe(type.typeArguments ?? []);
33606
+ }
33607
+ }
33608
+ firstUnsafe(types) {
33609
+ for (const type of types) {
33610
+ const name = this.unsafeName(type);
33611
+ if (name !== null) return name;
33612
+ }
33613
+ return null;
33614
+ }
33615
+ namedUnsafeName(typeId) {
33616
+ const named = this.project.typeById.get(typeId);
33617
+ if (named === void 0) return null;
33618
+ switch (named.kind) {
33619
+ case "enum":
33620
+ case "builtin":
33621
+ return null;
33622
+ case "class":
33623
+ return named.userClass === true ? null : named.name;
33624
+ case "synthetic":
33625
+ return named.name;
33626
+ case "interface":
33627
+ return this.interfaceUnsafeName(named);
33628
+ }
33629
+ }
33630
+ // An interface is unsafe when it reaches an unsafe type, so a cycle alone
33631
+ // proves nothing. Interfaces in one cycle reach each other and share a
33632
+ // verdict, settled once the cycle's first interface finishes; each
33633
+ // interface is scanned once.
33634
+ interfaceUnsafeName(named) {
33635
+ if (isUnityLifecycleInterfaceName(named.name)) return named.name;
33636
+ const cached = this.interfaces.get(named.id);
33637
+ if (cached !== void 0) return cached;
33638
+ const pendingAt = this.pending.get(named.id);
33639
+ if (pendingAt !== void 0) {
33640
+ this.lowestConsulted = Math.min(this.lowestConsulted, pendingAt);
33641
+ return null;
33642
+ }
33643
+ const position = this.stack.length;
33644
+ this.stack.push(named);
33645
+ this.pending.set(named.id, position);
33646
+ const outerLowest = this.lowestConsulted;
33647
+ this.lowestConsulted = Infinity;
33648
+ let unsafe = false;
33649
+ for (const member of named.members) {
33650
+ if (this.symbolUnsafeName(member) === null) continue;
33651
+ unsafe = true;
33652
+ break;
33653
+ }
33654
+ if (unsafe || this.lowestConsulted >= position) {
33655
+ this.settleFrom(position, unsafe);
33656
+ this.lowestConsulted = outerLowest;
33657
+ } else {
33658
+ this.lowestConsulted = Math.min(outerLowest, this.lowestConsulted);
33659
+ }
33660
+ return unsafe ? named.name : null;
33661
+ }
33662
+ settleFrom(position, unsafe) {
33663
+ for (const settled of this.stack.splice(position)) {
33664
+ this.pending.delete(settled.id);
33665
+ this.interfaces.set(settled.id, unsafe ? settled.name : null);
33666
+ }
33667
+ }
33668
+ };
33669
+
33331
33670
  // ../packages/neoscript-language/src/tile-conversion.ts
33332
33671
  var NEO_TILE_CONVERT_MEMBER_ID = "system_54ecc5a7-874d-54ed-92f4-38100a4b7465";
33333
33672
  var NEO_TILE_CLASS_ID = "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0";
@@ -33503,6 +33842,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
33503
33842
  };
33504
33843
  this.debugPosition = sourcePositionMapper(options.source);
33505
33844
  this.project = projectIndex ?? createProjectIndex(context.project);
33845
+ const lexicalClass = context.declaringType === void 0 ? context.thisClass : context.declaringType;
33846
+ this.userClassCode = lexicalClass?.kind === "named" && this.project.typeById.get(lexicalClass.typeId)?.userClass === true;
33847
+ this.writesUserData = this.userClassCode || context.projectSourceKind === "spec";
33506
33848
  this.listenerParameters = createListenerAnnotationProvider(
33507
33849
  this.project,
33508
33850
  context
@@ -33519,6 +33861,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
33519
33861
  const rootSymbol = context.project.roots.find(
33520
33862
  (candidate) => candidate.name === "root"
33521
33863
  );
33864
+ this.rootTypeId = rootSymbol?.type.kind === "named" ? rootSymbol.type.typeId : null;
33522
33865
  this.rootVariable = variable(
33523
33866
  "__root__",
33524
33867
  rootSymbol?.type ?? unknown,
@@ -33574,6 +33917,11 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
33574
33917
  functionControlBoundaries = [];
33575
33918
  debugSource;
33576
33919
  inferredExpressionReturnType;
33920
+ /** P104 §3.1. User class bodies reach only `root.User`. */
33921
+ userClassCode;
33922
+ rootTypeId;
33923
+ /** P104 §3.1. User class and test bodies may write User data. */
33924
+ writesUserData;
33577
33925
  initialScope() {
33578
33926
  const scope = new Scope(null, this.options.onFlowScope !== void 0);
33579
33927
  scope.define(
@@ -35103,6 +35451,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
35103
35451
  statement.pos
35104
35452
  );
35105
35453
  }
35454
+ if (writability === "readOnly" /* ReadOnly */ && target.userData) {
35455
+ throw new CompileError(USER_DATA_WRITE_ERROR, statement.pos);
35456
+ }
35106
35457
  if (writability === "readOnly" /* ReadOnly */) {
35107
35458
  throw new CompileError(
35108
35459
  `Cannot assign to a read-only ${this.describe(target.type)} value.`,
@@ -35296,7 +35647,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
35296
35647
  statement.pos
35297
35648
  );
35298
35649
  }
35299
- const writability = observed.writability;
35650
+ const writability = observed.userData ? "runtime" /* Runtime */ : observed.writability;
35300
35651
  if (writability !== "save" /* Save */ && writability !== "session" /* Session */ && writability !== "runtime" /* Runtime */ && writability !== "local" /* Local */) {
35301
35652
  throw new CompileError(
35302
35653
  "OnChanged requires a member whose storage is writable at gameplay runtime.",
@@ -35906,6 +36257,16 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
35906
36257
  expression.pos
35907
36258
  );
35908
36259
  const declaredTarget = this.project.typeByName.get(className);
36260
+ if (declaredTarget !== void 0) {
36261
+ this.assertUserSafe(
36262
+ { kind: "named", typeId: declaredTarget.id },
36263
+ "a `new` expression",
36264
+ expression.pos
36265
+ );
36266
+ }
36267
+ if (declaredTarget?.userClass === true && !this.writesUserData && this.context.storedConstructionReplay !== true) {
36268
+ throw new CompileError(USER_DATA_WRITE_ERROR, expression.pos);
36269
+ }
35909
36270
  if (declaredTarget?.kind === "class" && (expression.initializer?.length ?? 0) > 0 && this.context.storedConstructionReplay !== true) {
35910
36271
  return this.resolveExecutableObjectInitializer(
35911
36272
  declaredTarget,
@@ -36899,7 +37260,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
36899
37260
  /**
36900
37261
  * P67 §4.1/§4.2 — `<variant>.Initialize()` and `<source>.ToVariant(<variant>)`.
36901
37262
  *
36902
- * Checked before {@link resolveDelegateCallee} deliberately. The variant
37263
+ * Checked before {@link resolveCallableValueCallee} deliberately. The variant
36903
37264
  * graph really does carry an `Initialize` member of delegate type, so the
36904
37265
  * ordinary delegate path would resolve `.Initialize()` and run step 1 of the
36905
37266
  * construction path while silently skipping Overrides and ChildOverrides.
@@ -37094,7 +37455,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37094
37455
  type: member.type,
37095
37456
  symbol: member,
37096
37457
  ...member.writable ? {
37097
- writability: member.writability ? toWritability(member.writability) : "setter" /* Setter */
37458
+ writability: member.writability ? toWritability(member.writability, this.writesUserData) : "setter" /* Setter */
37098
37459
  } : {}
37099
37460
  };
37100
37461
  }
@@ -37105,7 +37466,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37105
37466
  },
37106
37467
  type: member.type,
37107
37468
  symbol: member,
37108
- ...member.writability ? { writability: toWritability(member.writability) } : {}
37469
+ ...member.writability ? {
37470
+ writability: toWritability(member.writability, this.writesUserData)
37471
+ } : {}
37109
37472
  };
37110
37473
  }
37111
37474
  resolveMemberNatural(receiverAst, name, scope, pos, optional2, receiverValue) {
@@ -37175,6 +37538,11 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37175
37538
  }
37176
37539
  const staticType = this.project.typeByName.get(receiverAst.name);
37177
37540
  if (staticType && staticType.kind !== "enum") {
37541
+ this.assertUserSafe(
37542
+ { kind: "named", typeId: staticType.id },
37543
+ "a static receiver",
37544
+ pos
37545
+ );
37178
37546
  if (optional2) {
37179
37547
  throw new CompileError(
37180
37548
  `Optional chaining is not valid on type receiver '${staticType.name}'.`,
@@ -37353,6 +37721,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37353
37721
  );
37354
37722
  }
37355
37723
  this.assertMemberAccessible(type, member, pos);
37724
+ if (this.userClassCode && type.id === this.rootTypeId && member.writability !== "user") {
37725
+ throw new CompileError("User code can only read `root.User`.", pos);
37726
+ }
37356
37727
  if (member.static === true) {
37357
37728
  throw new CompileError(
37358
37729
  `Static member '${type.name}.${name}' must be accessed through the type name, not an instance.`,
@@ -37382,12 +37753,14 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37382
37753
  ...nullPropagating ? { optionalChainType: memberType2 } : {},
37383
37754
  symbol: member,
37384
37755
  ...member.writable ? {
37385
- writability: member.writability ? toWritability(member.writability) : "setter" /* Setter */
37756
+ writability: member.writability ? toWritability(member.writability, this.writesUserData) : "setter" /* Setter */
37386
37757
  } : {}
37387
37758
  };
37388
37759
  }
37389
37760
  const writability = this.memberWritability(member, receiver);
37390
37761
  const entryWritability = member.lookup ? this.lookupEntryWritability(member, receiver) : void 0;
37762
+ const userData = this.memberUserData(member, receiver);
37763
+ const entryUserData = member.lookup ? this.lookupEntryUserData(member) : false;
37391
37764
  const lookupWire = member.lookup?.multiselect === true && memberType2.kind === "set" ? {
37392
37765
  type: 9 /* Lookup */,
37393
37766
  required: !isNullable(memberType2),
@@ -37409,7 +37782,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37409
37782
  symbol: member,
37410
37783
  ...writability ? { writability } : {},
37411
37784
  ...lookupWire ? { wireType: lookupWire } : {},
37412
- ...entryWritability ? { entryWritability } : {}
37785
+ ...entryWritability ? { entryWritability } : {},
37786
+ userData,
37787
+ entryUserData
37413
37788
  };
37414
37789
  }
37415
37790
  throw new CompileError(
@@ -37495,20 +37870,33 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37495
37870
  }
37496
37871
  memberWritability(member, receiver) {
37497
37872
  if (member.writability && !member.lookup) {
37498
- return toWritability(member.writability);
37873
+ return toWritability(member.writability, this.writesUserData);
37499
37874
  }
37500
37875
  if (!member.writable) return void 0;
37501
37876
  if (!member.lookup) {
37502
- return member.writability ? toWritability(member.writability) : receiver.entryWritability ?? receiver.writability ?? "save" /* Save */;
37877
+ return member.writability ? toWritability(member.writability, this.writesUserData) : receiver.entryWritability ?? receiver.writability ?? "save" /* Save */;
37878
+ }
37879
+ return member.writability ? toWritability(member.writability, this.writesUserData) : receiver.writability ?? "save" /* Save */;
37880
+ }
37881
+ /** Mirrors {@link memberWritability}'s inheritance for P104 User data. */
37882
+ memberUserData(member, receiver) {
37883
+ if (member.writability) return member.writability === "user";
37884
+ if (member.lookup || receiver.entryWritability === void 0) {
37885
+ return receiver.userData === true;
37503
37886
  }
37504
- return member.writability ? toWritability(member.writability) : receiver.writability ?? "save" /* Save */;
37887
+ return receiver.entryUserData === true;
37888
+ }
37889
+ lookupEntryUserData(member) {
37890
+ if (!member.lookup) return false;
37891
+ const collectionWritability = member.lookup.collectionWritability ?? this.project.symbolById.get(member.lookup.collectionMemberId)?.writability;
37892
+ return collectionWritability === "user";
37505
37893
  }
37506
37894
  lookupEntryWritability(member, receiver) {
37507
37895
  if (!member.lookup) return "readOnly" /* ReadOnly */;
37508
37896
  const target = this.project.symbolById.get(
37509
37897
  member.lookup.collectionMemberId
37510
37898
  );
37511
- const targetWritability = member.lookup.collectionWritability ? toWritability(member.lookup.collectionWritability) : target?.writability ? toWritability(target.writability) : target?.writable ? "runtime" /* Runtime */ : "readOnly" /* ReadOnly */;
37899
+ const targetWritability = member.lookup.collectionWritability ? toWritability(member.lookup.collectionWritability, this.writesUserData) : target?.writability ? toWritability(target.writability, this.writesUserData) : target?.writable ? "runtime" /* Runtime */ : "readOnly" /* ReadOnly */;
37512
37900
  if (receiver.writability === "immutable" /* Immutable */) {
37513
37901
  if (targetWritability === "save" /* Save */) {
37514
37902
  return "immutableToSaveLookup" /* ImmutableToSaveLookup */;
@@ -37529,7 +37917,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37529
37917
  },
37530
37918
  type: optional2 ? { ...type, nullable: true } : type,
37531
37919
  ...optional2 ? { optionalChainType: type } : {},
37532
- ...receiver.writability ? { writability: receiver.writability } : {}
37920
+ ...receiver.writability ? { writability: receiver.writability } : {},
37921
+ ...receiver.userData ? { userData: true } : {}
37533
37922
  };
37534
37923
  }
37535
37924
  resolveIndex(receiverAst, indexAst, scope, pos, optional2) {
@@ -37590,7 +37979,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37590
37979
  },
37591
37980
  type: nullPropagating ? { ...receiver.type.elementType, nullable: true } : receiver.type.elementType,
37592
37981
  ...nullPropagating ? { optionalChainType: receiver.type.elementType } : {},
37593
- ...receiver.writability ? { writability: receiver.writability } : {}
37982
+ ...receiver.writability ? { writability: receiver.writability } : {},
37983
+ ...receiver.userData ? { userData: true } : {}
37594
37984
  };
37595
37985
  }
37596
37986
  keyType = { kind: "primitive", name: "int" };
@@ -37624,7 +38014,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37624
38014
  },
37625
38015
  type: nullPropagating ? { ...valueType, nullable: true } : valueType,
37626
38016
  ...nullPropagating ? { optionalChainType: valueType } : {},
37627
- ...receiver.writability ? { writability: receiver.writability } : {}
38017
+ ...receiver.writability ? { writability: receiver.writability } : {},
38018
+ ...receiver.userData ? { userData: true } : {}
37628
38019
  };
37629
38020
  }
37630
38021
  resolveDictionaryKey(expectedKey, keyAst, scope, pos, requireNonOptional, dictionaryLiteral = false) {
@@ -37922,20 +38313,23 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37922
38313
  receiverValue
37923
38314
  );
37924
38315
  if (variantCall !== null) return variantCall;
37925
- const delegate = this.resolveDelegateCallee(callee, scope, receiverValue);
37926
- if (delegate !== null) {
38316
+ const callable2 = this.resolveCallableValueCallee(
38317
+ callee,
38318
+ scope,
38319
+ receiverValue
38320
+ );
38321
+ if (callable2?.type.kind === "delegate") {
37927
38322
  return this.resolveDelegateCall(
37928
- delegate,
38323
+ callable2,
37929
38324
  argumentsList2,
37930
38325
  scope,
37931
38326
  pos,
37932
38327
  callee.kind === "member" && callee.optional === true
37933
38328
  );
37934
38329
  }
37935
- const action = this.resolveActionCallee(callee, scope, receiverValue);
37936
- if (action !== null) {
38330
+ if (callable2?.type.kind === "action") {
37937
38331
  throw new CompileError(
37938
- `${this.describe(action.type)} is void and cannot be used as a value; call it as a statement instead.`,
38332
+ `${this.describe(callable2.type)} is void and cannot be used as a value; call it as a statement instead.`,
37939
38333
  pos
37940
38334
  );
37941
38335
  }
@@ -38028,6 +38422,11 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38028
38422
  }
38029
38423
  const staticType = this.project.typeByName.get(callee.receiver.name);
38030
38424
  if (staticType && staticType.kind !== "enum") {
38425
+ this.assertUserSafe(
38426
+ { kind: "named", typeId: staticType.id },
38427
+ "a static receiver",
38428
+ pos
38429
+ );
38031
38430
  if (callee.optional) {
38032
38431
  throw new CompileError(
38033
38432
  `Optional chaining is not valid on type receiver '${staticType.name}'.`,
@@ -38207,39 +38606,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38207
38606
  }
38208
38607
  };
38209
38608
  }
38210
- resolveDelegateCallee(callee, scope, receiverValue) {
38211
- if (callee.kind === "ident") {
38212
- const scoped = scope.lookup(callee.name);
38213
- const implicit = this.implicitMember(callee.name);
38214
- if (scoped === null && (implicit === null || implicit.symbol.kind === "function" || implicit.symbol.kind === "method")) {
38215
- return null;
38216
- }
38217
- const resolved = this.resolveIdentifier(callee.name, scope, callee.pos);
38218
- return resolved.type.kind === "delegate" ? resolved : null;
38219
- }
38220
- if (callee.kind !== "member") return null;
38221
- try {
38222
- const resolved = this.resolveMember(
38223
- callee.receiver,
38224
- callee.name,
38225
- scope,
38226
- callee.pos,
38227
- callee.optional === true,
38228
- receiverValue
38229
- );
38230
- return resolved.type.kind === "delegate" ? resolved : null;
38231
- } catch (error) {
38232
- if (error instanceof CompileError) return null;
38233
- throw error;
38234
- }
38235
- }
38236
- /**
38237
- * The action-typed sibling of {@link resolveDelegateCallee}. Kept separate
38238
- * so an action never leaks into the delegate call path: an action is
38239
- * statement-only, and its two call sites want opposite outcomes — the
38240
- * statement path compiles it, the expression path rejects it.
38241
- */
38242
- resolveActionCallee(callee, scope, receiverValue) {
38609
+ /** Classify callable values once before falling back to ordinary methods. */
38610
+ resolveCallableValueCallee(callee, scope, receiverValue) {
38243
38611
  if (callee.kind === "ident") {
38244
38612
  const scoped = scope.lookup(callee.name);
38245
38613
  const implicit = this.implicitMember(callee.name);
@@ -38247,7 +38615,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38247
38615
  return null;
38248
38616
  }
38249
38617
  const resolved = this.resolveIdentifier(callee.name, scope, callee.pos);
38250
- return resolved.type.kind === "action" ? resolved : null;
38618
+ return resolved.type.kind === "delegate" || resolved.type.kind === "action" ? resolved : null;
38251
38619
  }
38252
38620
  if (callee.kind !== "member") return null;
38253
38621
  try {
@@ -38259,7 +38627,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38259
38627
  callee.optional === true,
38260
38628
  receiverValue
38261
38629
  );
38262
- return resolved.type.kind === "action" ? resolved : null;
38630
+ return resolved.type.kind === "delegate" || resolved.type.kind === "action" ? resolved : null;
38263
38631
  } catch (error) {
38264
38632
  if (error instanceof CompileError) return null;
38265
38633
  throw error;
@@ -40176,6 +40544,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40176
40544
  */
40177
40545
  resolveActionCall(action, actionType, expression, scope) {
40178
40546
  this.assertActionControlAccessible(action, "invoke", expression.pos);
40547
+ if (action.userData && action.writability === "readOnly" /* ReadOnly */) {
40548
+ throw new CompileError(USER_DATA_WRITE_ERROR, expression.pos);
40549
+ }
40179
40550
  if (expression.callee.kind === "member" && expression.callee.optional) {
40180
40551
  throw new CompileError(
40181
40552
  `${this.describe(actionType)} is never null, so optional-chained invocation is not supported.`,
@@ -40236,19 +40607,15 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40236
40607
  throw new Error("Base call did not produce a function call.");
40237
40608
  return result.pointer;
40238
40609
  }
40239
- const action = this.resolveActionCallee(
40610
+ const callable2 = this.resolveCallableValueCallee(
40240
40611
  expression.callee,
40241
40612
  scope,
40242
40613
  receiverValue
40243
40614
  );
40244
- if (action?.type.kind === "action") {
40245
- return this.resolveActionCall(action, action.type, expression, scope);
40615
+ if (callable2?.type.kind === "action") {
40616
+ return this.resolveActionCall(callable2, callable2.type, expression, scope);
40246
40617
  }
40247
- const delegate = this.resolveDelegateCallee(
40248
- expression.callee,
40249
- scope,
40250
- receiverValue
40251
- );
40618
+ const delegate = callable2;
40252
40619
  if (delegate?.type.kind === "delegate") {
40253
40620
  const delegateType = delegate.type;
40254
40621
  requireArgCount(
@@ -40333,6 +40700,11 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40333
40700
  expression.callee.receiver.name
40334
40701
  );
40335
40702
  if (staticType && staticType.kind !== "enum") {
40703
+ this.assertUserSafe(
40704
+ { kind: "named", typeId: staticType.id },
40705
+ "a static receiver",
40706
+ expression.pos
40707
+ );
40336
40708
  if (expression.callee.optional) {
40337
40709
  throw new CompileError(
40338
40710
  `Optional chaining is not valid on type receiver '${staticType.name}'.`,
@@ -40431,6 +40803,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40431
40803
  pos
40432
40804
  );
40433
40805
  }
40806
+ if (writability === "readOnly" /* ReadOnly */ && receiver.userData) {
40807
+ throw new CompileError(USER_DATA_WRITE_ERROR, pos);
40808
+ }
40434
40809
  throw new CompileError(
40435
40810
  writability === "immutable" /* Immutable */ ? "Cannot mutate a collection whose effective storage is immutable." : "Cannot mutate a read-only collection value.",
40436
40811
  pos
@@ -40525,6 +40900,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40525
40900
  pos
40526
40901
  );
40527
40902
  }
40903
+ if (writability === "readOnly" /* ReadOnly */ && receiver.userData) {
40904
+ throw new CompileError(USER_DATA_WRITE_ERROR, pos);
40905
+ }
40528
40906
  if (writability === "readOnly" /* ReadOnly */) {
40529
40907
  throw new CompileError("Cannot clear a read-only action.", pos);
40530
40908
  }
@@ -40872,7 +41250,17 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40872
41250
  );
40873
41251
  }
40874
41252
  resolveType(type) {
40875
- return resolveNeoScriptType(type, this.context, this.project);
41253
+ const resolved = resolveNeoScriptType(type, this.context, this.project);
41254
+ this.assertUserSafe(resolved, "a type annotation", type.pos);
41255
+ return resolved;
41256
+ }
41257
+ /** P104 §3.2. User code names only User-safe types. */
41258
+ assertUserSafe(type, site, pos) {
41259
+ if (!this.userClassCode) return;
41260
+ const unsafe = userUnsafeTypeName(type, this.project);
41261
+ if (unsafe !== null) {
41262
+ throw new CompileError(userUnsafeTypeMessage(unsafe, site), pos);
41263
+ }
40876
41264
  }
40877
41265
  /**
40878
41266
  * P43 §7.1. A constructor body builds the value it is handed; every other
@@ -41038,7 +41426,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41038
41426
  pointer: { type: "variable" /* Variable */, variableId: symbol.id },
41039
41427
  type: symbol.type,
41040
41428
  symbol,
41041
- ...symbol.writability ? { writability: toWritability(symbol.writability) } : {}
41429
+ ...symbol.writability ? {
41430
+ writability: toWritability(
41431
+ symbol.writability,
41432
+ this.writesUserData
41433
+ )
41434
+ } : {}
41042
41435
  };
41043
41436
  }
41044
41437
  return literal(symbol.type, null);
@@ -42383,8 +42776,10 @@ function namedPrimitive(name) {
42383
42776
  return null;
42384
42777
  }
42385
42778
  }
42386
- function toWritability(value) {
42779
+ function toWritability(value, writesUserData) {
42387
42780
  switch (value) {
42781
+ case "user":
42782
+ return writesUserData ? "runtime" /* Runtime */ : "readOnly" /* ReadOnly */;
42388
42783
  case "save":
42389
42784
  return "save" /* Save */;
42390
42785
  case "session":
@@ -43085,10 +43480,10 @@ function resolvedAllowedStorage(classId, environment) {
43085
43480
  return null;
43086
43481
  }
43087
43482
  function constraintDefaultWritability(allowed) {
43088
- return allowed === "immutable" || allowed === "save" || allowed === "session" ? allowed : "session";
43483
+ return allowed === "immutable" || allowed === "save" || allowed === "session" || allowed === "user" ? allowed : "session";
43089
43484
  }
43090
43485
  function declaredStorageWritability(storage, staticOwnerClassId, environment) {
43091
- if (storage === "immutable" || storage === "save" || storage === "session") {
43486
+ if (storage === "immutable" || storage === "save" || storage === "session" || storage === "user") {
43092
43487
  return storage;
43093
43488
  }
43094
43489
  if (storage === "writable") return "runtime";
@@ -43102,12 +43497,13 @@ function staticDefaultWritability(classId, environment) {
43102
43497
  }
43103
43498
  function createRootType(ids, environment) {
43104
43499
  const definitions = [
43105
- ["Assets", ids.assets, false],
43106
- ["Save", ids.save, true],
43107
- ["Session", ids.session, true]
43500
+ ["Assets", ids.assets, false, "immutable"],
43501
+ ["Save", ids.save, true, "save"],
43502
+ ["Session", ids.session, true, "session"],
43503
+ ["User", ids.user, true, "user"]
43108
43504
  ];
43109
43505
  const members = [];
43110
- for (const [name, memberId, writable] of definitions) {
43506
+ for (const [name, memberId, writable, writability] of definitions) {
43111
43507
  if (!memberId) continue;
43112
43508
  const member = environment.members.get(memberId);
43113
43509
  if (!member) continue;
@@ -43117,7 +43513,7 @@ function createRootType(ids, environment) {
43117
43513
  kind: "property",
43118
43514
  type: memberType(member, environment, /* @__PURE__ */ new Set(), `root.${name}`),
43119
43515
  writable,
43120
- writability: name === "Assets" ? "immutable" : name === "Session" ? "session" : "save",
43516
+ writability,
43121
43517
  documentation: `Project ${name.toLowerCase()} root (${memberId}).`,
43122
43518
  ...sourceLocation(member.source, environment, `root.${name}.source`)
43123
43519
  });
@@ -43140,7 +43536,8 @@ function inferRootMemberIds(members) {
43140
43536
  return {
43141
43537
  assets: unique("immutable"),
43142
43538
  save: unique("save"),
43143
- session: unique("session")
43539
+ session: unique("session"),
43540
+ user: unique("user")
43144
43541
  };
43145
43542
  }
43146
43543
  function effectiveMemberWritability(members, classes, roots) {
@@ -43161,7 +43558,7 @@ function effectiveMemberWritability(members, classes, roots) {
43161
43558
  seen.add(memberId);
43162
43559
  const member = memberById.get(memberId);
43163
43560
  if (!member) return null;
43164
- if (member.storage === "immutable" || member.storage === "save" || member.storage === "session" || member.storage === "writable") {
43561
+ if (member.storage === "immutable" || member.storage === "save" || member.storage === "session" || member.storage === "writable" || member.storage === "user") {
43165
43562
  return member.storage;
43166
43563
  }
43167
43564
  return typeof member.overrideOf === "string" ? declaredStorage(member.overrideOf, seen) : null;
@@ -43229,6 +43626,7 @@ function effectiveMemberWritability(members, classes, roots) {
43229
43626
  if (typeof roots.session === "string") {
43230
43627
  rootStorage.set(roots.session, "session");
43231
43628
  }
43629
+ if (typeof roots.user === "string") rootStorage.set(roots.user, "user");
43232
43630
  for (const [memberId, member] of memberById) {
43233
43631
  const declared = rootStorage.get(memberId) ?? declaredStorage(memberId);
43234
43632
  if (declared === "writable") {
@@ -43300,6 +43698,7 @@ function schemaClass(value, environment, field) {
43300
43698
  ),
43301
43699
  ...value.declarationModifier === "abstract" ? { abstract: true } : {},
43302
43700
  ...value.declarationModifier === "sealed" ? { sealed: true } : {},
43701
+ ...resolvedAllowedStorage(id, environment) === "user" ? { userClass: true } : {},
43303
43702
  ...sourceLocation(value.source, environment, `${field}.source`),
43304
43703
  typeParameters: records(
43305
43704
  value.genericParameters ?? [],
@@ -44804,6 +45203,15 @@ function analyzerMemberById(context, id) {
44804
45203
  }
44805
45204
  return analyzerSchemaIndex(context).member(id) ?? null;
44806
45205
  }
45206
+ function resolveAnalyzerMember(context, member) {
45207
+ const index = activeSchemaIndexByContext.get(context);
45208
+ if (index === void 0) return resolveMember(member, context.vm.members);
45209
+ const cached = index.resolvedMembers.get(member);
45210
+ if (cached !== void 0) return cached;
45211
+ const resolved = resolveMemberFromIndex(member, index.membersById);
45212
+ index.resolvedMembers.set(member, resolved);
45213
+ return resolved;
45214
+ }
44807
45215
 
44808
45216
  // ../src/runtime/neoscript/neoscript-language-context-adapter.ts
44809
45217
  var NEOSCRIPT_COMPILER_ADAPTER_REVISION = 5;
@@ -44812,6 +45220,31 @@ var UNKNOWN_TYPE = {
44812
45220
  name: "unknown"
44813
45221
  };
44814
45222
  var storageResolverByContext = /* @__PURE__ */ new WeakMap();
45223
+ var dialogueProjects = /* @__PURE__ */ new WeakMap();
45224
+ function withDialogueContextType(project, context) {
45225
+ if (!context.dialogueContext) return project;
45226
+ let contexts = dialogueProjects.get(project);
45227
+ if (contexts === void 0) {
45228
+ contexts = /* @__PURE__ */ new Map();
45229
+ dialogueProjects.set(project, contexts);
45230
+ }
45231
+ const dialogueType = createDialogueContextType(context);
45232
+ const key = JSON.stringify(dialogueType);
45233
+ let scoped = contexts.get(key);
45234
+ if (scoped === void 0) {
45235
+ scoped = {
45236
+ ...project,
45237
+ types: [
45238
+ ...project.types.filter(
45239
+ (type) => type.id !== AnalyzerDialogueContextClassId
45240
+ ),
45241
+ dialogueType
45242
+ ]
45243
+ };
45244
+ contexts.set(key, scoped);
45245
+ }
45246
+ return scoped;
45247
+ }
44815
45248
  function createNeoScriptDocumentContext(context, projectOverride) {
44816
45249
  return withAnalyzerSchemaIndex(
44817
45250
  context,
@@ -44819,7 +45252,7 @@ function createNeoScriptDocumentContext(context, projectOverride) {
44819
45252
  );
44820
45253
  }
44821
45254
  function createNeoScriptDocumentContextInScope(context, projectOverride) {
44822
- const project = projectOverride ?? createNeoScriptProject(context);
45255
+ const project = projectOverride === void 0 ? createNeoScriptProject(context) : withDialogueContextType(projectOverride, context);
44823
45256
  const documentKind = context.scriptKind ?? "getter";
44824
45257
  const thisClass = context.thisClass ? namedType(context.thisClass.id, true) : void 0;
44825
45258
  const baseClass = overrideBaseClass(context);
@@ -45033,12 +45466,15 @@ function classToLanguageType(schemaClass2, context) {
45033
45466
  const record4 = analyzerMemberById(context, placement.memberId);
45034
45467
  if (!record4) continue;
45035
45468
  let projectedRecord = record4;
45469
+ let projectedBase;
45036
45470
  try {
45037
45471
  projectedRecord = substituteMember(
45038
45472
  record4,
45039
45473
  genericEnvironment,
45040
- context.vm.members
45474
+ context.vm.members,
45475
+ resolveAnalyzerMember(context, record4)
45041
45476
  );
45477
+ projectedBase = projectedRecord;
45042
45478
  } catch {
45043
45479
  }
45044
45480
  const symbol = memberToSymbol(
@@ -45048,7 +45484,8 @@ function classToLanguageType(schemaClass2, context) {
45048
45484
  placement.ownerClassId,
45049
45485
  index,
45050
45486
  context,
45051
- genericEnvironment
45487
+ genericEnvironment,
45488
+ projectedBase
45052
45489
  );
45053
45490
  if (!symbol) continue;
45054
45491
  names.add(symbol.name);
@@ -45081,6 +45518,7 @@ function classToLanguageType(schemaClass2, context) {
45081
45518
  ...schemaClass2.docsText ? { documentation: schemaClass2.docsText } : {},
45082
45519
  kind: "class",
45083
45520
  abstract: isAbstractClass(schemaClass2),
45521
+ ...resolveAllowedStorage(schemaClass2.id, context.vm.classes) === 5 /* User */ ? { userClass: true } : {},
45084
45522
  location: virtualIdentifierLocation(
45085
45523
  context,
45086
45524
  "Classes",
@@ -45132,7 +45570,8 @@ function constructorSignature(schemaClass2, members, context, genericEnvironment
45132
45570
  const resolved = substituteMember(
45133
45571
  record4,
45134
45572
  genericEnvironment,
45135
- context.vm.members
45573
+ context.vm.members,
45574
+ resolveAnalyzerMember(context, record4)
45136
45575
  );
45137
45576
  return {
45138
45577
  required: isRequiredMember(resolved),
@@ -45158,7 +45597,8 @@ function constructorSignature(schemaClass2, members, context, genericEnvironment
45158
45597
  const resolved = substituteMember(
45159
45598
  record4,
45160
45599
  genericEnvironment,
45161
- context.vm.members
45600
+ context.vm.members,
45601
+ resolveAnalyzerMember(context, record4)
45162
45602
  );
45163
45603
  return {
45164
45604
  required: isRequiredMember(resolved),
@@ -45210,10 +45650,10 @@ function canonicalMemberId(id, context) {
45210
45650
  }
45211
45651
  return resolve(id);
45212
45652
  }
45213
- function memberToSymbol(record4, schemaKey, containingClass, ownerClassId, index, context, genericEnvironment) {
45653
+ function memberToSymbol(record4, schemaKey, containingClass, ownerClassId, index, context, genericEnvironment, projectedBase) {
45214
45654
  let resolved;
45215
45655
  try {
45216
- resolved = resolveMember(record4, context.vm.members);
45656
+ resolved = projectedBase ?? resolveAnalyzerMember(context, record4);
45217
45657
  } catch {
45218
45658
  return null;
45219
45659
  }
@@ -45221,7 +45661,8 @@ function memberToSymbol(record4, schemaKey, containingClass, ownerClassId, index
45221
45661
  record4,
45222
45662
  context,
45223
45663
  /* @__PURE__ */ new Set(),
45224
- genericEnvironment
45664
+ genericEnvironment,
45665
+ resolved
45225
45666
  );
45226
45667
  const owner = analyzerSchemaIndex(context).class(ownerClassId);
45227
45668
  const inheritedFrom = owner && owner.id !== containingClass.id ? {
@@ -45356,6 +45797,8 @@ function symbolWritability(memberId, context, staticOwnerClassId) {
45356
45797
  return { writability: "session" };
45357
45798
  case 4 /* Writable */:
45358
45799
  return { writability: "runtime" };
45800
+ case 5 /* User */:
45801
+ return { writability: "user" };
45359
45802
  }
45360
45803
  }
45361
45804
  function uniqueEffectiveWritability(memberId, context) {
@@ -45377,6 +45820,8 @@ function uniqueEffectiveWritability(memberId, context) {
45377
45820
  return "save";
45378
45821
  case 3 /* Session */:
45379
45822
  return "session";
45823
+ case 5 /* User */:
45824
+ return "user";
45380
45825
  }
45381
45826
  }
45382
45827
  function interfaceToLanguageType(neoInterface, context) {
@@ -45476,14 +45921,17 @@ function interfaceMemberToSymbol(neoInterface, key, member, context, inherited)
45476
45921
  ...inheritedFrom ? { inheritedFrom } : {}
45477
45922
  };
45478
45923
  }
45924
+ var ROOT_WRITABILITY = {
45925
+ [1 /* Immutable */]: "immutable",
45926
+ [2 /* Save */]: "save",
45927
+ [3 /* Session */]: "session",
45928
+ [5 /* User */]: "user"
45929
+ };
45479
45930
  function createRootType2(context) {
45480
- const definitions = [
45481
- ["Assets", context.vm.project.rootAssetsMemberId],
45482
- ["Save", context.vm.project.rootSaveFileMemberId],
45483
- ["Session", context.vm.project.rootSessionMemberId]
45484
- ];
45485
45931
  const members = [];
45486
- for (const [index, [name, memberId]] of definitions.entries()) {
45932
+ for (const [index, root] of PROJECT_ROOTS.entries()) {
45933
+ const name = root.key;
45934
+ const memberId = context.vm.project[root.projectField];
45487
45935
  const member = analyzerMemberById(context, memberId);
45488
45936
  if (!member) continue;
45489
45937
  members.push({
@@ -45491,8 +45939,8 @@ function createRootType2(context) {
45491
45939
  name,
45492
45940
  kind: "property",
45493
45941
  type: memberRuntimeType(member, context),
45494
- writable: name !== "Assets",
45495
- writability: name === "Assets" ? "immutable" : name === "Session" ? "session" : "save",
45942
+ writable: root.storage !== 1 /* Immutable */,
45943
+ writability: ROOT_WRITABILITY[root.storage],
45496
45944
  documentation: `Project ${name.toLowerCase()} root (${memberId}).`,
45497
45945
  location: virtualIdentifierLocation(
45498
45946
  context,
@@ -45545,7 +45993,7 @@ function createListIndexes(context) {
45545
45993
  for (const record4 of context.vm.members) {
45546
45994
  let resolved;
45547
45995
  try {
45548
- resolved = resolveMember(record4, context.vm.members);
45996
+ resolved = resolveAnalyzerMember(context, record4);
45549
45997
  } catch {
45550
45998
  continue;
45551
45999
  }
@@ -45575,12 +46023,12 @@ function createListIndexes(context) {
45575
46023
  }
45576
46024
  return result;
45577
46025
  }
45578
- function memberRuntimeType(record4, context, seen = /* @__PURE__ */ new Set(), genericEnvironment) {
46026
+ function memberRuntimeType(record4, context, seen = /* @__PURE__ */ new Set(), genericEnvironment, projectedBase) {
45579
46027
  if (seen.has(record4.id)) return UNKNOWN_TYPE;
45580
46028
  const nextSeen = new Set(seen).add(record4.id);
45581
46029
  let member;
45582
46030
  try {
45583
- member = resolveMember(record4, context.vm.members);
46031
+ member = projectedBase ?? resolveAnalyzerMember(context, record4);
45584
46032
  } catch {
45585
46033
  return UNKNOWN_TYPE;
45586
46034
  }
@@ -45827,7 +46275,12 @@ function classArguments(member, context, seen, genericEnvironment) {
45827
46275
  function substituteForGenericEnvironment(member, environment, context) {
45828
46276
  if (!environment) return member;
45829
46277
  try {
45830
- return substituteMember(member, environment, context.vm.members);
46278
+ return substituteMember(
46279
+ member,
46280
+ environment,
46281
+ context.vm.members,
46282
+ resolveAnalyzerMember(context, member)
46283
+ );
45831
46284
  } catch {
45832
46285
  return member;
45833
46286
  }
@@ -46059,9 +46512,7 @@ function projectLanguageVersion(context) {
46059
46512
  `adapter:${NEOSCRIPT_COMPILER_ADAPTER_REVISION}`,
46060
46513
  context.vm.project.id,
46061
46514
  context.vm.project.updatedAt,
46062
- context.vm.project.rootAssetsMemberId,
46063
- context.vm.project.rootSaveFileMemberId,
46064
- context.vm.project.rootSessionMemberId,
46515
+ ...projectRootMemberIds(context.vm.project),
46065
46516
  ...records2.map((record4) => `${record4.id}:${record4.updatedAt}`).sort()
46066
46517
  ].join("|");
46067
46518
  }
@@ -46115,7 +46566,7 @@ function scriptDefinitionLocations2(memberId, context) {
46115
46566
  if (!record4) return {};
46116
46567
  let resolved;
46117
46568
  try {
46118
- resolved = resolveMember(record4, context.vm.members);
46569
+ resolved = resolveAnalyzerMember(context, record4);
46119
46570
  } catch {
46120
46571
  return {};
46121
46572
  }
@@ -46201,7 +46652,7 @@ function virtualNeoSchemaClassHeader(schemaClass2, context) {
46201
46652
  return `public ${isAbstractClass(schemaClass2) ? "abstract " : ""}partial class ${virtualCSharpIdentifier(schemaClass2.name)}${genericParameters}${inheritance}${constraints.join("")} // Neo class ${schemaClass2.id}`;
46202
46653
  }
46203
46654
  function virtualConstraintMemberType(member, context) {
46204
- const resolved = resolveMember(member, context.vm.members);
46655
+ const resolved = resolveAnalyzerMember(context, member);
46205
46656
  switch (resolved.kind) {
46206
46657
  case 1 /* Bool */:
46207
46658
  return "bool";
@@ -47037,7 +47488,7 @@ async function restartProjectRead(read) {
47037
47488
  // ../src/models/project/project-types.ts
47038
47489
  function isProject(value) {
47039
47490
  const v = value;
47040
- return typeof v?.name === "string" && typeof v?.id === "string" && isProjectOwner(v.owner) && isActorIdentifier(v.author) && typeof v?.createdAt === "number" && typeof v?.updatedAt === "number" && typeof v?.rootAssetsMemberId === "string" && typeof v?.rootSaveFileMemberId === "string" && typeof v?.rootSessionMemberId === "string" && isOptionalNullableString2(v.defaultPriorityGroupId) && isOptionalNullableString2(v.defaultTextureTemplateId) && isOptionalNullableString2(v.defaultAudioClipTemplateId) && isProjectExportSettingsOrEmpty(v.exportSettings);
47491
+ return typeof v?.name === "string" && typeof v?.id === "string" && isProjectOwner(v.owner) && isActorIdentifier(v.author) && typeof v?.createdAt === "number" && typeof v?.updatedAt === "number" && typeof v?.rootAssetsMemberId === "string" && typeof v?.rootSaveFileMemberId === "string" && typeof v?.rootSessionMemberId === "string" && typeof v?.rootUserMemberId === "string" && isOptionalNullableString2(v.defaultPriorityGroupId) && isOptionalNullableString2(v.defaultTextureTemplateId) && isOptionalNullableString2(v.defaultAudioClipTemplateId) && isProjectExportSettingsOrEmpty(v.exportSettings);
47041
47492
  }
47042
47493
  function isProjectOwner(value) {
47043
47494
  if (!isActorIdentifier(value)) return false;
@@ -48774,18 +49225,18 @@ function readProjectDocument(value, options = {}) {
48774
49225
  "localizationConfig",
48775
49226
  isProjectLocalizationConfig
48776
49227
  ) : readField(value, "localizationConfig", isProjectLocalizationConfig);
48777
- const storedValues = readArrayField(value, "values", isMemberValue);
49228
+ const storedValues = readDocumentArrayField(value, "values", isMemberValue);
48778
49229
  const valueBuckets = options.values === "stored" ? { values: storedValues } : projectDocumentValueBuckets(storedValues);
48779
49230
  return {
48780
49231
  version: readField(value, "version", isProjectVersion),
48781
- versions: readArrayField(value, "versions", isProjectVersion),
49232
+ versions: readDocumentArrayField(value, "versions", isProjectVersion),
48782
49233
  versionStatus: readField(value, "versionStatus", isProjectVersionStatus),
48783
- versionStatuses: readArrayField(
49234
+ versionStatuses: readDocumentArrayField(
48784
49235
  value,
48785
49236
  "versionStatuses",
48786
49237
  isProjectVersionStatus
48787
49238
  ),
48788
- releaseChannels: readArrayField(
49239
+ releaseChannels: readDocumentArrayField(
48789
49240
  value,
48790
49241
  "releaseChannels",
48791
49242
  isProjectReleaseChannel
@@ -48795,7 +49246,7 @@ function readProjectDocument(value, options = {}) {
48795
49246
  value,
48796
49247
  options.members === "authored-or-compiled" ? isAnyMemberAuthoredOrCompiled : isAnyMember
48797
49248
  ),
48798
- classes: readArrayField(value, "classes", isNeoSchemaClass),
49249
+ classes: readDocumentArrayField(value, "classes", isNeoSchemaClass),
48799
49250
  constructors: readOptionalArrayField(
48800
49251
  value,
48801
49252
  "constructors",
@@ -48816,13 +49267,13 @@ function readProjectDocument(value, options = {}) {
48816
49267
  // Retain the physical bucket after expansion for write-path comparisons.
48817
49268
  values: valueBuckets.values,
48818
49269
  ...valueBuckets.physicalValues === void 0 ? {} : { physicalValues: valueBuckets.physicalValues },
48819
- enums: readArrayField(
49270
+ enums: readDocumentArrayField(
48820
49271
  value,
48821
49272
  "enums",
48822
49273
  options.identities === "prospective" ? isProspectiveEnum : isEnum
48823
49274
  ),
48824
- interfaces: readArrayField(value, "interfaces", isNeoInterface),
48825
- ...options.dialogues === "omit" ? {} : { dialogues: readArrayField(value, "dialogues", isDialogue) },
49275
+ interfaces: readDocumentArrayField(value, "interfaces", isNeoInterface),
49276
+ ...options.dialogues === "omit" ? {} : { dialogues: readDocumentArrayField(value, "dialogues", isDialogue) },
48826
49277
  dialogueRecords: readOptionalArrayField(
48827
49278
  value,
48828
49279
  "dialogueRecords",
@@ -48833,26 +49284,38 @@ function readProjectDocument(value, options = {}) {
48833
49284
  "dialogueNodes",
48834
49285
  isDialogueNodeRecord
48835
49286
  ),
48836
- dialogueGroups: readArrayField(value, "dialogueGroups", isAnyDialogueGroup),
48837
- priorityGroups: readArrayField(value, "priorityGroups", isPriorityGroup),
48838
- projectFiles: readArrayField(value, "projectFiles", isProjectFile),
48839
- textureTemplates: readArrayField(
49287
+ dialogueGroups: readDocumentArrayField(
49288
+ value,
49289
+ "dialogueGroups",
49290
+ isAnyDialogueGroup
49291
+ ),
49292
+ priorityGroups: readDocumentArrayField(
49293
+ value,
49294
+ "priorityGroups",
49295
+ isPriorityGroup
49296
+ ),
49297
+ projectFiles: readDocumentArrayField(value, "projectFiles", isProjectFile),
49298
+ textureTemplates: readDocumentArrayField(
48840
49299
  value,
48841
49300
  "textureTemplates",
48842
49301
  isUnityTexture2DImportSettingsTemplate
48843
49302
  ),
48844
- audioClipTemplates: readArrayField(
49303
+ audioClipTemplates: readDocumentArrayField(
48845
49304
  value,
48846
49305
  "audioClipTemplates",
48847
49306
  isUnityAudioClipImportSettingsTemplate
48848
49307
  ),
48849
49308
  localizationConfig,
48850
- localizationStatuses: readArrayField(
49309
+ localizationStatuses: readDocumentArrayField(
48851
49310
  value,
48852
49311
  "localizationStatuses",
48853
49312
  isLocalizationStatus
48854
49313
  ),
48855
- localizedTexts: readArrayField(value, "localizedTexts", isLocalizedText),
49314
+ localizedTexts: readDocumentArrayField(
49315
+ value,
49316
+ "localizedTexts",
49317
+ isLocalizedText
49318
+ ),
48856
49319
  migrations: readOptionalArrayField(value, "migrations", isProjectMigration)
48857
49320
  };
48858
49321
  }
@@ -48882,7 +49345,7 @@ function isHashHead(value) {
48882
49345
  }
48883
49346
  function readField(source, key, isValid) {
48884
49347
  const value = source[key];
48885
- if (isValid(value)) return value;
49348
+ if (frozenRecordGuard(isValid)(value)) return value;
48886
49349
  throw new Error(
48887
49350
  `Convex project document field "${key}" has an invalid shape.`
48888
49351
  );
@@ -48890,11 +49353,23 @@ function readField(source, key, isValid) {
48890
49353
  function readOptionalNullableField(source, key, isValid) {
48891
49354
  const value = source[key];
48892
49355
  if (value === void 0 || value === null) return null;
48893
- if (isValid(value)) return value;
49356
+ if (frozenRecordGuard(isValid)(value)) return value;
48894
49357
  throw new Error(
48895
49358
  `Convex project document field "${key}" has an invalid shape.`
48896
49359
  );
48897
49360
  }
49361
+ var frozenRecordGuards = /* @__PURE__ */ new WeakMap();
49362
+ function frozenRecordGuard(isValid) {
49363
+ let guard = frozenRecordGuards.get(isValid);
49364
+ if (guard === void 0) {
49365
+ guard = memoizeFrozenJsonGuard(isValid);
49366
+ frozenRecordGuards.set(isValid, guard);
49367
+ }
49368
+ return guard;
49369
+ }
49370
+ function readDocumentArrayField(source, key, isValid) {
49371
+ return readArrayField(source, key, frozenRecordGuard(isValid));
49372
+ }
48898
49373
  function readArrayField(source, key, isValid) {
48899
49374
  const value = source[key];
48900
49375
  if (!Array.isArray(value)) {
@@ -48916,10 +49391,10 @@ function describeRejectedCompilerRevision(value) {
48916
49391
  }
48917
49392
  function readOptionalArrayField(source, key, isValid) {
48918
49393
  if (!Object.prototype.hasOwnProperty.call(source, key)) return [];
48919
- return readArrayField(source, key, isValid);
49394
+ return readDocumentArrayField(source, key, isValid);
48920
49395
  }
48921
49396
  function readStoredMembersField(source, isValid = isAnyMember) {
48922
- return readArrayField(
49397
+ return readDocumentArrayField(
48923
49398
  source,
48924
49399
  "members",
48925
49400
  isValid
@@ -49206,10 +49681,20 @@ var WORLD_LAYER_LINK_KINDS = /* @__PURE__ */ new Set([
49206
49681
  NeoWorldSystemClassKind.ObjectLayerLink
49207
49682
  ]);
49208
49683
 
49209
- // ../packages/manifest/src/value-comparison.ts
49210
- function isObjectRecord(value) {
49211
- return typeof value === "object" && value !== null && !Array.isArray(value);
49212
- }
49684
+ // ../src/database/project-snapshot-derived-edges.ts
49685
+ var REFERENCE_ID_PAYLOAD = canonicalJsonStringify({
49686
+ referenceKind: "record-id"
49687
+ });
49688
+ var REFERENCE_NAME_PAYLOAD = canonicalJsonStringify({
49689
+ referenceKind: "type-name"
49690
+ });
49691
+ var CONSTRUCTED_CLASS_PAYLOAD = canonicalJsonStringify({
49692
+ referenceKind: "constructed-class-id"
49693
+ });
49694
+ var BODY_CHILD_PAYLOAD = canonicalJsonStringify({
49695
+ relation: "body-child",
49696
+ depth: 1
49697
+ });
49213
49698
 
49214
49699
  // ../src/models/project/world-content-sidecar-validation.ts
49215
49700
  var WORLD_PLACEMENT_ASSET_KIND = /* @__PURE__ */ new Map([[NeoWorldSystemClassKind.Object, NeoWorldSystemClassKind.Object]]);
@@ -51305,7 +51790,9 @@ var commonMemberEntries = {
51305
51790
  defaultValue: nullable(schemaDefaultValueSchema),
51306
51791
  overrideOf: nullableId,
51307
51792
  system: nullable(schemaSystemMetadataSchema),
51308
- storage: nullable(picklist(["immutable", "save", "session", "writable"])),
51793
+ storage: nullable(
51794
+ picklist(["immutable", "save", "session", "writable", "user"])
51795
+ ),
51309
51796
  distribution: nullable(picklist(["sparse", "packed"])),
51310
51797
  storageKey: nullableId
51311
51798
  };
@@ -51495,7 +51982,8 @@ var MEMBER_STORAGE = [
51495
51982
  "immutable",
51496
51983
  "save",
51497
51984
  "session",
51498
- "writable"
51985
+ "writable",
51986
+ "user"
51499
51987
  ];
51500
51988
  var MEMBER_DISTRIBUTION = ["sparse", "packed"];
51501
51989
  var STRING_FORMAT = ["localized", "plain"];
@@ -53387,7 +53875,8 @@ var CLASS_ALLOWED_STORAGE = [
53387
53875
  "immutable",
53388
53876
  "save",
53389
53877
  "session",
53390
- "writable"
53878
+ "writable",
53879
+ "user"
53391
53880
  ];
53392
53881
  var CLASS_SCHEMA_RECORD_ADAPTER = {
53393
53882
  recordKind: "class",
@@ -54143,6 +54632,1442 @@ var SPECIALIZED_RELATION_KINDS = /* @__PURE__ */ new Set([
54143
54632
  "world.object-layer-link.target"
54144
54633
  ]);
54145
54634
 
54635
+ // ../packages/manifest/schema-contract/registry.mjs
54636
+ var PROJECT_SCHEMA_CONTRACT = Object.freeze({
54637
+ cliVersion: "0.72.1",
54638
+ projectFileUploadBatchSize: 32,
54639
+ documentRecords: {
54640
+ member: {
54641
+ authored: [
54642
+ "id",
54643
+ "name",
54644
+ "docsText",
54645
+ "kind",
54646
+ "requirement",
54647
+ "mutability",
54648
+ "modifier",
54649
+ "access",
54650
+ "defaultValue",
54651
+ "extendsMemberId",
54652
+ "system",
54653
+ "storage",
54654
+ "storageKey",
54655
+ // Deliberately carries no normalization rule (P76 §1): absence is the
54656
+ // canonical automatic setting and explicit ordinal 0 is an explicit
54657
+ // `.Sparse`, so `absentMeansDefault` would collapse the two states
54658
+ // that the whole contract exists to keep apart.
54659
+ "distribution",
54660
+ "minValue",
54661
+ "maxValue",
54662
+ "decimalPoints",
54663
+ "format",
54664
+ "searchBy",
54665
+ "entryMemberId",
54666
+ "keyKind",
54667
+ "keyEnumId",
54668
+ "listKind",
54669
+ "indexes",
54670
+ "columnSettings",
54671
+ "classId",
54672
+ "payload",
54673
+ "schemaKeyOrder",
54674
+ "classArguments",
54675
+ "enumId",
54676
+ "selection",
54677
+ "collectionMemberId",
54678
+ "collectionValueId",
54679
+ "declaredTypeInfo",
54680
+ "targetTypeInfo",
54681
+ "valueTypeInfo",
54682
+ "dialogueGroupId",
54683
+ "code",
54684
+ "setterCode",
54685
+ "returnTypeInfo",
54686
+ "argumentTypes",
54687
+ "dispatch",
54688
+ "bodyMode",
54689
+ // P97 §1.1. No normalization rule, like `distribution`: absence means
54690
+ // unset (a declaration resolves to `.None`, an override inherits) and
54691
+ // explicit ordinal 0 is an authored `.None` that stops inheritance.
54692
+ "effect",
54693
+ "uiAction",
54694
+ "templateId",
54695
+ "genericParamId"
54696
+ ],
54697
+ derived: ["valueId", "getter", "setter", "action"],
54698
+ volatile: ["projectId", "createdAt", "updatedAt"],
54699
+ normalization: {
54700
+ requirement: { kind: "absentMeansDefault", defaultValue: 0 },
54701
+ mutability: { kind: "absentMeansDefault", defaultValue: 0 },
54702
+ modifier: { kind: "absentMeansDefault", defaultValue: 0 },
54703
+ access: { kind: "absentMeansDefault", defaultValue: 0 },
54704
+ defaultValue: "nullIsAbsentOnFullMember",
54705
+ extendsMemberId: "nullIsAbsent",
54706
+ system: "nullIsAbsent",
54707
+ storage: { kind: "absentMeansDefault", defaultValue: 0 },
54708
+ storageKey: "nullOrEmptyStringIsAbsentOnFullMember",
54709
+ minValue: "nullIsAbsentOnFullMember",
54710
+ maxValue: "nullIsAbsentOnFullMember",
54711
+ decimalPoints: "nullIsAbsentOnFullMember",
54712
+ format: { kind: "absentMeansDefault", defaultValue: 0 },
54713
+ searchBy: { kind: "absentMeansDefault", defaultValue: 0 },
54714
+ keyEnumId: "nullIsAbsent",
54715
+ keyKind: { kind: "absentMeansDefault", defaultValue: 0 },
54716
+ listKind: { kind: "absentMeansDefault", defaultValue: 0 },
54717
+ indexes: "nullOrEmptyArrayIsAbsentOnFullMember",
54718
+ columnSettings: "nullOrEmptyArrayIsAbsentOnFullMember",
54719
+ schemaKeyOrder: "nullIsAbsentOnFullMember",
54720
+ classArguments: "nullOrEmptyObjectIsAbsentOnFullMember",
54721
+ payload: { kind: "absentMeansDefault", defaultValue: 0 },
54722
+ selection: { kind: "absentMeansDefault", defaultValue: 0 },
54723
+ collectionValueId: "nullIsAbsentOnFullMember",
54724
+ declaredTypeInfo: "nullIsAbsentOnFullMember",
54725
+ targetTypeInfo: "nullIsAbsentOnFullMember",
54726
+ valueTypeInfo: "nullIsAbsentOnFullMember",
54727
+ dialogueGroupId: "nullIsAbsentOnFullMember",
54728
+ code: "nullIsAbsentOnFullMember",
54729
+ templateId: "nullIsAbsentOnFullMember",
54730
+ setterCode: "nullIsAbsentOnFullMember",
54731
+ dispatch: { kind: "absentMeansDefault", defaultValue: 0 },
54732
+ bodyMode: { kind: "absentMeansDefault", defaultValue: 0 },
54733
+ uiAction: "nullIsAbsentOnFullMember"
54734
+ }
54735
+ },
54736
+ class: {
54737
+ authored: [
54738
+ "id",
54739
+ "name",
54740
+ "docsText",
54741
+ "schema",
54742
+ "schemaKeyOrder",
54743
+ "extendsClassId",
54744
+ "implementsInterfaceIds",
54745
+ "uiVisibility",
54746
+ "modifier",
54747
+ "system",
54748
+ "allowedStorage",
54749
+ "allowedStorageKeys",
54750
+ "genericParams",
54751
+ "extendsGenericBindings",
54752
+ "constructorIds",
54753
+ "requiredConstructorId",
54754
+ "targetMemberId"
54755
+ ],
54756
+ derived: [],
54757
+ volatile: ["projectId", "createdAt", "updatedAt"],
54758
+ normalization: {
54759
+ uiVisibility: { kind: "absentMeansDefault", defaultValue: 0 },
54760
+ modifier: { kind: "absentMeansDefault", defaultValue: 0 },
54761
+ targetMemberId: "nullIsAbsent",
54762
+ schemaKeyOrder: "nullIsAbsent",
54763
+ extendsClassId: "nullIsAbsent",
54764
+ implementsInterfaceIds: "nullOrEmptyArrayIsAbsent",
54765
+ system: "nullIsAbsent",
54766
+ allowedStorage: { kind: "absentMeansDefault", defaultValue: 0 },
54767
+ allowedStorageKeys: "nullIsAbsent",
54768
+ genericParams: "nullOrEmptyArrayIsAbsent",
54769
+ extendsGenericBindings: "nullOrEmptyObjectIsAbsent",
54770
+ constructorIds: "nullOrEmptyArrayIsAbsent",
54771
+ requiredConstructorId: "nullIsAbsent"
54772
+ }
54773
+ },
54774
+ constructor: {
54775
+ authored: [
54776
+ "id",
54777
+ "classId",
54778
+ "argumentTypes",
54779
+ "code",
54780
+ "baseArguments",
54781
+ "baseInitializerFields",
54782
+ "docsText"
54783
+ ],
54784
+ derived: [
54785
+ "action",
54786
+ "compiledBaseArguments",
54787
+ "compiledBaseInitializerFields"
54788
+ ],
54789
+ volatile: ["projectId", "createdAt", "updatedAt"],
54790
+ // `code` is deliberately un-normalized. P49 §1.2 gives it three states —
54791
+ // a body, `""` for a declared-but-empty body, and `null` for a class
54792
+ // header that declares no `init` block — and the last two must stay
54793
+ // distinct in the canonical form or `neo pull` cannot tell
54794
+ // `class Foo { init { } }` from `class Foo()`. `nullIsAbsent` would keep
54795
+ // them distinct too, but it drops the field from the written record
54796
+ // (`composeDocumentRecord` writes the normalized authored half), which
54797
+ // would make the persisted shape disagree with the domain model's
54798
+ // required `code: string | null`. Leaving it plain means exactly two
54799
+ // spellings of an empty body reach storage, never three.
54800
+ normalization: {
54801
+ baseArguments: "nullOrEmptyArrayIsAbsent",
54802
+ baseInitializerFields: "nullOrEmptyArrayIsAbsent"
54803
+ }
54804
+ },
54805
+ variant: {
54806
+ // P67 §2.1. A variant record names its class, its scope, and the root row
54807
+ // of the value graph it owns. The delegates themselves are value rows, so
54808
+ // the compiled `action` IR the server derives lives there, not here —
54809
+ // which is why this record has no derived half at all.
54810
+ authored: ["id", "classId", "name", "folderId", "valueId"],
54811
+ derived: [],
54812
+ volatile: ["projectId", "createdAt", "updatedAt"],
54813
+ // `folderId` is always written: null is the class root folder, and a
54814
+ // missing field would make "root" and "corrupt" the same shape.
54815
+ normalization: { folderId: "missingIsNull" }
54816
+ },
54817
+ "variant-folder": {
54818
+ // P67 §3.3. A folder's whole content is its path, which is what lets a
54819
+ // rename be a one-record edit that orphans nothing.
54820
+ authored: ["id", "classId", "path", "binding"],
54821
+ derived: [],
54822
+ volatile: ["projectId", "createdAt", "updatedAt"],
54823
+ normalization: { binding: "nullIsAbsent" }
54824
+ },
54825
+ interface: {
54826
+ authored: [
54827
+ "id",
54828
+ "name",
54829
+ "docsText",
54830
+ "members",
54831
+ "memberKeyOrder",
54832
+ "extendsInterfaceIds",
54833
+ "system"
54834
+ ],
54835
+ derived: [],
54836
+ volatile: ["projectId", "createdAt", "updatedAt"],
54837
+ normalization: {
54838
+ memberKeyOrder: "nullOrEmptyArrayIsAbsent",
54839
+ extendsInterfaceIds: "nullOrEmptyArrayIsAbsent",
54840
+ system: "nullIsAbsent"
54841
+ }
54842
+ },
54843
+ enum: {
54844
+ authored: [
54845
+ "id",
54846
+ "name",
54847
+ "docsText",
54848
+ "options",
54849
+ "optionKeyOrder",
54850
+ "system"
54851
+ ],
54852
+ derived: [],
54853
+ volatile: ["projectId", "createdAt", "updatedAt"],
54854
+ normalization: { system: "nullIsAbsent" }
54855
+ },
54856
+ "unity-texture-template": {
54857
+ authored: [
54858
+ "id",
54859
+ "name",
54860
+ "type",
54861
+ "textureType",
54862
+ "textureShape",
54863
+ "sRGBTexture",
54864
+ "alphaSource",
54865
+ "alphaIsTransparency",
54866
+ "nonPowerOfTwoScale",
54867
+ "ignorePngGamma",
54868
+ "readWriteEnabled",
54869
+ "virtualTextureOnly",
54870
+ "generateMipMaps",
54871
+ "borderMipMaps",
54872
+ "mipMapFiltering",
54873
+ "mipMapsPreserveCoverage",
54874
+ "alphaCutoffValue",
54875
+ "fadeOutMipMaps",
54876
+ "mipMapFadeDistanceStart",
54877
+ "mipMapFadeDistanceEnd",
54878
+ "anisoLevel",
54879
+ "wrapMode",
54880
+ "wrapModeU",
54881
+ "wrapModeV",
54882
+ "filterMode",
54883
+ "maxTextureSize",
54884
+ "resizeAlgorithm",
54885
+ "textureCompression",
54886
+ "compressionQuality",
54887
+ "crunchedCompression",
54888
+ "platformSettings",
54889
+ "spriteSettings",
54890
+ "normalMapSettings",
54891
+ "cookieSettings",
54892
+ "singleChannelSettings",
54893
+ "swizzle"
54894
+ ],
54895
+ derived: [],
54896
+ volatile: ["projectId", "createdAt", "updatedAt"],
54897
+ normalization: {
54898
+ wrapModeU: "missingIsNull",
54899
+ wrapModeV: "missingIsNull",
54900
+ spriteSettings: "missingIsNull",
54901
+ normalMapSettings: "missingIsNull",
54902
+ cookieSettings: "missingIsNull",
54903
+ singleChannelSettings: "missingIsNull",
54904
+ swizzle: "missingIsNull"
54905
+ }
54906
+ },
54907
+ "unity-audio-clip-template": {
54908
+ authored: [
54909
+ "id",
54910
+ "name",
54911
+ "forceToMono",
54912
+ "normalize",
54913
+ "loadInBackground",
54914
+ "ambisonic",
54915
+ "loadType",
54916
+ "compressionFormat",
54917
+ "quality",
54918
+ "sampleRateSetting",
54919
+ "overrideSampleRate",
54920
+ "preloadAudioData"
54921
+ ],
54922
+ derived: [],
54923
+ volatile: ["projectId", "createdAt", "updatedAt"],
54924
+ normalization: { overrideSampleRate: "missingIsNull" }
54925
+ },
54926
+ "localization-config": {
54927
+ authored: [
54928
+ "id",
54929
+ "mainLocale",
54930
+ "supportedLocales",
54931
+ "sortedStatusIds",
54932
+ "mainLocaleDefaultStatusId"
54933
+ ],
54934
+ derived: [],
54935
+ volatile: ["projectId", "createdAt", "updatedAt"],
54936
+ normalization: {}
54937
+ },
54938
+ "localization-status": {
54939
+ authored: [
54940
+ "id",
54941
+ "slug",
54942
+ "name",
54943
+ "description",
54944
+ "color",
54945
+ "emoji",
54946
+ "archivedAt",
54947
+ "transitionRules",
54948
+ "transitionToStatusIdOnEditText",
54949
+ "transitionToWhenSourceBecomesStatusId",
54950
+ "system"
54951
+ ],
54952
+ derived: [],
54953
+ volatile: ["projectId", "createdAt", "updatedAt"],
54954
+ normalization: {
54955
+ description: "missingIsNull",
54956
+ color: "missingIsNull",
54957
+ emoji: "missingIsNull",
54958
+ archivedAt: "missingIsNull",
54959
+ transitionRules: "missingIsNull",
54960
+ transitionToStatusIdOnEditText: "missingIsNull",
54961
+ transitionToWhenSourceBecomesStatusId: "missingIsNull",
54962
+ system: "nullIsAbsent"
54963
+ }
54964
+ },
54965
+ "internal-record-relation": {
54966
+ authored: [
54967
+ "id",
54968
+ "relationKind",
54969
+ "sourceRecordKind",
54970
+ "sourceRecordId",
54971
+ "targetRecordKind",
54972
+ "targetRecordId",
54973
+ "orderKey"
54974
+ ],
54975
+ derived: [],
54976
+ volatile: ["projectId", "createdAt", "updatedAt"],
54977
+ normalization: { orderKey: "nullIsAbsent" }
54978
+ }
54979
+ },
54980
+ sdkDeclarations: {
54981
+ attributes: {
54982
+ enums: {
54983
+ NeoStorage: [
54984
+ "Inherit",
54985
+ "Immutable",
54986
+ "Save",
54987
+ "Session",
54988
+ "Writable",
54989
+ "User"
54990
+ ],
54991
+ NeoAllowedStorage: [
54992
+ "Any",
54993
+ "Immutable",
54994
+ "Save",
54995
+ "Session",
54996
+ "Writable",
54997
+ "User"
54998
+ ],
54999
+ NeoListKind: ["Ordered", "Unordered"],
55000
+ NeoDictionaryKeyKind: ["String", "Enum"],
55001
+ NeoClassVisibility: ["Visible", "Hidden"],
55002
+ NeoSubtreeDistribution: ["Sparse", "Packed"],
55003
+ NeoStringFormat: ["Localized", "Plain"],
55004
+ NeoMemberSearchBy: ["None", "MemberKey"],
55005
+ NeoListIndexKind: ["Bucket", "Unique"],
55006
+ NeoColumnVisibility: ["Visible", "Hidden"],
55007
+ NeoColumnPin: ["None", "Leading"],
55008
+ NeoColumnOverflow: ["Clip", "Wrap"],
55009
+ NeoFileKind: ["Sprite", "Audio"],
55010
+ NeoEffectKind: ["None", "Auto"]
55011
+ },
55012
+ markers: {
55013
+ NeoSchemaClassAttribute: {
55014
+ targets: ["Class"],
55015
+ constructor: [
55016
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55017
+ ],
55018
+ properties: [
55019
+ { type: "string?", name: "Id", access: "get" },
55020
+ { type: "string?", name: "Name", access: "set" },
55021
+ {
55022
+ type: "NeoClassVisibility",
55023
+ name: "Visibility",
55024
+ access: "set",
55025
+ default: "NeoClassVisibility.Visible"
55026
+ },
55027
+ {
55028
+ type: "NeoAllowedStorage",
55029
+ name: "AllowedStorage",
55030
+ access: "set",
55031
+ default: "NeoAllowedStorage.Any"
55032
+ },
55033
+ { type: "string[]?", name: "AllowedStorageKeys", access: "set" }
55034
+ ]
55035
+ },
55036
+ NeoInterfaceAttribute: {
55037
+ targets: ["Interface"],
55038
+ constructor: [
55039
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55040
+ ],
55041
+ properties: [
55042
+ { type: "string?", name: "Id", access: "get" },
55043
+ { type: "string?", name: "Name", access: "set" }
55044
+ ]
55045
+ },
55046
+ NeoEnumAttribute: {
55047
+ targets: ["Enum"],
55048
+ constructor: [
55049
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55050
+ ],
55051
+ properties: [
55052
+ { type: "string?", name: "Id", access: "get" },
55053
+ { type: "string?", name: "Name", access: "set" }
55054
+ ]
55055
+ },
55056
+ NeoIdAttribute: {
55057
+ targets: ["GenericParameter"],
55058
+ constructor: [
55059
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55060
+ ],
55061
+ properties: [{ type: "string?", name: "Id", access: "get" }]
55062
+ },
55063
+ NeoMemberAttribute: {
55064
+ targets: ["Property", "Method"],
55065
+ constructor: [
55066
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55067
+ ],
55068
+ properties: [
55069
+ { type: "string?", name: "Id", access: "get" },
55070
+ { type: "string?", name: "Key", access: "set" },
55071
+ { type: "string?", name: "Name", access: "set" },
55072
+ {
55073
+ type: "NeoStorage",
55074
+ name: "Storage",
55075
+ access: "set",
55076
+ default: "NeoStorage.Inherit"
55077
+ },
55078
+ { type: "string?", name: "StorageKey", access: "set" },
55079
+ { type: "int", name: "Order", access: "set", default: "-1" }
55080
+ ]
55081
+ },
55082
+ NeoSystemAttribute: {
55083
+ targets: ["Class", "Interface", "Enum", "Property", "Method"],
55084
+ constructor: [
55085
+ {
55086
+ type: "NeoSystemProtectionKind",
55087
+ name: "kind",
55088
+ assigns: "Kind"
55089
+ }
55090
+ ],
55091
+ properties: [
55092
+ {
55093
+ type: "NeoSystemProtectionKind",
55094
+ name: "Kind",
55095
+ access: "get"
55096
+ },
55097
+ {
55098
+ type: "NeoWorldKind",
55099
+ name: "WorldKind",
55100
+ access: "set",
55101
+ default: "NeoWorldKind.None"
55102
+ }
55103
+ ]
55104
+ },
55105
+ NeoTextAttribute: {
55106
+ targets: ["Property"],
55107
+ properties: [
55108
+ {
55109
+ type: "NeoStringFormat",
55110
+ name: "Format",
55111
+ access: "set",
55112
+ default: "NeoStringFormat.Localized"
55113
+ },
55114
+ {
55115
+ type: "NeoMemberSearchBy",
55116
+ name: "SearchBy",
55117
+ access: "set",
55118
+ default: "NeoMemberSearchBy.None"
55119
+ }
55120
+ ]
55121
+ },
55122
+ NeoNullAttribute: { targets: ["Property"], properties: [] },
55123
+ NeoNumberAttribute: {
55124
+ targets: ["Property"],
55125
+ properties: [
55126
+ {
55127
+ type: "double",
55128
+ name: "Min",
55129
+ access: "set",
55130
+ default: "double.NaN"
55131
+ },
55132
+ {
55133
+ type: "double",
55134
+ name: "Max",
55135
+ access: "set",
55136
+ default: "double.NaN"
55137
+ },
55138
+ { type: "string?", name: "DecimalMin", access: "set" },
55139
+ { type: "string?", name: "DecimalMax", access: "set" },
55140
+ {
55141
+ type: "int",
55142
+ name: "DecimalPoints",
55143
+ access: "set",
55144
+ default: "-1"
55145
+ }
55146
+ ]
55147
+ },
55148
+ NeoDictionaryAttribute: {
55149
+ targets: ["Property"],
55150
+ properties: [
55151
+ {
55152
+ type: "NeoDictionaryKeyKind",
55153
+ name: "KeyKind",
55154
+ access: "set",
55155
+ default: "NeoDictionaryKeyKind.String"
55156
+ },
55157
+ { type: "Type?", name: "KeyEnum", access: "set" }
55158
+ ]
55159
+ },
55160
+ NeoListAttribute: {
55161
+ targets: ["Property"],
55162
+ properties: [
55163
+ {
55164
+ type: "NeoListKind",
55165
+ name: "Kind",
55166
+ access: "set",
55167
+ default: "NeoListKind.Ordered"
55168
+ }
55169
+ ]
55170
+ },
55171
+ NeoEntriesAttribute: {
55172
+ targets: ["Class", "Property"],
55173
+ constructor: [
55174
+ { type: "string", name: "settings", assigns: "Settings" }
55175
+ ],
55176
+ properties: [{ type: "string", name: "Settings", access: "get" }]
55177
+ },
55178
+ NeoSchemaOrderAttribute: {
55179
+ targets: ["Class", "Property"],
55180
+ constructor: [
55181
+ {
55182
+ type: "string[]",
55183
+ name: "members",
55184
+ modifier: "params",
55185
+ assigns: "Members"
55186
+ }
55187
+ ],
55188
+ properties: [{ type: "string[]", name: "Members", access: "get" }]
55189
+ },
55190
+ NeoIndexAttribute: {
55191
+ targets: ["Property"],
55192
+ allowMultiple: true,
55193
+ constructor: [{ type: "string", name: "member", assigns: "Member" }],
55194
+ properties: [
55195
+ { type: "string", name: "Member", access: "get" },
55196
+ {
55197
+ type: "NeoListIndexKind",
55198
+ name: "Kind",
55199
+ access: "set",
55200
+ default: "NeoListIndexKind.Bucket"
55201
+ }
55202
+ ]
55203
+ },
55204
+ NeoColumnAttribute: {
55205
+ targets: ["Property"],
55206
+ allowMultiple: true,
55207
+ constructor: [{ type: "string", name: "member", assigns: "Member" }],
55208
+ properties: [
55209
+ { type: "string", name: "Member", access: "get" },
55210
+ { type: "int", name: "Width", access: "set", default: "-1" },
55211
+ {
55212
+ type: "NeoColumnVisibility",
55213
+ name: "Visibility",
55214
+ access: "set",
55215
+ default: "NeoColumnVisibility.Visible"
55216
+ },
55217
+ {
55218
+ type: "NeoColumnPin",
55219
+ name: "Pin",
55220
+ access: "set",
55221
+ default: "NeoColumnPin.None"
55222
+ },
55223
+ {
55224
+ type: "NeoColumnOverflow",
55225
+ name: "Overflow",
55226
+ access: "set",
55227
+ default: "NeoColumnOverflow.Clip"
55228
+ }
55229
+ ]
55230
+ },
55231
+ NeoLookupAttribute: {
55232
+ targets: ["Property"],
55233
+ constructor: [
55234
+ {
55235
+ type: "string",
55236
+ name: "collectionMember",
55237
+ assigns: "CollectionMember"
55238
+ }
55239
+ ],
55240
+ properties: [
55241
+ { type: "string", name: "CollectionMember", access: "get" },
55242
+ { type: "string?", name: "CollectionValueMember", access: "set" }
55243
+ ]
55244
+ },
55245
+ NeoDialogueAttribute: {
55246
+ targets: ["Property"],
55247
+ properties: [{ type: "string?", name: "Group", access: "set" }]
55248
+ },
55249
+ NeoFileAttribute: {
55250
+ targets: ["Property"],
55251
+ constructor: [{ type: "NeoFileKind", name: "kind", assigns: "Kind" }],
55252
+ properties: [
55253
+ { type: "NeoFileKind", name: "Kind", access: "get" },
55254
+ { type: "Type?", name: "Template", access: "set" }
55255
+ ]
55256
+ },
55257
+ NeoComputedAttribute: { targets: ["Property"], properties: [] },
55258
+ NeoScriptAttribute: { targets: ["Method"], properties: [] },
55259
+ NeoFunctionAttribute: { targets: ["Method"], properties: [] },
55260
+ NeoEnumOptionAttribute: {
55261
+ targets: ["Field"],
55262
+ constructor: [
55263
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55264
+ ],
55265
+ properties: [
55266
+ { type: "string?", name: "Id", access: "get" },
55267
+ { type: "string?", name: "Key", access: "set" },
55268
+ { type: "string?", name: "Text", access: "set" }
55269
+ ]
55270
+ },
55271
+ NeoTextureTemplateAttribute: {
55272
+ targets: ["Class", "Property"],
55273
+ constructor: [
55274
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55275
+ ],
55276
+ properties: [{ type: "string?", name: "Id", access: "get" }]
55277
+ },
55278
+ NeoAudioTemplateAttribute: {
55279
+ targets: ["Class", "Property"],
55280
+ constructor: [
55281
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55282
+ ],
55283
+ properties: [{ type: "string?", name: "Id", access: "get" }]
55284
+ },
55285
+ NeoLocalizationAttribute: {
55286
+ targets: ["Class", "Property"],
55287
+ constructor: [
55288
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55289
+ ],
55290
+ properties: [{ type: "string?", name: "Id", access: "get" }]
55291
+ },
55292
+ NeoLocalizationStatusAttribute: {
55293
+ targets: ["Class", "Property"],
55294
+ constructor: [
55295
+ { type: "string?", name: "id", default: "null", assigns: "Id" }
55296
+ ],
55297
+ properties: [{ type: "string?", name: "Id", access: "get" }]
55298
+ },
55299
+ NeoRegistryAttribute: { targets: ["Class"], properties: [] },
55300
+ NeoRelationConfigurationAttribute: {
55301
+ targets: ["Class"],
55302
+ properties: []
55303
+ }
55304
+ }
55305
+ },
55306
+ settings: {
55307
+ enums: {
55308
+ NeoProjectRecordKind: [
55309
+ "Project",
55310
+ "Member",
55311
+ "Value",
55312
+ "Class",
55313
+ "InternalRecordRelation",
55314
+ "Enum",
55315
+ "Interface",
55316
+ "Dialogue",
55317
+ "DialogueNode",
55318
+ "DialogueGroup",
55319
+ "PriorityGroup",
55320
+ "ProjectFile",
55321
+ "UnityTextureTemplate",
55322
+ "UnityAudioClipTemplate",
55323
+ "LocalizationConfig",
55324
+ "LocalizationStatus",
55325
+ "LocalizedText",
55326
+ "Migration"
55327
+ ],
55328
+ NeoEntryKind: [
55329
+ "Null",
55330
+ "Boolean",
55331
+ "Integer",
55332
+ "String",
55333
+ "Float",
55334
+ "Decimal",
55335
+ "Vector2",
55336
+ "Vector2Int",
55337
+ "Vector3",
55338
+ "Vector3Int",
55339
+ "Color",
55340
+ "Dictionary",
55341
+ "List",
55342
+ "Class",
55343
+ "Enum",
55344
+ "Lookup",
55345
+ "DialogueLookup",
55346
+ "Sprite",
55347
+ "Audio",
55348
+ "Generic"
55349
+ ],
55350
+ NeoSystemProtectionKind: [
55351
+ "WorldAuthoring",
55352
+ "DialogueMemorySchema",
55353
+ "DialogueMemoryContainer",
55354
+ "DialoguePriorityDefault",
55355
+ "PolicyImmutable",
55356
+ "PolicyDeleteBlocked",
55357
+ "ScriptRuntime"
55358
+ ],
55359
+ NeoMemberRequirement: ["Optional", "Required"],
55360
+ NeoMemberMutability: ["Mutable", "ReadOnly"],
55361
+ NeoMemberModifier: ["Virtual", "Sealed", "Abstract", "Static"],
55362
+ NeoMemberAccess: ["Public", "Protected", "Private"],
55363
+ NeoMemberSelection: ["Single", "Multi"],
55364
+ NeoFunctionDispatch: ["Synchronous", "Asynchronous"],
55365
+ NeoMemberPayload: ["Full", "Partial"],
55366
+ NeoFunctionLogicMode: ["UI"],
55367
+ NeoWorldKind: [
55368
+ "CellPattern",
55369
+ "None",
55370
+ "TileGrid",
55371
+ "TileLayer",
55372
+ "ObjectLayer",
55373
+ "Tile",
55374
+ "ObjectBase",
55375
+ "LayerGroupBase",
55376
+ "SpriteObject",
55377
+ "Object",
55378
+ "TileLayerLink",
55379
+ "ObjectLayerLink",
55380
+ "PlacementTile",
55381
+ "ObjectCollider",
55382
+ "SortingGroup",
55383
+ "SortingLayer",
55384
+ "SmartTile",
55385
+ "SmartTileRule",
55386
+ "SmartTileNeighbor",
55387
+ "AnimationClip",
55388
+ "AnimationFrame",
55389
+ "AnimationChildOverride",
55390
+ "AnimationFrameBase",
55391
+ "AnimationSegmentFrame",
55392
+ "AnimationSegment",
55393
+ "SpriteAnimationSegment",
55394
+ "AnimationTrack",
55395
+ "AnimationChildTrack",
55396
+ "AnimationSegmentTrack",
55397
+ "SpriteAnimationSegmentTrack",
55398
+ "Variant",
55399
+ "VariantFolder",
55400
+ "LookupVariant",
55401
+ "LookupVariantFolder"
55402
+ ],
55403
+ NeoTextureType: [
55404
+ "Default",
55405
+ "NormalMap",
55406
+ "EditorGuiAndLegacyGui",
55407
+ "Sprite",
55408
+ "Cursor",
55409
+ "Cookie",
55410
+ "Lightmap",
55411
+ "SingleChannel"
55412
+ ],
55413
+ NeoSpriteMode: ["Single", "Multiple", "Polygon"],
55414
+ NeoSpriteMeshType: ["FullRect", "Tight"],
55415
+ NeoSpriteAlignment: [
55416
+ "Center",
55417
+ "TopLeft",
55418
+ "TopCenter",
55419
+ "TopRight",
55420
+ "LeftCenter",
55421
+ "RightCenter",
55422
+ "BottomLeft",
55423
+ "BottomCenter",
55424
+ "BottomRight",
55425
+ "Custom"
55426
+ ],
55427
+ NeoTextureWrapMode: [
55428
+ "Repeat",
55429
+ "Clamp",
55430
+ "Mirror",
55431
+ "MirrorOnce",
55432
+ "PerAxis"
55433
+ ],
55434
+ NeoTextureFilterMode: ["Point", "Bilinear", "Trilinear"],
55435
+ NeoTextureCompression: [
55436
+ "None",
55437
+ "LowQuality",
55438
+ "NormalQuality",
55439
+ "HighQuality"
55440
+ ],
55441
+ NeoTextureFormat: [
55442
+ "Automatic",
55443
+ "RgbaCompressedDxt5Bc3",
55444
+ "RgbCompressedDxt1Bc1",
55445
+ "Rgba32Bit",
55446
+ "Rgb24Bit"
55447
+ ],
55448
+ NeoAlphaSource: ["None", "InputTextureAlpha", "FromGrayScale"],
55449
+ NeoNonPowerOfTwoScale: ["None", "ToNearest", "ToLarger", "ToSmaller"],
55450
+ NeoNormalMapFiltering: ["Sharp", "Smooth"],
55451
+ NeoCookieLightType: ["Spot", "Directional", "Point"],
55452
+ NeoSingleChannelComponent: ["Alpha", "Red"],
55453
+ NeoTextureSwizzle: ["Red", "Green", "Blue", "Alpha", "Zero", "One"],
55454
+ NeoMipMapFiltering: ["Box", "Kaiser"],
55455
+ NeoTextureResizeAlgorithm: ["Mitchell", "Bilinear"],
55456
+ NeoAudioLoadType: [
55457
+ "DecompressOnLoad",
55458
+ "CompressedInMemory",
55459
+ "Streaming"
55460
+ ],
55461
+ NeoAudioCompressionFormat: ["Pcm", "Adpcm", "Vorbis"],
55462
+ NeoAudioSampleRate: [
55463
+ "PreserveSampleRate",
55464
+ "OptimizeSampleRate",
55465
+ "OverrideSampleRate"
55466
+ ]
55467
+ },
55468
+ classes: {
55469
+ NeoClassRelationDefinition: {
55470
+ constructors: [
55471
+ [{ type: "Type", name: "target", assigns: "Target" }],
55472
+ [
55473
+ { type: "string?", name: "id", assigns: "Id" },
55474
+ { type: "Type", name: "target", assigns: "Target" }
55475
+ ]
55476
+ ],
55477
+ properties: [
55478
+ { type: "string?", name: "Id" },
55479
+ { type: "Type", name: "Target", default: "typeof(object)" }
55480
+ ]
55481
+ },
55482
+ NeoGridRelationSettings: [
55483
+ {
55484
+ type: "List<NeoClassRelationDefinition>",
55485
+ name: "TileImports",
55486
+ default: "new List<NeoClassRelationDefinition>()"
55487
+ },
55488
+ {
55489
+ type: "List<NeoClassRelationDefinition>",
55490
+ name: "ObjectImports",
55491
+ default: "new List<NeoClassRelationDefinition>()"
55492
+ },
55493
+ {
55494
+ type: "List<NeoClassRelationDefinition>",
55495
+ name: "TileLayers",
55496
+ default: "new List<NeoClassRelationDefinition>()"
55497
+ },
55498
+ {
55499
+ type: "List<NeoClassRelationDefinition>",
55500
+ name: "ObjectLayers",
55501
+ default: "new List<NeoClassRelationDefinition>()"
55502
+ }
55503
+ ],
55504
+ NeoTileRelationSettings: [
55505
+ {
55506
+ type: "List<NeoClassRelationDefinition>",
55507
+ name: "CompatibleLayers",
55508
+ default: "new List<NeoClassRelationDefinition>()"
55509
+ },
55510
+ { type: "NeoClassRelationDefinition?", name: "DefaultLayer" }
55511
+ ],
55512
+ NeoObjectRelationSettings: [
55513
+ {
55514
+ type: "List<NeoClassRelationDefinition>",
55515
+ name: "CompatibleLayers",
55516
+ default: "new List<NeoClassRelationDefinition>()"
55517
+ },
55518
+ { type: "NeoClassRelationDefinition?", name: "DefaultLayer" }
55519
+ ],
55520
+ NeoTileLayerLinkRelationSettings: [
55521
+ { type: "NeoClassRelationDefinition?", name: "TargetLayer" }
55522
+ ],
55523
+ NeoObjectLayerLinkRelationSettings: [
55524
+ { type: "NeoClassRelationDefinition?", name: "TargetLayer" }
55525
+ ],
55526
+ NeoEntrySettings: [
55527
+ { type: "string?", name: "Id" },
55528
+ { type: "string", name: "Path", default: "string.Empty" },
55529
+ { type: "NeoEntryKind", name: "Kind" },
55530
+ {
55531
+ type: "NeoMemberRequirement",
55532
+ name: "Requirement",
55533
+ default: "NeoMemberRequirement.Optional"
55534
+ },
55535
+ {
55536
+ type: "NeoMemberMutability",
55537
+ name: "Mutability",
55538
+ default: "NeoMemberMutability.Mutable"
55539
+ },
55540
+ {
55541
+ type: "NeoMemberModifier",
55542
+ name: "Modifier",
55543
+ default: "NeoMemberModifier.Virtual"
55544
+ },
55545
+ {
55546
+ type: "NeoMemberAccess",
55547
+ name: "Access",
55548
+ default: "NeoMemberAccess.Public"
55549
+ },
55550
+ { type: "NeoMemberReference?", name: "Overrides" },
55551
+ {
55552
+ type: "NeoStorage",
55553
+ name: "Storage",
55554
+ default: "NeoStorage.Inherit"
55555
+ },
55556
+ { type: "string?", name: "StorageKey" },
55557
+ { type: "NeoValueSettings?", name: "Default" },
55558
+ { type: "NeoTextSettings?", name: "Text" },
55559
+ { type: "NeoNumberSettings?", name: "Number" },
55560
+ { type: "NeoDictionarySettings?", name: "Dictionary" },
55561
+ { type: "NeoListSettings?", name: "List" },
55562
+ { type: "NeoLookupSettings?", name: "Lookup" },
55563
+ { type: "NeoDialogueSettings?", name: "Dialogue" },
55564
+ { type: "NeoFileSettings?", name: "File" },
55565
+ { type: "NeoClassSettings?", name: "Class" },
55566
+ { type: "NeoEnumSettings?", name: "Enum" },
55567
+ { type: "NeoGenericSettings?", name: "Generic" },
55568
+ { type: "NeoSystemSettings?", name: "System" },
55569
+ {
55570
+ type: "IReadOnlyList<NeoEntrySettings>",
55571
+ name: "Entries",
55572
+ default: "new List<NeoEntrySettings>()"
55573
+ }
55574
+ ],
55575
+ NeoValueSettings: [
55576
+ { type: "bool", name: "IsNull" },
55577
+ { type: "Type?", name: "ConcreteType" },
55578
+ { type: "bool?", name: "Boolean" },
55579
+ { type: "long?", name: "Integer" },
55580
+ { type: "double?", name: "Number" },
55581
+ { type: "string?", name: "Text" },
55582
+ { type: "decimal?", name: "Decimal" },
55583
+ { type: "NeoVector2?", name: "Vector2" },
55584
+ { type: "NeoVector2Int?", name: "Vector2Int" },
55585
+ { type: "NeoVector3?", name: "Vector3" },
55586
+ { type: "NeoVector3Int?", name: "Vector3Int" },
55587
+ { type: "NeoColor?", name: "Color" },
55588
+ { type: "NeoSprite?", name: "Sprite" },
55589
+ { type: "NeoAudio?", name: "Audio" },
55590
+ { type: "NeoDialogue?", name: "Dialogue" },
55591
+ { type: "NeoReferenceSettings?", name: "Reference" },
55592
+ { type: "string?", name: "EnumOption" },
55593
+ { type: "IReadOnlyList<NeoValueSettings>?", name: "List" },
55594
+ {
55595
+ type: "IReadOnlyDictionary<string, NeoValueSettings>?",
55596
+ name: "Dictionary"
55597
+ },
55598
+ {
55599
+ type: "IReadOnlyDictionary<string, NeoValueSettings>?",
55600
+ name: "Object"
55601
+ }
55602
+ ],
55603
+ NeoReferenceSettings: [
55604
+ { type: "Type", name: "Type", default: "typeof(object)" },
55605
+ { type: "string", name: "Id", default: "string.Empty" }
55606
+ ],
55607
+ NeoTextSettings: [
55608
+ {
55609
+ type: "NeoStringFormat",
55610
+ name: "Format",
55611
+ default: "NeoStringFormat.Localized"
55612
+ },
55613
+ {
55614
+ type: "NeoMemberSearchBy",
55615
+ name: "SearchBy",
55616
+ default: "NeoMemberSearchBy.None"
55617
+ }
55618
+ ],
55619
+ NeoNumberSettings: [
55620
+ { type: "double?", name: "Min" },
55621
+ { type: "double?", name: "Max" },
55622
+ { type: "string?", name: "DecimalMin" },
55623
+ { type: "string?", name: "DecimalMax" },
55624
+ { type: "int?", name: "DecimalPoints" }
55625
+ ],
55626
+ NeoFunctionSettings: [{ type: "NeoFunctionLogicMode", name: "Logic" }],
55627
+ NeoDictionarySettings: [
55628
+ { type: "NeoDictionaryKeyKind", name: "KeyKind" },
55629
+ { type: "Type?", name: "KeyEnum" }
55630
+ ],
55631
+ NeoClassSettings: [
55632
+ { type: "Type", name: "Type", default: "typeof(object)" },
55633
+ { type: "IReadOnlyList<string>?", name: "SchemaOrder" },
55634
+ {
55635
+ type: "IReadOnlyDictionary<string, NeoGenericBindingSettings>?",
55636
+ name: "TypeArguments"
55637
+ }
55638
+ ],
55639
+ NeoGenericBindingSettings: [
55640
+ { type: "string", name: "Parameter", default: "string.Empty" },
55641
+ { type: "string?", name: "GenericParameter" },
55642
+ { type: "NeoEntrySettings?", name: "Member" }
55643
+ ],
55644
+ NeoEnumSettings: [
55645
+ { type: "Type", name: "Enum", default: "typeof(object)" },
55646
+ {
55647
+ type: "NeoMemberSelection",
55648
+ name: "Selection",
55649
+ default: "NeoMemberSelection.Single"
55650
+ }
55651
+ ],
55652
+ NeoGenericSettings: [
55653
+ { type: "string", name: "Parameter", default: "string.Empty" }
55654
+ ],
55655
+ NeoLookupSettings: [
55656
+ { type: "string", name: "CollectionMember", default: "string.Empty" },
55657
+ { type: "string?", name: "CollectionValueMember" },
55658
+ {
55659
+ type: "NeoMemberSelection",
55660
+ name: "Selection",
55661
+ default: "NeoMemberSelection.Single"
55662
+ }
55663
+ ],
55664
+ /**
55665
+ * Class-level settings. `TargetMember` names the member of another
55666
+ * class this class writes — schema metadata rather than row data, the
55667
+ * same shape `NeoLookupSettings.CollectionMember` uses to name a
55668
+ * collection.
55669
+ */
55670
+ NeoClassSchemaSettings: [
55671
+ { type: "string", name: "TargetMember", default: "string.Empty" }
55672
+ ],
55673
+ NeoDialogueSettings: [
55674
+ { type: "string?", name: "Group" },
55675
+ {
55676
+ type: "NeoMemberSelection",
55677
+ name: "Selection",
55678
+ default: "NeoMemberSelection.Single"
55679
+ }
55680
+ ],
55681
+ NeoFileSettings: [
55682
+ { type: "NeoFileKind", name: "Kind" },
55683
+ { type: "Type?", name: "Template" }
55684
+ ],
55685
+ NeoSystemSettings: [
55686
+ {
55687
+ type: "NeoSystemProtectionKind",
55688
+ name: "Kind",
55689
+ default: "NeoSystemProtectionKind.WorldAuthoring"
55690
+ },
55691
+ { type: "NeoWorldKind?", name: "WorldKind" }
55692
+ ],
55693
+ NeoListSettings: [
55694
+ { type: "NeoListKind", name: "Kind", default: "NeoListKind.Ordered" },
55695
+ {
55696
+ type: "IReadOnlyList<NeoListIndexSettings>",
55697
+ name: "Indexes",
55698
+ default: "new List<NeoListIndexSettings>()"
55699
+ },
55700
+ {
55701
+ type: "IReadOnlyList<NeoListColumnSettings>",
55702
+ name: "Columns",
55703
+ default: "new List<NeoListColumnSettings>()"
55704
+ }
55705
+ ],
55706
+ NeoListIndexSettings: [
55707
+ { type: "string", name: "Member", default: "string.Empty" },
55708
+ {
55709
+ type: "NeoListIndexKind",
55710
+ name: "Kind",
55711
+ default: "NeoListIndexKind.Bucket"
55712
+ }
55713
+ ],
55714
+ NeoListColumnSettings: [
55715
+ { type: "string", name: "Member", default: "string.Empty" },
55716
+ { type: "int?", name: "Width" },
55717
+ {
55718
+ type: "NeoColumnVisibility",
55719
+ name: "Visibility",
55720
+ default: "NeoColumnVisibility.Visible"
55721
+ },
55722
+ {
55723
+ type: "NeoColumnPin",
55724
+ name: "Pin",
55725
+ default: "NeoColumnPin.None"
55726
+ },
55727
+ {
55728
+ type: "NeoColumnOverflow",
55729
+ name: "Overflow",
55730
+ default: "NeoColumnOverflow.Clip"
55731
+ }
55732
+ ],
55733
+ NeoTextureTemplateSettings: [
55734
+ { type: "string", name: "Name", default: "string.Empty" },
55735
+ {
55736
+ type: "NeoTextureType",
55737
+ name: "TextureType",
55738
+ default: "NeoTextureType.Sprite"
55739
+ },
55740
+ { type: "bool", name: "SrgbTexture", default: "true" },
55741
+ {
55742
+ type: "NeoAlphaSource",
55743
+ name: "AlphaSource",
55744
+ default: "NeoAlphaSource.InputTextureAlpha"
55745
+ },
55746
+ { type: "bool", name: "AlphaIsTransparency", default: "true" },
55747
+ { type: "NeoNonPowerOfTwoScale", name: "NonPowerOfTwoScale" },
55748
+ { type: "bool", name: "IgnorePngGamma" },
55749
+ { type: "bool", name: "ReadWriteEnabled" },
55750
+ { type: "bool", name: "VirtualTextureOnly" },
55751
+ { type: "bool", name: "GenerateMipMaps" },
55752
+ { type: "bool", name: "BorderMipMaps" },
55753
+ { type: "NeoMipMapFiltering", name: "MipMapFiltering" },
55754
+ { type: "bool", name: "MipMapsPreserveCoverage" },
55755
+ { type: "double", name: "AlphaCutoffValue", default: "0.5" },
55756
+ { type: "bool", name: "FadeOutMipMaps" },
55757
+ { type: "int", name: "MipMapFadeDistanceStart", default: "1" },
55758
+ { type: "int", name: "MipMapFadeDistanceEnd", default: "3" },
55759
+ { type: "int", name: "AnisoLevel", default: "1" },
55760
+ {
55761
+ type: "NeoTextureWrapMode",
55762
+ name: "WrapMode",
55763
+ default: "NeoTextureWrapMode.Clamp"
55764
+ },
55765
+ { type: "NeoTextureWrapMode?", name: "WrapModeU" },
55766
+ { type: "NeoTextureWrapMode?", name: "WrapModeV" },
55767
+ {
55768
+ type: "NeoTextureFilterMode",
55769
+ name: "FilterMode",
55770
+ default: "NeoTextureFilterMode.Point"
55771
+ },
55772
+ { type: "int", name: "MaxTextureSize", default: "2048" },
55773
+ { type: "NeoTextureResizeAlgorithm", name: "ResizeAlgorithm" },
55774
+ { type: "NeoTextureCompression", name: "TextureCompression" },
55775
+ { type: "int", name: "CompressionQuality", default: "50" },
55776
+ { type: "bool", name: "CrunchedCompression" },
55777
+ {
55778
+ type: "NeoTexturePlatformSettings",
55779
+ name: "Platforms",
55780
+ default: "new()"
55781
+ },
55782
+ { type: "NeoSpriteSettings?", name: "Sprite" },
55783
+ { type: "NeoNormalMapSettings?", name: "NormalMap" },
55784
+ { type: "NeoCookieSettings?", name: "Cookie" },
55785
+ { type: "NeoSingleChannelSettings?", name: "SingleChannel" },
55786
+ { type: "NeoSwizzleSettings?", name: "Swizzle" }
55787
+ ],
55788
+ NeoTexturePlatformSettings: [
55789
+ {
55790
+ type: "NeoTexturePlatformEntry",
55791
+ name: "Default",
55792
+ default: "new()"
55793
+ },
55794
+ {
55795
+ type: "NeoTexturePlatformEntry",
55796
+ name: "Standalone",
55797
+ default: "new()"
55798
+ },
55799
+ { type: "NeoTexturePlatformEntry", name: "Web", default: "new()" }
55800
+ ],
55801
+ NeoTexturePlatformEntry: [
55802
+ { type: "bool", name: "Override" },
55803
+ { type: "int", name: "MaxTextureSize", default: "2048" },
55804
+ { type: "NeoTextureResizeAlgorithm", name: "ResizeAlgorithm" },
55805
+ { type: "NeoTextureFormat", name: "Format" },
55806
+ { type: "NeoTextureCompression", name: "TextureCompression" },
55807
+ { type: "bool", name: "CrunchedCompression" },
55808
+ { type: "int", name: "CompressionQuality", default: "50" }
55809
+ ],
55810
+ NeoSpriteSettings: [
55811
+ {
55812
+ type: "NeoSpriteMode",
55813
+ name: "Mode",
55814
+ default: "NeoSpriteMode.Multiple"
55815
+ },
55816
+ { type: "double", name: "PixelsPerUnit", default: "100" },
55817
+ {
55818
+ type: "NeoSpriteMeshType",
55819
+ name: "MeshType",
55820
+ default: "NeoSpriteMeshType.Tight"
55821
+ },
55822
+ { type: "int", name: "ExtrudeEdges", default: "1" },
55823
+ { type: "NeoSpriteAlignment", name: "PivotAlignment" },
55824
+ { type: "NeoVector2", name: "Pivot", default: "new(0.5, 0.5)" },
55825
+ { type: "bool", name: "GeneratePhysicsShape", default: "true" },
55826
+ { type: "NeoSpriteSliceSettings?", name: "Slice" }
55827
+ ],
55828
+ NeoSpriteSliceSettings: [
55829
+ { type: "NeoVector2", name: "PixelSize" },
55830
+ { type: "NeoVector2", name: "Offset" },
55831
+ { type: "NeoVector2", name: "Padding" },
55832
+ { type: "bool", name: "KeepEmptyRects" },
55833
+ { type: "NeoSpriteAlignment", name: "PivotAlignment" },
55834
+ { type: "NeoVector2", name: "Pivot" },
55835
+ { type: "NeoVector4", name: "Border" },
55836
+ { type: "string", name: "NamingPattern", default: '"{0}"' },
55837
+ { type: "int", name: "NamingStartIndex" },
55838
+ { type: "bool", name: "ColumnMajor" }
55839
+ ],
55840
+ NeoNormalMapSettings: [
55841
+ { type: "bool", name: "CreateFromGrayscale" },
55842
+ { type: "double", name: "Bumpiness", default: "0.25" },
55843
+ {
55844
+ type: "NeoNormalMapFiltering",
55845
+ name: "Filtering",
55846
+ default: "NeoNormalMapFiltering.Smooth"
55847
+ },
55848
+ { type: "bool", name: "FlipGreenChannel" }
55849
+ ],
55850
+ NeoCookieSettings: [{ type: "NeoCookieLightType", name: "LightType" }],
55851
+ NeoSingleChannelSettings: [
55852
+ { type: "NeoSingleChannelComponent", name: "Component" }
55853
+ ],
55854
+ NeoSwizzleSettings: [
55855
+ {
55856
+ type: "NeoTextureSwizzle",
55857
+ name: "R",
55858
+ default: "NeoTextureSwizzle.Red"
55859
+ },
55860
+ {
55861
+ type: "NeoTextureSwizzle",
55862
+ name: "G",
55863
+ default: "NeoTextureSwizzle.Green"
55864
+ },
55865
+ {
55866
+ type: "NeoTextureSwizzle",
55867
+ name: "B",
55868
+ default: "NeoTextureSwizzle.Blue"
55869
+ },
55870
+ {
55871
+ type: "NeoTextureSwizzle",
55872
+ name: "A",
55873
+ default: "NeoTextureSwizzle.Alpha"
55874
+ }
55875
+ ],
55876
+ NeoAudioTemplateSettings: [
55877
+ { type: "string", name: "Name", default: "string.Empty" },
55878
+ { type: "bool", name: "ForceToMono" },
55879
+ { type: "bool", name: "Normalize" },
55880
+ { type: "bool", name: "LoadInBackground" },
55881
+ { type: "bool", name: "Ambisonic" },
55882
+ { type: "NeoAudioLoadType", name: "LoadType" },
55883
+ {
55884
+ type: "NeoAudioCompressionFormat",
55885
+ name: "CompressionFormat",
55886
+ default: "NeoAudioCompressionFormat.Vorbis"
55887
+ },
55888
+ { type: "double", name: "Quality", default: "1" },
55889
+ { type: "NeoAudioSampleRate", name: "SampleRate" },
55890
+ { type: "int?", name: "OverrideSampleRate" },
55891
+ { type: "bool", name: "PreloadAudioData", default: "true" }
55892
+ ],
55893
+ NeoLocalizationSettings: [
55894
+ { type: "string", name: "MainLocale", default: '"en-US"' },
55895
+ {
55896
+ type: "IReadOnlyList<NeoLocaleSettings>",
55897
+ name: "Locales",
55898
+ default: "new List<NeoLocaleSettings>()"
55899
+ },
55900
+ {
55901
+ type: "IReadOnlyList<string>",
55902
+ name: "StatusIds",
55903
+ default: "new List<string>()"
55904
+ },
55905
+ {
55906
+ type: "string",
55907
+ name: "MainLocaleDefaultStatus",
55908
+ default: "string.Empty"
55909
+ }
55910
+ ],
55911
+ NeoLocaleSettings: [
55912
+ { type: "string", name: "Locale", default: "string.Empty" },
55913
+ { type: "string?", name: "SourceLocale" },
55914
+ { type: "string?", name: "Name" },
55915
+ { type: "int", name: "Order" },
55916
+ { type: "long?", name: "ArchivedAt" }
55917
+ ],
55918
+ NeoLocalizationStatusSettings: [
55919
+ { type: "string", name: "Slug", default: "string.Empty" },
55920
+ { type: "string", name: "Name", default: "string.Empty" },
55921
+ { type: "string?", name: "Description" },
55922
+ { type: "string?", name: "Color" },
55923
+ { type: "string?", name: "Emoji" },
55924
+ { type: "long?", name: "ArchivedAt" },
55925
+ { type: "IReadOnlyList<string>?", name: "TransitionRules" },
55926
+ { type: "string?", name: "TransitionOnTextEdit" },
55927
+ { type: "string?", name: "TransitionWhenSourceBecomes" },
55928
+ { type: "NeoSystemSettings?", name: "System" }
55929
+ ]
55930
+ },
55931
+ records: {
55932
+ NeoProjectRecordReference: {
55933
+ kind: "readonly record struct",
55934
+ catalog: true,
55935
+ parameters: [
55936
+ { type: "NeoProjectRecordKind", name: "Kind" },
55937
+ { type: "string", name: "Id" }
55938
+ ]
55939
+ },
55940
+ NeoInternalRecordRelationDefinition: {
55941
+ kind: "sealed record",
55942
+ catalog: true,
55943
+ parameters: [
55944
+ { type: "string?", name: "Id" },
55945
+ { type: "string", name: "RelationKind" },
55946
+ { type: "NeoProjectRecordReference", name: "Source" },
55947
+ { type: "NeoProjectRecordReference", name: "Target" }
55948
+ ]
55949
+ },
55950
+ NeoVector2: {
55951
+ kind: "readonly record struct",
55952
+ parameters: [
55953
+ { type: "double", name: "X" },
55954
+ { type: "double", name: "Y" }
55955
+ ]
55956
+ },
55957
+ NeoVector2Int: {
55958
+ kind: "readonly record struct",
55959
+ parameters: [
55960
+ { type: "int", name: "X" },
55961
+ { type: "int", name: "Y" }
55962
+ ]
55963
+ },
55964
+ NeoVector3: {
55965
+ kind: "readonly record struct",
55966
+ parameters: [
55967
+ { type: "double", name: "X" },
55968
+ { type: "double", name: "Y" },
55969
+ { type: "double", name: "Z" }
55970
+ ]
55971
+ },
55972
+ NeoVector3Int: {
55973
+ kind: "readonly record struct",
55974
+ parameters: [
55975
+ { type: "int", name: "X" },
55976
+ { type: "int", name: "Y" },
55977
+ { type: "int", name: "Z" }
55978
+ ]
55979
+ },
55980
+ NeoVector4: {
55981
+ kind: "readonly record struct",
55982
+ parameters: [
55983
+ { type: "double", name: "X" },
55984
+ { type: "double", name: "Y" },
55985
+ { type: "double", name: "Z" },
55986
+ { type: "double", name: "W" }
55987
+ ]
55988
+ },
55989
+ NeoColor: {
55990
+ kind: "readonly record struct",
55991
+ parameters: [
55992
+ { type: "double", name: "R" },
55993
+ { type: "double", name: "G" },
55994
+ { type: "double", name: "B" },
55995
+ { type: "double", name: "A" }
55996
+ ]
55997
+ },
55998
+ NeoSprite: {
55999
+ kind: "sealed record",
56000
+ parameters: [
56001
+ { type: "string", name: "FileId" },
56002
+ { type: "int", name: "SliceIndex" }
56003
+ ]
56004
+ },
56005
+ NeoAudio: {
56006
+ kind: "sealed record",
56007
+ parameters: [{ type: "string", name: "FileId" }]
56008
+ },
56009
+ NeoDialogue: {
56010
+ kind: "sealed record",
56011
+ parameters: [{ type: "string", name: "DialogueId" }]
56012
+ },
56013
+ "NeoLookup<T>": {
56014
+ kind: "sealed record",
56015
+ parameters: [{ type: "string", name: "ValueId" }]
56016
+ },
56017
+ NeoMemberReference: {
56018
+ kind: "readonly record struct",
56019
+ parameters: [{ type: "string", name: "Id" }]
56020
+ }
56021
+ },
56022
+ intrinsics: {
56023
+ Neo: [
56024
+ {
56025
+ typeParameters: "<T>",
56026
+ returnType: "T",
56027
+ name: "Ref",
56028
+ parameters: [{ type: "string", name: "id" }],
56029
+ expression: "default!"
56030
+ },
56031
+ {
56032
+ typeParameters: "<T>",
56033
+ returnType: "NeoLookup<T>",
56034
+ name: "Lookup",
56035
+ parameters: [{ type: "string", name: "id" }],
56036
+ expression: "new(id)"
56037
+ },
56038
+ {
56039
+ returnType: "NeoDialogue",
56040
+ name: "Dialogue",
56041
+ parameters: [{ type: "string", name: "id" }],
56042
+ expression: "new(id)"
56043
+ },
56044
+ {
56045
+ returnType: "NeoSprite",
56046
+ name: "Sprite",
56047
+ parameters: [
56048
+ { type: "string", name: "fileId" },
56049
+ { type: "int", name: "sliceIndex", default: "0" }
56050
+ ],
56051
+ expression: "new(fileId, sliceIndex)"
56052
+ },
56053
+ {
56054
+ returnType: "NeoAudio",
56055
+ name: "Audio",
56056
+ parameters: [{ type: "string", name: "fileId" }],
56057
+ expression: "new(fileId)"
56058
+ },
56059
+ {
56060
+ returnType: "NeoMemberReference",
56061
+ name: "Member",
56062
+ parameters: [{ type: "string", name: "id" }],
56063
+ expression: "new(id)"
56064
+ }
56065
+ ]
56066
+ }
56067
+ }
56068
+ }
56069
+ });
56070
+
54146
56071
  // src/project-source/workspace-status-core.ts
54147
56072
  var ANIMATION_DOCUMENT_RECORD_KINDS = [
54148
56073
  ProjectRecordKind.Project,
@@ -54454,6 +56379,16 @@ var WORLD_OBJECT_CONTRACT_WORLD_KINDS = /* @__PURE__ */ new Set([
54454
56379
  NeoWorldSystemClassKind.SpriteObject
54455
56380
  ]);
54456
56381
 
56382
+ // ../src/models/exports/unity-codegen-revision.ts
56383
+ var UNITY_CODEGEN_REVISION = "45a0847addd4616acfc29f142556dcb2e0a27daae14d6aa456430228e66dbc07";
56384
+
56385
+ // src/export-cache.ts
56386
+ var CACHE_BUILD = JSON.stringify([
56387
+ PROJECT_SCHEMA_CONTRACT.cliVersion,
56388
+ NEOSCRIPT_COMPILER_REVISION,
56389
+ UNITY_CODEGEN_REVISION
56390
+ ]);
56391
+
54457
56392
  // src/export-state.ts
54458
56393
  import { join } from "node:path";
54459
56394
  var EXPORT_STATE_FILE = join(".neo", "export.json");