@neocompose/cli 0.58.2 → 0.58.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.58.3] - 2026-09-24
4
+
5
+ - Joined snapshot pages carry stored JSON. Document readers decode it after the query returns, reducing query work and allowing large numeric payloads to fit in fewer requests.
6
+
7
+ - Document reads plan independent ranges before fetching payloads, with parallelism scaled to project size and deployment capacity. Pull and other document readers trade some additional reads for shorter waits; each payload page uses the available Convex limits and stays on the same published revision.
8
+
3
9
  ## [0.58.2] - 2026-09-24
4
10
 
5
11
  - Pull downloads up to eight managed image or audio files concurrently. Matching local bytes are still reused.
package/dist/neo.mjs CHANGED
@@ -86570,6 +86570,54 @@ var init_materialize_values = __esm({
86570
86570
  }
86571
86571
  });
86572
86572
 
86573
+ // ../convex/convexValues.ts
86574
+ function decodeConvexOpaqueJson(value, context) {
86575
+ if (typeof value !== "string") {
86576
+ throw new Error(`${context} must be an encoded JSON string.`);
86577
+ }
86578
+ try {
86579
+ return JSON.parse(value);
86580
+ } catch (error) {
86581
+ const message = error instanceof Error ? error.message : String(error);
86582
+ throw new Error(`${context} could not be parsed as JSON: ${message}`);
86583
+ }
86584
+ }
86585
+ var CONVEX_DOCUMENT_WARNING_BYTES, CONVEX_DOCUMENT_MAX_BYTES;
86586
+ var init_convexValues = __esm({
86587
+ "../convex/convexValues.ts"() {
86588
+ "use strict";
86589
+ CONVEX_DOCUMENT_WARNING_BYTES = 750 * 1024;
86590
+ CONVEX_DOCUMENT_MAX_BYTES = 1024 * 1024;
86591
+ }
86592
+ });
86593
+
86594
+ // ../convex/projectRecordSnapshotStorage.ts
86595
+ function decodeProjectRecordSnapshotData(snapshot, context = `Project record snapshot for ${snapshot.recordKind} "${snapshot.recordId}" dataJson`) {
86596
+ const decoded = decodeConvexOpaqueJson(snapshot.dataJson, context);
86597
+ if (!isPlainRecord(decoded)) return decoded;
86598
+ const hydratedData = { ...decoded };
86599
+ if (snapshot.recordKind === "enum" && !Object.hasOwn(hydratedData, "optionKeyOrder") && isPlainRecord(hydratedData.options)) {
86600
+ hydratedData.optionKeyOrder = Object.keys(hydratedData.options);
86601
+ }
86602
+ hydratedData.id = snapshot.recordId;
86603
+ if (snapshot.recordKind !== "project") {
86604
+ hydratedData.projectId = snapshot.projectId;
86605
+ }
86606
+ if (!Object.hasOwn(hydratedData, "updatedAt")) {
86607
+ hydratedData.updatedAt = snapshot.createdAt;
86608
+ }
86609
+ return hydratedData;
86610
+ }
86611
+ function isPlainRecord(value) {
86612
+ return typeof value === "object" && value !== null && !Array.isArray(value);
86613
+ }
86614
+ var init_projectRecordSnapshotStorage = __esm({
86615
+ "../convex/projectRecordSnapshotStorage.ts"() {
86616
+ "use strict";
86617
+ init_convexValues();
86618
+ }
86619
+ });
86620
+
86573
86621
  // ../src/database/project-read-base.ts
86574
86622
  import { ConvexError } from "convex/values";
86575
86623
  function readProjectReadBase(value) {
@@ -86887,6 +86935,7 @@ var project_document_read_exports = {};
86887
86935
  __export(project_document_read_exports, {
86888
86936
  DOCUMENT_MANIFEST_PAGE_SIZE: () => DOCUMENT_MANIFEST_PAGE_SIZE,
86889
86937
  assembleProjectDocumentRaw: () => assembleProjectDocumentRaw,
86938
+ createDocumentPageReader: () => createDocumentPageReader,
86890
86939
  fetchProjectDocumentPartitionRecords: () => fetchProjectDocumentPartitionRecords,
86891
86940
  fetchProjectDocumentRawChunked: () => fetchProjectDocumentRawChunked,
86892
86941
  fetchProjectDocumentRawChunkedOnce: () => fetchProjectDocumentRawChunkedOnce,
@@ -86944,46 +86993,14 @@ async function fetchProjectDocumentRawChunkedOnce(runner, options = {}) {
86944
86993
  };
86945
86994
  try {
86946
86995
  await rememberRecords(firstPage);
86947
- const fetchRemainingPages = async (mapKey, initialCursor) => {
86948
- let cursor = initialCursor;
86949
- while (cursor !== null) {
86950
- const pageResult = await runner.fetchPage(
86951
- {
86952
- numItems: DOCUMENT_MANIFEST_PAGE_SIZE,
86953
- cursor
86954
- },
86955
- mapKey,
86956
- readBase
86957
- );
86958
- if (pageResult === null) {
86959
- throw new Error(
86960
- "Convex project document manifest returned null for a continuation page."
86961
- );
86962
- }
86963
- const page = readProjectDocumentPage(pageResult);
86964
- assertProjectReadBase(readBase, page.readBase);
86965
- await rememberRecords(page);
86966
- cursor = page.continueCursor;
86967
- }
86968
- };
86969
- await fetchRemainingPages(firstMapKey, firstPage.continueCursor);
86970
- for (const mapKey of mapKeys.slice(1)) {
86971
- const pageResult = await runner.fetchPage(
86972
- { numItems: DOCUMENT_MANIFEST_PAGE_SIZE, cursor: null },
86973
- mapKey,
86974
- readBase,
86975
- "omit"
86976
- );
86977
- if (pageResult === null) {
86978
- throw new Error(
86979
- `Convex project document manifest returned null for partition "${mapKey ?? "all"}".`
86980
- );
86981
- }
86982
- const page = readProjectDocumentPage(pageResult);
86983
- assertProjectReadBase(readBase, page.readBase);
86984
- await rememberRecords(page);
86985
- await fetchRemainingPages(mapKey, page.continueCursor);
86986
- }
86996
+ const pages = createDocumentPageReader(runner, firstPage.readConcurrency);
86997
+ await drainDocumentReads([
86998
+ pages.remaining(firstPage, firstMapKey, readBase, rememberRecords),
86999
+ ...mapKeys.slice(1).map(async (mapKey) => {
87000
+ const page = await pages.first(mapKey, readBase, rememberRecords);
87001
+ await pages.remaining(page, mapKey, readBase, rememberRecords);
87002
+ })
87003
+ ]);
86987
87004
  const snapshotsById = await snapshots.finish();
86988
87005
  if (options.mapKeys !== void 0 && !options.mapKeys.includes("all")) {
86989
87006
  const members = [];
@@ -87043,28 +87060,15 @@ async function fetchProjectDocumentPartitionRecords(runner, mapKey, readBase) {
87043
87060
  (ids) => fetchScopedSnapshotBatch(runner, ids, readBase)
87044
87061
  );
87045
87062
  try {
87046
- let cursor = null;
87047
- do {
87048
- const pageResult = await runner.fetchPage(
87049
- { numItems: DOCUMENT_MANIFEST_PAGE_SIZE, cursor },
87050
- mapKey,
87051
- readBase,
87052
- "omit"
87053
- );
87054
- if (pageResult === null) {
87055
- throw new Error(
87056
- `Convex project document manifest returned null for partition "${mapKey}".`
87057
- );
87058
- }
87059
- const page = readProjectDocumentPage(pageResult);
87060
- assertProjectReadBase(readBase, page.readBase);
87061
- for (const record6 of page.records) {
87063
+ const pages = createDocumentPageReader(runner);
87064
+ const remember = async (page) => {
87065
+ for (const record6 of page.records)
87062
87066
  recordsByKey.set(`${record6.recordKind} ${record6.recordId}`, record6);
87063
- }
87064
87067
  if (page.snapshots !== void 0) snapshots.seed(page.snapshots);
87065
87068
  await snapshots.enqueue(page.records.map((record6) => record6.snapshotId));
87066
- cursor = page.continueCursor;
87067
- } while (cursor !== null);
87069
+ };
87070
+ const first = await pages.first(mapKey, readBase, remember);
87071
+ await pages.remaining(first, mapKey, readBase, remember);
87068
87072
  const snapshotsById = await snapshots.finish();
87069
87073
  await runner.validateReadBase(readBase);
87070
87074
  return [...recordsByKey.values()].map((record6) => {
@@ -87086,6 +87090,84 @@ async function fetchProjectDocumentPartitionRecords(runner, mapKey, readBase) {
87086
87090
  await snapshots.stop();
87087
87091
  }
87088
87092
  }
87093
+ function createDocumentPageReader(runner, concurrency) {
87094
+ let active = 0;
87095
+ let nextWaiter = 0;
87096
+ let waiters = [];
87097
+ let failure;
87098
+ const readPage = async (pagination, mapKey, readBase, remember) => {
87099
+ if (active >= (concurrency ?? 1))
87100
+ await new Promise((resolve5) => waiters.push(resolve5));
87101
+ else active++;
87102
+ try {
87103
+ if (failure !== void 0) throw failure.error;
87104
+ const raw = await runner.fetchPage(pagination, mapKey, readBase, "omit");
87105
+ if (raw === null)
87106
+ throw new Error(
87107
+ `Missing document page for partition "${mapKey ?? "all"}".`
87108
+ );
87109
+ const page = readProjectDocumentPage(raw);
87110
+ assertProjectReadBase(readBase, page.readBase);
87111
+ concurrency ??= page.readConcurrency ?? 1;
87112
+ if (pagination.cursor !== null && page.continueCursor === pagination.cursor)
87113
+ throw new Error("Document continuation made no progress.");
87114
+ if (pagination.endCursor != null && page.continueCursor === null)
87115
+ throw new Error("Document range ended before its endpoint.");
87116
+ await remember(page, pagination.cursor);
87117
+ return page;
87118
+ } catch (error) {
87119
+ failure ??= { error };
87120
+ throw error;
87121
+ } finally {
87122
+ const next = waiters[nextWaiter++];
87123
+ if (next !== void 0) next();
87124
+ else {
87125
+ active--;
87126
+ nextWaiter = 0;
87127
+ waiters = [];
87128
+ }
87129
+ }
87130
+ };
87131
+ return {
87132
+ first(mapKey, readBase, remember) {
87133
+ return readPage(
87134
+ { numItems: DOCUMENT_MANIFEST_PAGE_SIZE, cursor: null },
87135
+ mapKey,
87136
+ readBase,
87137
+ remember
87138
+ );
87139
+ },
87140
+ async remaining(first, mapKey, readBase, remember) {
87141
+ if (first.continueCursor === null) return;
87142
+ const ranges = first.remainingRanges ?? [
87143
+ { cursor: first.continueCursor, endCursor: null }
87144
+ ];
87145
+ await drainDocumentReads(
87146
+ ranges.map(async (range2) => {
87147
+ let cursor = range2.cursor;
87148
+ while (cursor !== null && cursor !== range2.endCursor) {
87149
+ const page = await readPage(
87150
+ {
87151
+ numItems: DOCUMENT_MANIFEST_PAGE_SIZE,
87152
+ cursor,
87153
+ endCursor: range2.endCursor
87154
+ },
87155
+ mapKey,
87156
+ readBase,
87157
+ remember
87158
+ );
87159
+ cursor = page.continueCursor;
87160
+ }
87161
+ })
87162
+ );
87163
+ }
87164
+ };
87165
+ }
87166
+ async function drainDocumentReads(reads) {
87167
+ const results = await Promise.allSettled(reads);
87168
+ for (const result of results)
87169
+ if (result.status === "rejected") throw result.reason;
87170
+ }
87089
87171
  async function fetchProjectDocumentValueRecords(runner, valueIds, readBase) {
87090
87172
  if (runner.fetchValueSnapshotsPage === void 0) {
87091
87173
  throw new Error(
@@ -87151,6 +87233,41 @@ function readProjectDocumentPage(value) {
87151
87233
  "Convex project document manifest page continueCursor must be a string or null."
87152
87234
  );
87153
87235
  }
87236
+ let remainingRanges;
87237
+ if (value.remainingRanges !== void 0) {
87238
+ if (!Array.isArray(value.remainingRanges))
87239
+ throw new Error("Snapshot remaining ranges must be an array.");
87240
+ remainingRanges = [];
87241
+ let expectedCursor = continueCursor;
87242
+ for (const range2 of value.remainingRanges) {
87243
+ if (!isObject4(range2))
87244
+ throw new Error("Snapshot range must be an object.");
87245
+ if (typeof range2.cursor !== "string")
87246
+ throw new Error("Snapshot range cursor must be a string.");
87247
+ if (range2.endCursor !== null && typeof range2.endCursor !== "string")
87248
+ throw new Error("Snapshot range end cursor must be a string or null.");
87249
+ if (range2.cursor !== expectedCursor)
87250
+ throw new Error("Snapshot ranges must form a contiguous continuation.");
87251
+ if (range2.cursor === range2.endCursor)
87252
+ throw new Error("Snapshot range must make progress.");
87253
+ remainingRanges.push({
87254
+ cursor: range2.cursor,
87255
+ endCursor: range2.endCursor
87256
+ });
87257
+ expectedCursor = range2.endCursor;
87258
+ }
87259
+ if (expectedCursor !== null)
87260
+ throw new Error("Snapshot ranges must cover the entire remaining tail.");
87261
+ }
87262
+ const readConcurrency = value.readConcurrency;
87263
+ if (readConcurrency !== void 0) {
87264
+ if (typeof readConcurrency !== "number")
87265
+ throw new Error("Document read concurrency must be a number.");
87266
+ if (!Number.isSafeInteger(readConcurrency))
87267
+ throw new Error("Document read concurrency must be a safe integer.");
87268
+ if (readConcurrency < 1)
87269
+ throw new Error("Document read concurrency must be positive.");
87270
+ }
87154
87271
  const metadata = value.metadata ?? null;
87155
87272
  if (metadata !== null && !isObject4(metadata)) {
87156
87273
  throw new Error(
@@ -87167,6 +87284,8 @@ function readProjectDocumentPage(value) {
87167
87284
  releaseChannels: metadata.releaseChannels,
87168
87285
  documentRevision: metadata.documentRevision
87169
87286
  },
87287
+ ...remainingRanges === void 0 ? {} : { remainingRanges },
87288
+ ...readConcurrency === void 0 ? {} : { readConcurrency },
87170
87289
  ...snapshots === void 0 ? {} : { snapshots },
87171
87290
  records: snapshots === void 0 ? readProjectDocumentManifestRecords(value.records) : snapshots.map((snapshot) => ({
87172
87291
  recordKind: snapshot.recordKind,
@@ -87220,7 +87339,21 @@ function readProjectDocumentManifestPageRecords(value) {
87220
87339
  if (!isObject4(value)) {
87221
87340
  throw new Error("Convex project document manifest page must be an object.");
87222
87341
  }
87223
- return readProjectDocumentPage(value).records;
87342
+ if (value.snapshots === void 0)
87343
+ return readProjectDocumentManifestRecords(value.records);
87344
+ if (!Array.isArray(value.snapshots))
87345
+ throw new Error("Snapshot page snapshots must be an array.");
87346
+ return readProjectDocumentManifestRecords(
87347
+ value.snapshots.map((snapshot) => {
87348
+ if (!isObject4(snapshot))
87349
+ throw new Error("Snapshot page entry must be an object.");
87350
+ return {
87351
+ recordKind: snapshot.recordKind,
87352
+ recordId: snapshot.recordId,
87353
+ snapshotId: snapshot.id
87354
+ };
87355
+ })
87356
+ );
87224
87357
  }
87225
87358
  async function fetchProjectDocumentSnapshots(fetchBatch, snapshotIds) {
87226
87359
  const loader = createProjectDocumentSnapshotLoader(fetchBatch);
@@ -87236,6 +87369,7 @@ function createProjectDocumentSnapshotLoader(fetchBatch) {
87236
87369
  const snapshotsById = /* @__PURE__ */ new Map();
87237
87370
  const active = /* @__PURE__ */ new Set();
87238
87371
  let pending = [];
87372
+ let enqueued = Promise.resolve();
87239
87373
  let stopped = false;
87240
87374
  let failure;
87241
87375
  const checkFailure = () => {
@@ -87272,17 +87406,21 @@ function createProjectDocumentSnapshotLoader(fetchBatch) {
87272
87406
  snapshotsById.set(snapshot.id, snapshot);
87273
87407
  }
87274
87408
  },
87275
- async enqueue(snapshotIds) {
87276
- checkFailure();
87277
- for (const id2 of snapshotIds) {
87278
- if (seen.has(id2)) continue;
87279
- seen.add(id2);
87280
- pending.push(id2);
87281
- if (pending.length === DOCUMENT_SNAPSHOT_FETCH_CHUNK_SIZE)
87282
- await flush();
87283
- }
87409
+ enqueue(snapshotIds) {
87410
+ enqueued = enqueued.then(async () => {
87411
+ checkFailure();
87412
+ for (const id2 of snapshotIds) {
87413
+ if (seen.has(id2)) continue;
87414
+ seen.add(id2);
87415
+ pending.push(id2);
87416
+ if (pending.length === DOCUMENT_SNAPSHOT_FETCH_CHUNK_SIZE)
87417
+ await flush();
87418
+ }
87419
+ });
87420
+ return enqueued;
87284
87421
  },
87285
87422
  async finish() {
87423
+ await enqueued;
87286
87424
  await flush();
87287
87425
  await Promise.all(active);
87288
87426
  checkFailure();
@@ -87290,6 +87428,8 @@ function createProjectDocumentSnapshotLoader(fetchBatch) {
87290
87428
  },
87291
87429
  async stop() {
87292
87430
  stopped = true;
87431
+ await enqueued.catch(() => {
87432
+ });
87293
87433
  await Promise.all(active);
87294
87434
  }
87295
87435
  };
@@ -87361,6 +87501,30 @@ function readProjectDocumentSnapshotBatch(value, requestedIds) {
87361
87501
  `Convex project record snapshot "${snapshot.id}" is missing a content hash.`
87362
87502
  );
87363
87503
  }
87504
+ let data = snapshot.data;
87505
+ if ("dataJson" in snapshot) {
87506
+ if (typeof snapshot.dataJson !== "string")
87507
+ throw new Error(`Snapshot "${snapshot.id}" dataJson must be a string.`);
87508
+ if (typeof snapshot.projectId !== "string")
87509
+ throw new Error(
87510
+ `Snapshot "${snapshot.id}" projectId must be a string.`
87511
+ );
87512
+ if (typeof snapshot.createdAt !== "number")
87513
+ throw new Error(
87514
+ `Snapshot "${snapshot.id}" createdAt must be a number.`
87515
+ );
87516
+ if (!Number.isFinite(snapshot.createdAt))
87517
+ throw new Error(
87518
+ `Snapshot "${snapshot.id}" createdAt must be finite milliseconds.`
87519
+ );
87520
+ data = decodeProjectRecordSnapshotData({
87521
+ projectId: snapshot.projectId,
87522
+ recordKind,
87523
+ recordId: snapshot.recordId,
87524
+ createdAt: snapshot.createdAt,
87525
+ dataJson: snapshot.dataJson
87526
+ });
87527
+ }
87364
87528
  return {
87365
87529
  id: snapshot.id,
87366
87530
  recordKind,
@@ -87371,7 +87535,7 @@ function readProjectDocumentSnapshotBatch(value, requestedIds) {
87371
87535
  data: readCurrentProjectRecordData({
87372
87536
  recordKind,
87373
87537
  dataSchemaVersion: snapshot.dataSchemaVersion,
87374
- data: snapshot.data
87538
+ data
87375
87539
  })
87376
87540
  };
87377
87541
  });
@@ -87693,6 +87857,7 @@ var DOCUMENT_MANIFEST_PAGE_SIZE, DOCUMENT_SNAPSHOT_FETCH_CHUNK_SIZE, DOCUMENT_SN
87693
87857
  var init_project_document_read = __esm({
87694
87858
  "../src/database/project-document-read.ts"() {
87695
87859
  "use strict";
87860
+ init_projectRecordSnapshotStorage();
87696
87861
  init_project_read_base();
87697
87862
  init_project2();
87698
87863
  init_members();
@@ -87711,7 +87876,7 @@ var init_project_document_read = __esm({
87711
87876
  init_projectRecordBuckets();
87712
87877
  init_project_record_migrations();
87713
87878
  init_member_default_reference_ids();
87714
- DOCUMENT_MANIFEST_PAGE_SIZE = 2048;
87879
+ DOCUMENT_MANIFEST_PAGE_SIZE = 8192;
87715
87880
  DOCUMENT_SNAPSHOT_FETCH_CHUNK_SIZE = 128;
87716
87881
  DOCUMENT_SNAPSHOT_FETCH_CONCURRENCY = 4;
87717
87882
  }
@@ -88394,7 +88559,7 @@ var init_commit_preparation_scope_planner = __esm({
88394
88559
 
88395
88560
  // ../src/database/project-record-semantics.ts
88396
88561
  function projectRecordSemanticData(value) {
88397
- if (!isPlainRecord(value)) return value;
88562
+ if (!isPlainRecord2(value)) return value;
88398
88563
  const semantic = {};
88399
88564
  for (const [key, child] of Object.entries(value)) {
88400
88565
  if (SERVER_MANAGED_PROJECT_RECORD_FIELDS.has(key)) continue;
@@ -88431,7 +88596,7 @@ function toCanonicalJsonValue2(value) {
88431
88596
  if (Array.isArray(value)) {
88432
88597
  return value.map((item) => toCanonicalJsonValue2(item) ?? null);
88433
88598
  }
88434
- if (!isPlainRecord(value)) {
88599
+ if (!isPlainRecord2(value)) {
88435
88600
  throw new Error("Cannot canonicalize a non-plain object.");
88436
88601
  }
88437
88602
  const canonical = {};
@@ -88445,7 +88610,7 @@ function toCanonicalJsonValue2(value) {
88445
88610
  }
88446
88611
  return canonical;
88447
88612
  }
88448
- function isPlainRecord(value) {
88613
+ function isPlainRecord2(value) {
88449
88614
  if (value === null || typeof value !== "object") return false;
88450
88615
  const prototype = Object.getPrototypeOf(value);
88451
88616
  return prototype === Object.prototype || prototype === null;
@@ -88479,7 +88644,7 @@ function stagedChangesAffectClassRelations(current, changes) {
88479
88644
  const before2 = classesById.get(change.recordId);
88480
88645
  if (before2 === void 0) return true;
88481
88646
  const after = change.nextData;
88482
- if (!isPlainRecord2(after)) return true;
88647
+ if (!isPlainRecord3(after)) return true;
88483
88648
  if (before2.extendsClassId !== after.extendsClassId) return true;
88484
88649
  continue;
88485
88650
  }
@@ -88498,11 +88663,11 @@ function valueCreateCannotAffectClassRelations(change, before) {
88498
88663
  return before === void 0;
88499
88664
  }
88500
88665
  function relationEndpointClassId(record6) {
88501
- if (!isPlainRecord2(record6)) return void 0;
88666
+ if (!isPlainRecord3(record6)) return void 0;
88502
88667
  if (typeof record6.classId === "string") return record6.classId;
88503
88668
  return void 0;
88504
88669
  }
88505
- function isPlainRecord2(value) {
88670
+ function isPlainRecord3(value) {
88506
88671
  if (value === null || typeof value !== "object") return false;
88507
88672
  return !Array.isArray(value);
88508
88673
  }
@@ -88558,7 +88723,7 @@ function assertWorldFootprintEntryTypes(document, changes) {
88558
88723
  if (change.recordKind !== "value" || change.operation === "delete" || change.deleted)
88559
88724
  continue;
88560
88725
  referencedIds2.add(change.recordId);
88561
- if (isPlainRecord3(change.nextData) && Array.isArray(change.nextData.value)) {
88726
+ if (isPlainRecord4(change.nextData) && Array.isArray(change.nextData.value)) {
88562
88727
  for (const id2 of change.nextData.value)
88563
88728
  if (typeof id2 === "string") referencedIds2.add(id2);
88564
88729
  }
@@ -88595,14 +88760,14 @@ function createdWorldPlacementIds(changes, worldKinds) {
88595
88760
  }
88596
88761
  function hasWorldPlacementBinding(value, worldKinds) {
88597
88762
  if (hasWorldPlacementSidecar(value)) return true;
88598
- if (!isPlainRecord3(value) || typeof value.containerId !== "string")
88763
+ if (!isPlainRecord4(value) || typeof value.containerId !== "string")
88599
88764
  return false;
88600
88765
  if (typeof value.classId !== "string") return false;
88601
88766
  const kind = worldKinds?.get(value.classId);
88602
88767
  return kind === NeoWorldSystemClassKind.Tile;
88603
88768
  }
88604
88769
  function hasWorldPlacementSidecar(value) {
88605
- if (!isPlainRecord3(value) || !isPlainRecord3(value.value)) return false;
88770
+ if (!isPlainRecord4(value) || !isPlainRecord4(value.value)) return false;
88606
88771
  const body = value.value;
88607
88772
  if (typeof body.assetClassId === "string") return true;
88608
88773
  if (typeof body.assetValueId === "string") return true;
@@ -88616,7 +88781,7 @@ function worldPlacementBindingChanged(before, after) {
88616
88781
  );
88617
88782
  }
88618
88783
  function worldPlacementBindingSlice(value) {
88619
- if (!isPlainRecord3(value) || !isPlainRecord3(value.value)) return null;
88784
+ if (!isPlainRecord4(value) || !isPlainRecord4(value.value)) return null;
88620
88785
  return {
88621
88786
  classId: value.classId ?? null,
88622
88787
  containerId: value.containerId ?? null,
@@ -88635,13 +88800,13 @@ function ownedSparseValueBindingChanged(before, after) {
88635
88800
  );
88636
88801
  }
88637
88802
  function ownedSparseValueBindingSlice(value) {
88638
- if (!isPlainRecord3(value)) return null;
88803
+ if (!isPlainRecord4(value)) return null;
88639
88804
  return {
88640
88805
  classId: value.classId ?? null,
88641
88806
  containerId: value.containerId ?? null
88642
88807
  };
88643
88808
  }
88644
- function isPlainRecord3(value) {
88809
+ function isPlainRecord4(value) {
88645
88810
  return typeof value === "object" && value !== null && !Array.isArray(value);
88646
88811
  }
88647
88812
  function stagedChangesRequireWorldLayerBindingValidation(current, changes) {
@@ -88657,14 +88822,14 @@ function stagedChangesRequireWorldLayerBindingValidation(current, changes) {
88657
88822
  continue;
88658
88823
  }
88659
88824
  if (change.recordKind !== "class") continue;
88660
- if (change.operation === "create" && change.deleted !== true && !classesById.has(change.recordId) && isPlainRecord3(change.nextData) && change.nextData.extendsClassId == null && change.nextData.system == null)
88825
+ if (change.operation === "create" && change.deleted !== true && !classesById.has(change.recordId) && isPlainRecord4(change.nextData) && change.nextData.extendsClassId == null && change.nextData.system == null)
88661
88826
  continue;
88662
88827
  if (change.operation !== "update") return true;
88663
88828
  if (change.deleted === true) return true;
88664
88829
  const before = classesById.get(change.recordId);
88665
88830
  if (before === void 0) return true;
88666
88831
  const after = change.nextData;
88667
- if (!isPlainRecord3(after)) return true;
88832
+ if (!isPlainRecord4(after)) return true;
88668
88833
  if (before.extendsClassId !== after.extendsClassId) return true;
88669
88834
  if (isAbstractClass(before) !== isAbstractClass(after)) return true;
88670
88835
  if (!worldClassSystemBlockIsEqual(before.system, after.system)) return true;
@@ -88686,12 +88851,12 @@ function stagedChangesRequireWorldLayerBindingValidation(current, changes) {
88686
88851
  before,
88687
88852
  change.deleted === true || change.operation === "delete" ? null : change.nextData
88688
88853
  ) ? [before, change.nextData] : []) {
88689
- if (!isPlainRecord3(row) || typeof row.containerId !== "string") continue;
88854
+ if (!isPlainRecord4(row) || typeof row.containerId !== "string") continue;
88690
88855
  for (const owner of [
88691
88856
  valuesById.get(row.containerId),
88692
88857
  changedValuesById.get(row.containerId)
88693
88858
  ]) {
88694
- if (isPlainRecord3(owner) && isPlainRecord3(owner.value) && owner.value.assetValueId === change.recordId)
88859
+ if (isPlainRecord4(owner) && isPlainRecord4(owner.value) && owner.value.assetValueId === change.recordId)
88695
88860
  return true;
88696
88861
  }
88697
88862
  }
@@ -88714,9 +88879,9 @@ function worldClassSystemBlockIsEqual(before, after) {
88714
88879
  );
88715
88880
  }
88716
88881
  function hasWorldLayerOverrideMetadata(record6) {
88717
- if (!isPlainRecord3(record6)) return false;
88882
+ if (!isPlainRecord4(record6)) return false;
88718
88883
  const value = record6.value;
88719
- if (!isPlainRecord3(value)) return false;
88884
+ if (!isPlainRecord4(value)) return false;
88720
88885
  return typeof value.layerOverrideValueId === "string";
88721
88886
  }
88722
88887
  var init_project_world_placement_bindings = __esm({
@@ -106579,7 +106744,7 @@ function systemProtectedWriteInheritedRecordId(write) {
106579
106744
  return null;
106580
106745
  if (write.deleted) return null;
106581
106746
  if (!isSystemBearingRecordKind(write.recordKind)) return null;
106582
- if (!isPlainRecord4(write.nextData)) return null;
106747
+ if (!isPlainRecord5(write.nextData)) return null;
106583
106748
  if (readSystemMetadata(write.nextData) === null) return null;
106584
106749
  const extendsMemberId = write.nextData.extendsMemberId;
106585
106750
  if (typeof extendsMemberId !== "string") return null;
@@ -106599,7 +106764,7 @@ function assertSystemProtectedRecordWriteValid(write) {
106599
106764
  assertSystemMetadataUnchanged(write, base);
106600
106765
  }
106601
106766
  function readBaseRecord(write) {
106602
- if (!isPlainRecord4(write.baseData)) return null;
106767
+ if (!isPlainRecord5(write.baseData)) return null;
106603
106768
  return {
106604
106769
  recordKind: write.recordKind,
106605
106770
  data: write.baseData,
@@ -106612,7 +106777,7 @@ function collectSystemBearingBaseRecords(document) {
106612
106777
  const stored = document[collection];
106613
106778
  if (!Array.isArray(stored)) continue;
106614
106779
  for (const record6 of stored) {
106615
- if (!isPlainRecord4(record6)) continue;
106780
+ if (!isPlainRecord5(record6)) continue;
106616
106781
  const id2 = record6.id;
106617
106782
  if (typeof id2 !== "string") continue;
106618
106783
  records2.set(baseKey(recordKind, id2), {
@@ -106626,7 +106791,7 @@ function collectSystemBearingBaseRecords(document) {
106626
106791
  }
106627
106792
  function assertCreateDeclaresNoSystemMetadata(write) {
106628
106793
  if (!isSystemBearingRecordKind(write.recordKind)) return;
106629
- if (!isPlainRecord4(write.nextData)) return;
106794
+ if (!isPlainRecord5(write.nextData)) return;
106630
106795
  const system = readSystemMetadata(write.nextData);
106631
106796
  if (system === null) return;
106632
106797
  if (inheritsLegacyEmittedSystemMetadata(write, system)) return;
@@ -106652,11 +106817,11 @@ function assertProtectedRecordNotEdited(change, base) {
106652
106817
  )) {
106653
106818
  return;
106654
106819
  }
106655
- if (!isPlainRecord4(change.nextData)) return;
106820
+ if (!isPlainRecord5(change.nextData)) return;
106656
106821
  if (authoredFieldsEqual(change.recordKind, base.data, change.nextData)) {
106657
106822
  return;
106658
106823
  }
106659
- if (isInheritedWorldDefaultEdit(change) && isPlainRecord4(change.inheritedBaseData) && change.inheritedBaseData.id === base.data.extendsMemberId && systemMetadataEqual(
106824
+ if (isInheritedWorldDefaultEdit(change) && isPlainRecord5(change.inheritedBaseData) && change.inheritedBaseData.id === base.data.extendsMemberId && systemMetadataEqual(
106660
106825
  base.system,
106661
106826
  readSystemMetadata(change.inheritedBaseData)
106662
106827
  ))
@@ -106668,7 +106833,7 @@ function assertProtectedRecordNotEdited(change, base) {
106668
106833
  function isInheritedWorldDefaultEdit(write) {
106669
106834
  if (write.recordKind !== "member" || write.recordId.startsWith("system_"))
106670
106835
  return false;
106671
- if (write.deleted || !isPlainRecord4(write.baseData) || !isPlainRecord4(write.nextData))
106836
+ if (write.deleted || !isPlainRecord5(write.baseData) || !isPlainRecord5(write.nextData))
106672
106837
  return false;
106673
106838
  if (readSystemMetadata(write.baseData)?.kind !== SystemProtectionKind.WorldAuthoring)
106674
106839
  return false;
@@ -106684,7 +106849,7 @@ function isInheritedWorldDefaultEdit(write) {
106684
106849
  );
106685
106850
  }
106686
106851
  function assertSystemMetadataUnchanged(change, base) {
106687
- if (!isPlainRecord4(change.nextData)) return;
106852
+ if (!isPlainRecord5(change.nextData)) return;
106688
106853
  const next = readSystemMetadata(change.nextData);
106689
106854
  if (systemMetadataEqual(base.system, next)) return;
106690
106855
  throw new Error(
@@ -106735,10 +106900,10 @@ function repointedChildValueIds(document, change) {
106735
106900
  );
106736
106901
  if (baseValue === void 0) return [];
106737
106902
  const before = baseValue.value;
106738
- if (!isPlainRecord4(before)) return [];
106739
- if (!isPlainRecord4(change.nextData)) return [];
106903
+ if (!isPlainRecord5(before)) return [];
106904
+ if (!isPlainRecord5(change.nextData)) return [];
106740
106905
  const after = change.nextData.value;
106741
- if (!isPlainRecord4(after)) return [];
106906
+ if (!isPlainRecord5(after)) return [];
106742
106907
  return Object.entries(before).flatMap(([schemaKey, childValueId2]) => {
106743
106908
  if (typeof childValueId2 !== "string") return [];
106744
106909
  if (after[schemaKey] === childValueId2) return [];
@@ -106773,7 +106938,7 @@ function isSystemBearingRecordKind(recordKind) {
106773
106938
  );
106774
106939
  }
106775
106940
  function readSystemMetadata(record6) {
106776
- if (!isPlainRecord4(record6)) return null;
106941
+ if (!isPlainRecord5(record6)) return null;
106777
106942
  const system = record6.system;
106778
106943
  if (!isSystemMetadata(system)) return null;
106779
106944
  return system;
@@ -106792,11 +106957,11 @@ function systemReason(system) {
106792
106957
  return SYSTEM_PROTECTION_RULES[system.kind].serverReason;
106793
106958
  }
106794
106959
  function describeChangedRecord(recordKind, recordId, record6) {
106795
- const name = isPlainRecord4(record6) ? record6.name : void 0;
106960
+ const name = isPlainRecord5(record6) ? record6.name : void 0;
106796
106961
  if (typeof name !== "string") return `Record ${recordKind} "${recordId}"`;
106797
106962
  return `Record ${recordKind} "${name}" (${recordId})`;
106798
106963
  }
106799
- function isPlainRecord4(value) {
106964
+ function isPlainRecord5(value) {
106800
106965
  return typeof value === "object" && value !== null && !Array.isArray(value);
106801
106966
  }
106802
106967
  function baseKey(recordKind, recordId) {
@@ -106927,7 +107092,7 @@ function readWorldReferenceList(args) {
106927
107092
  args.keyCandidates
106928
107093
  );
106929
107094
  if (schemaKey === null) return [];
106930
- if (!isPlainRecord5(args.ownerValue.value)) return [];
107095
+ if (!isPlainRecord6(args.ownerValue.value)) return [];
106931
107096
  const listValueId = args.ownerValue.value[schemaKey];
106932
107097
  if (typeof listValueId !== "string") return [];
106933
107098
  const listValue2 = args.graph.valuesById.get(listValueId);
@@ -106993,18 +107158,18 @@ function worldReferenceClassInherits(graph, classId, ancestorClassId) {
106993
107158
  return false;
106994
107159
  }
106995
107160
  function toWorldReferenceClassRecord(value) {
106996
- if (!isPlainRecord5(value)) return null;
107161
+ if (!isPlainRecord6(value)) return null;
106997
107162
  const id2 = stringField2(value, "id");
106998
107163
  if (id2 === null) return null;
106999
107164
  return {
107000
107165
  id: id2,
107001
107166
  extendsClassId: nullableStringField(value, "extendsClassId"),
107002
107167
  schema: isStringRecord8(value.schema) ? value.schema : void 0,
107003
- system: isPlainRecord5(value.system) ? value.system : null
107168
+ system: isPlainRecord6(value.system) ? value.system : null
107004
107169
  };
107005
107170
  }
107006
107171
  function toWorldReferenceValueRecord(value) {
107007
- if (!isPlainRecord5(value)) return null;
107172
+ if (!isPlainRecord6(value)) return null;
107008
107173
  const id2 = stringField2(value, "id");
107009
107174
  if (id2 === null) return null;
107010
107175
  return {
@@ -107018,10 +107183,10 @@ function worldReferenceValueClassId(value) {
107018
107183
  return typeof value.classId === "string" && value.classId.length > 0 ? value.classId : null;
107019
107184
  }
107020
107185
  function isStringRecord8(value) {
107021
- if (!isPlainRecord5(value)) return false;
107186
+ if (!isPlainRecord6(value)) return false;
107022
107187
  return Object.values(value).every((entry) => typeof entry === "string");
107023
107188
  }
107024
- function isPlainRecord5(value) {
107189
+ function isPlainRecord6(value) {
107025
107190
  return typeof value === "object" && value !== null && !Array.isArray(value);
107026
107191
  }
107027
107192
  function stringField2(value, key) {
@@ -107603,7 +107768,7 @@ function stagedAffectedWorldLayerLinkClassIds(args) {
107603
107768
  change.nextData
107604
107769
  ];
107605
107770
  for (const candidate of candidates) {
107606
- if (!isPlainRecord2(candidate)) continue;
107771
+ if (!isPlainRecord3(candidate)) continue;
107607
107772
  const relationKind = candidate.relationKind;
107608
107773
  if (typeof relationKind !== "string") continue;
107609
107774
  if (!isStagedWorldLayerLinkTargetRelationKind(relationKind)) continue;
@@ -107788,7 +107953,7 @@ function candidateActionListenerRowIds(projected, actions) {
107788
107953
  for (const row of projected.values) {
107789
107954
  if (storedRowActionListeners(row).length > 0) candidates.add(row.id);
107790
107955
  if (actionSchemaKeys.size === 0) continue;
107791
- if (!isPlainRecord2(row.value)) continue;
107956
+ if (!isPlainRecord3(row.value)) continue;
107792
107957
  for (const schemaKey of actionSchemaKeys) {
107793
107958
  const childId = row.value[schemaKey];
107794
107959
  if (typeof childId === "string") candidates.add(childId);
@@ -107798,7 +107963,7 @@ function candidateActionListenerRowIds(projected, actions) {
107798
107963
  }
107799
107964
  function storedRowActionListeners(row) {
107800
107965
  const body = row.value;
107801
- if (!isPlainRecord2(body)) return [];
107966
+ if (!isPlainRecord3(body)) return [];
107802
107967
  const listeners = body.listeners;
107803
107968
  return Array.isArray(listeners) ? listeners : [];
107804
107969
  }
@@ -107876,7 +108041,7 @@ function authoredActionListeners(action) {
107876
108041
  if (defaultValue === void 0 || defaultValue === null) return [];
107877
108042
  if (!isLiteralValueContent(defaultValue)) return [];
107878
108043
  const body = defaultValue.value;
107879
- if (!isPlainRecord2(body)) return [];
108044
+ if (!isPlainRecord3(body)) return [];
107880
108045
  const listeners = body.listeners;
107881
108046
  return Array.isArray(listeners) ? listeners : [];
107882
108047
  }
@@ -108238,7 +108403,7 @@ function candidateVariantRowIds(projected, variantMembers) {
108238
108403
  candidates.add(row.id);
108239
108404
  }
108240
108405
  if (schemaKeys.size === 0) continue;
108241
- if (!isPlainRecord2(row.value)) continue;
108406
+ if (!isPlainRecord3(row.value)) continue;
108242
108407
  for (const [schemaKey, childId] of Object.entries(row.value)) {
108243
108408
  if (schemaKeys.has(schemaKey) && typeof childId === "string")
108244
108409
  candidates.add(childId);
@@ -130577,27 +130742,6 @@ var init_convex = __esm({
130577
130742
  }
130578
130743
  });
130579
130744
 
130580
- // ../convex/convexValues.ts
130581
- function decodeConvexOpaqueJson(value, context) {
130582
- if (typeof value !== "string") {
130583
- throw new Error(`${context} must be an encoded JSON string.`);
130584
- }
130585
- try {
130586
- return JSON.parse(value);
130587
- } catch (error) {
130588
- const message = error instanceof Error ? error.message : String(error);
130589
- throw new Error(`${context} could not be parsed as JSON: ${message}`);
130590
- }
130591
- }
130592
- var CONVEX_DOCUMENT_WARNING_BYTES, CONVEX_DOCUMENT_MAX_BYTES;
130593
- var init_convexValues = __esm({
130594
- "../convex/convexValues.ts"() {
130595
- "use strict";
130596
- CONVEX_DOCUMENT_WARNING_BYTES = 750 * 1024;
130597
- CONVEX_DOCUMENT_MAX_BYTES = 1024 * 1024;
130598
- }
130599
- });
130600
-
130601
130745
  // ../src/database/project-version-transaction-result.ts
130602
130746
  function decodeProjectVersionTransactionResultPage(page) {
130603
130747
  const assignments = {};
@@ -140680,7 +140824,7 @@ var init_registry2 = __esm({
140680
140824
  "schema-contract/registry.mjs"() {
140681
140825
  "use strict";
140682
140826
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
140683
- cliVersion: "0.58.2",
140827
+ cliVersion: "0.58.3",
140684
140828
  projectFileUploadBatchSize: 32,
140685
140829
  documentRecords: {
140686
140830
  member: {
@@ -148501,7 +148645,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
148501
148645
  async function main() {
148502
148646
  const args = parseArgs(process.argv.slice(2));
148503
148647
  if (args.command === "--version") {
148504
- console.log("0.58.2");
148648
+ console.log("0.58.3");
148505
148649
  return;
148506
148650
  }
148507
148651
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.58.2",
3
+ "version": "0.58.3",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ description: >-
9
9
  `@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
10
10
  ---
11
11
 
12
- <!-- reviewed-through-cli: 0.58.2 -->
12
+ <!-- reviewed-through-cli: 0.58.3 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -97,7 +97,7 @@ wrappers.
97
97
  The marker near the top of `SKILL.md` must exactly match the package version:
98
98
 
99
99
  ```html
100
- <!-- reviewed-through-cli: 0.58.2 -->
100
+ <!-- reviewed-through-cli: 0.58.3 -->
101
101
  ```
102
102
 
103
103
  The quoted version above is checked too, so this instruction cannot go stale
@@ -66,8 +66,9 @@ matching local bytes. It verifies all downloads before replacing binaries or
66
66
  updating conflict artifacts. A failed transfer leaves existing files intact;
67
67
  retry the pull after resolving the reported download error.
68
68
 
69
- Pull pins every page and snapshot batch to one published generation and logical
70
- revision. If either changes during assembly, the CLI discards the attempt and
69
+ Full document pulls size pages against Convex resource limits and fetch
70
+ independent remaining ranges concurrently. Pull pins every page and snapshot
71
+ batch to one published generation and logical revision. If either changes during assembly, the CLI discards the attempt and
71
72
  restarts. Upgrade the CLI together with the P83 server read protocol.
72
73
 
73
74
  Treat `neo push --dry-run` as a full local commit rehearsal: source emission,