Skip to content

Commit 32d2a69

Browse files
pubkeyclaude
andauthored
Fix populate() for array fields with ref on items (#8324)
* Fix populate() for array fields with ref on items instead of on the array RxDocument.populate() threw DOC6 for array fields when `ref` was defined on `items` instead of on the array field itself, even though createRxSchema accepts both patterns. Now populate() also checks items.ref as a fallback for array-type schema fields. https://claude.ai/code/session_012UknZ1m9tWSKkdi8nmWcqJ * Move changelog entry to orga/changelog/ per project convention The project uses individual files in orga/changelog/ instead of direct edits to CHANGELOG.md, to avoid merge conflicts across PRs. https://claude.ai/code/session_012UknZ1m9tWSKkdi8nmWcqJ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent a8be739 commit 32d2a69

3 files changed

Lines changed: 66 additions & 3 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- FIX `RxDocument.populate()` throwing `DOC6` for array fields when `ref` is defined on `items` instead of on the array field itself, even though `createRxSchema` accepts both patterns

src/rx-document.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,17 +198,22 @@ export const basePrototype = {
198198
path
199199
});
200200
}
201-
if (!schemaObj.ref) {
201+
const ref = schemaObj.ref
202+
? schemaObj.ref
203+
: (schemaObj.type === 'array' && schemaObj.items && (schemaObj.items as any).ref
204+
? (schemaObj.items as any).ref
205+
: undefined);
206+
if (!ref) {
202207
throw newRxError('DOC6', {
203208
path,
204209
schemaObj
205210
});
206211
}
207212

208-
const refCollection: RxCollection = this.collection.database.collections[schemaObj.ref];
213+
const refCollection: RxCollection = this.collection.database.collections[ref];
209214
if (!refCollection) {
210215
throw newRxError('DOC7', {
211-
ref: schemaObj.ref,
216+
ref,
212217
path,
213218
schemaObj
214219
});

test/unit/population.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,63 @@ describeParallel('population.test.js', () => {
416416
'populated array order for docB must match its ref id order'
417417
);
418418

419+
db.close();
420+
});
421+
it('populate array when ref is defined on items instead of on the array field', async () => {
422+
const db = await createRxDatabase({
423+
name: randomToken(10),
424+
storage: config.storage.getStorage(),
425+
});
426+
const cols = await db.addCollections({
427+
human: {
428+
schema: {
429+
version: 0,
430+
primaryKey: 'name',
431+
type: 'object',
432+
properties: {
433+
name: {
434+
type: 'string',
435+
maxLength: 100
436+
},
437+
friends: {
438+
type: 'array',
439+
items: {
440+
ref: 'human',
441+
type: 'string'
442+
}
443+
}
444+
}
445+
}
446+
}
447+
});
448+
const col = cols.human;
449+
450+
const friendNames = ['alice', 'bob', 'charlie'];
451+
await Promise.all(
452+
friendNames.map(name => col.insert({ name, friends: [] }))
453+
);
454+
await col.insert({
455+
name: 'protagonist',
456+
friends: friendNames
457+
});
458+
459+
const doc = await col.findOne('protagonist').exec(true);
460+
461+
// populate() must work when 'ref' is on items
462+
const friendDocs = await doc.populate('friends');
463+
assert.ok(Array.isArray(friendDocs));
464+
assert.strictEqual(friendDocs.length, 3);
465+
friendDocs.forEach((friend: any) => {
466+
assert.ok(isRxDocument(friend));
467+
});
468+
const populatedNames = friendDocs.map((d: any) => d.name);
469+
assert.deepStrictEqual(populatedNames, friendNames);
470+
471+
// pseudo-proxy _ getter must also work
472+
const friendDocs2 = await (doc as any).friends_;
473+
assert.ok(Array.isArray(friendDocs2));
474+
assert.strictEqual(friendDocs2.length, 3);
475+
419476
db.close();
420477
});
421478
});

0 commit comments

Comments
 (0)