@byline/richtext-lexical 2.5.0 → 2.5.2

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.
@@ -97,9 +97,15 @@ interface RunPopulateOptions {
97
97
  /**
98
98
  * Walk every supplied rich-text value, collect the union of pending
99
99
  * hydrations across all visitors, batch-fetch by source collection, and
100
- * apply. Threading `readContext` keeps the visited-set / `afterReadFired`
101
- * / read-budget machinery in sync with relation populate and user-land
102
- * `afterRead` hooks.
100
+ * apply.
101
+ *
102
+ * `readContext` is accepted (factories thread it through from
103
+ * `RichTextPopulateContext` / `RichTextEmbedContext`) but currently unused —
104
+ * the batch fetch goes straight to `getDocumentsByDocumentIds` and doesn't
105
+ * recurse into populate or `afterRead`, so there's no visited-set or
106
+ * read-budget state to share. Retained on the options shape so a future
107
+ * visitor that performs nested populate can opt back in without another
108
+ * contract churn.
103
109
  */
104
110
  export declare function runLexicalPopulate(options: RunPopulateOptions): Promise<void>;
105
111
  export {};
@@ -17,7 +17,7 @@ function* iterAllNodes(node) {
17
17
  if (Array.isArray(node.children)) for (const child of node.children)yield* iterAllNodes(child);
18
18
  }
19
19
  async function runLexicalPopulate(options) {
20
- const { client, readContext, visitors, values } = options;
20
+ const { client, visitors, values } = options;
21
21
  const pending = [];
22
22
  for (const value of values){
23
23
  const root = getLexicalRoot(value);
@@ -39,17 +39,19 @@ async function runLexicalPopulate(options) {
39
39
  const fetched = new Map();
40
40
  await Promise.all(Array.from(idsByCollection.entries()).map(async ([collectionPath, idSet])=>{
41
41
  const ids = Array.from(idSet);
42
- const result = await client.collection(collectionPath).find({
43
- where: {
44
- id: {
45
- $in: ids
46
- }
47
- },
48
- pageSize: ids.length,
49
- _readContext: readContext
42
+ const collectionId = await client.resolveCollectionId(collectionPath);
43
+ const rawDocs = await client.db.queries.documents.getDocumentsByDocumentIds({
44
+ collection_id: collectionId,
45
+ document_ids: ids,
46
+ readMode: 'published'
50
47
  });
51
48
  const byId = new Map();
52
- for (const d of result.docs)if ('string' == typeof d.id) byId.set(d.id, d);
49
+ for (const raw of rawDocs)if ('string' == typeof raw.document_id) byId.set(raw.document_id, {
50
+ id: raw.document_id,
51
+ path: raw.path,
52
+ status: raw.status,
53
+ fields: raw.fields
54
+ });
53
55
  fetched.set(collectionPath, byId);
54
56
  }));
55
57
  for (const p of pending){
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": false,
4
4
  "type": "module",
5
5
  "license": "MPL-2.0",
6
- "version": "2.5.0",
6
+ "version": "2.5.2",
7
7
  "engines": {
8
8
  "node": ">=20.9.0"
9
9
  },
@@ -72,9 +72,9 @@
72
72
  "npm-run-all": "^4.1.5",
73
73
  "prism-react-renderer": "^2.4.1",
74
74
  "react-error-boundary": "^6.1.1",
75
- "@byline/client": "2.5.0",
76
- "@byline/core": "2.5.0",
77
- "@byline/ui": "2.5.0"
75
+ "@byline/client": "2.5.2",
76
+ "@byline/core": "2.5.2",
77
+ "@byline/ui": "2.5.2"
78
78
  },
79
79
  "peerDependencies": {
80
80
  "react": "^19.0.0",
@@ -140,12 +140,18 @@ interface RunPopulateOptions {
140
140
  /**
141
141
  * Walk every supplied rich-text value, collect the union of pending
142
142
  * hydrations across all visitors, batch-fetch by source collection, and
143
- * apply. Threading `readContext` keeps the visited-set / `afterReadFired`
144
- * / read-budget machinery in sync with relation populate and user-land
145
- * `afterRead` hooks.
143
+ * apply.
144
+ *
145
+ * `readContext` is accepted (factories thread it through from
146
+ * `RichTextPopulateContext` / `RichTextEmbedContext`) but currently unused —
147
+ * the batch fetch goes straight to `getDocumentsByDocumentIds` and doesn't
148
+ * recurse into populate or `afterRead`, so there's no visited-set or
149
+ * read-budget state to share. Retained on the options shape so a future
150
+ * visitor that performs nested populate can opt back in without another
151
+ * contract churn.
146
152
  */
147
153
  export async function runLexicalPopulate(options: RunPopulateOptions): Promise<void> {
148
- const { client, readContext, visitors, values } = options
154
+ const { client, visitors, values } = options
149
155
 
150
156
  const pending: PendingHydration[] = []
151
157
  for (const value of values) {
@@ -172,18 +178,34 @@ export async function runLexicalPopulate(options: RunPopulateOptions): Promise<v
172
178
  bucket.add(p.documentId)
173
179
  }
174
180
 
181
+ // Fetch directly through the adapter rather than the client's `find()` —
182
+ // `parseWhere` has no handler for `id`, so `find({ where: { id: { $in } } })`
183
+ // silently dropped the filter and returned arbitrary docs ordered by
184
+ // `created_at desc`. This is the same primitive relation populate uses
185
+ // (`packages/core/src/services/populate.ts`) when it batches by document id.
175
186
  const fetched = new Map<string, Map<string, Record<string, any>>>()
176
187
  await Promise.all(
177
188
  Array.from(idsByCollection.entries()).map(async ([collectionPath, idSet]) => {
178
189
  const ids = Array.from(idSet)
179
- const result = await client.collection(collectionPath).find({
180
- where: { id: { $in: ids } },
181
- pageSize: ids.length,
182
- _readContext: readContext,
190
+ const collectionId = await client.resolveCollectionId(collectionPath)
191
+ const rawDocs = await client.db.queries.documents.getDocumentsByDocumentIds({
192
+ collection_id: collectionId,
193
+ document_ids: ids,
194
+ readMode: 'published',
183
195
  })
184
196
  const byId = new Map<string, Record<string, any>>()
185
- for (const d of result.docs as Array<Record<string, any>>) {
186
- if (typeof d.id === 'string') byId.set(d.id, d)
197
+ for (const raw of rawDocs as Array<Record<string, any>>) {
198
+ if (typeof raw.document_id !== 'string') continue
199
+ // Normalise the raw storage shape (`document_id` / `path` / `status` /
200
+ // `fields`) to the `{ id, path, status, fields }` shape the visitors
201
+ // expect — matches the shaped `ClientDocument` the previous `find()`
202
+ // path returned.
203
+ byId.set(raw.document_id, {
204
+ id: raw.document_id,
205
+ path: raw.path,
206
+ status: raw.status,
207
+ fields: raw.fields,
208
+ })
187
209
  }
188
210
  fetched.set(collectionPath, byId)
189
211
  })