@stackbit/cms-core 0.6.4-develop.1 → 0.6.4-develop.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/dist/.tsbuildinfo +1 -1
- package/dist/content-store.d.ts +5 -0
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +13 -0
- package/dist/content-store.js.map +1 -1
- package/dist/utils/search-utils.d.ts.map +1 -1
- package/dist/utils/search-utils.js +50 -25
- package/dist/utils/search-utils.js.map +1 -1
- package/package.json +2 -2
- package/src/content-store.ts +24 -1
- package/src/utils/search-utils.ts +116 -64
package/src/content-store.ts
CHANGED
|
@@ -37,7 +37,8 @@ import {
|
|
|
37
37
|
isContentChangeResultEmpty,
|
|
38
38
|
contentChangeResultCounts,
|
|
39
39
|
updateOperationValueFieldWithCrossReference,
|
|
40
|
-
getErrorAtLine
|
|
40
|
+
getErrorAtLine,
|
|
41
|
+
findContentSourcesDataForTypeOrId
|
|
41
42
|
} from './content-store-utils';
|
|
42
43
|
import {
|
|
43
44
|
getSiteMapEntriesFromStackbitConfig,
|
|
@@ -1493,6 +1494,28 @@ export class ContentStore {
|
|
|
1493
1494
|
return contentSourceData.documentMap[srcDocumentId];
|
|
1494
1495
|
}
|
|
1495
1496
|
|
|
1497
|
+
getDocumentsByContext({
|
|
1498
|
+
context,
|
|
1499
|
+
srcProjectId,
|
|
1500
|
+
srcType
|
|
1501
|
+
}: {
|
|
1502
|
+
context: any;
|
|
1503
|
+
srcProjectId?: string;
|
|
1504
|
+
srcType: string;
|
|
1505
|
+
}): ContentStoreTypes.Document[] {
|
|
1506
|
+
const contentSourcesData: ContentStoreTypes.ContentSourceData[] = findContentSourcesDataForTypeOrId({
|
|
1507
|
+
contentSourceDataById: this.contentSourceDataById,
|
|
1508
|
+
srcType,
|
|
1509
|
+
srcProjectId
|
|
1510
|
+
});
|
|
1511
|
+
return _.reduce(contentSourcesData, (documents: ContentStoreTypes.Document[], csData: ContentStoreTypes.ContentSourceData) => {
|
|
1512
|
+
const matchingDocuments = _.filter(csData.csiDocuments, { context })
|
|
1513
|
+
.map((document) => csData.documentMap[document.id])
|
|
1514
|
+
.filter(Boolean);
|
|
1515
|
+
return [...documents, ...matchingDocuments] as ContentStoreTypes.Document[];
|
|
1516
|
+
}, []);
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1496
1519
|
getDocuments({ locale }: { locale?: string } = {}): ContentStoreTypes.Document[] {
|
|
1497
1520
|
return _.reduce(
|
|
1498
1521
|
this.contentSourceDataById,
|
|
@@ -11,6 +11,9 @@ const META_FIELD = {
|
|
|
11
11
|
},
|
|
12
12
|
updatedAt: {
|
|
13
13
|
type: 'date'
|
|
14
|
+
},
|
|
15
|
+
status: {
|
|
16
|
+
type: 'enum'
|
|
14
17
|
}
|
|
15
18
|
} as const;
|
|
16
19
|
|
|
@@ -27,7 +30,7 @@ export const searchDocuments = (data: {
|
|
|
27
30
|
documents: ContentStoreTypes.Document[];
|
|
28
31
|
schema: Schema;
|
|
29
32
|
locale?: string;
|
|
30
|
-
defaultLocales?: Record<string, string
|
|
33
|
+
defaultLocales?: Record<string, string>;
|
|
31
34
|
}): {
|
|
32
35
|
total: number;
|
|
33
36
|
items: ContentStoreTypes.Document[];
|
|
@@ -107,7 +110,7 @@ const isDocumentMatchesPattern = (document: ContentStoreTypes.Document, query: s
|
|
|
107
110
|
|
|
108
111
|
const getFieldForFilter = (document: ContentStoreTypes.Document, filter: SearchFilterItem): ContentStoreTypes.DocumentField => {
|
|
109
112
|
if (filter.isMeta) {
|
|
110
|
-
if (filter.field !== 'createdAt' && filter.field !== 'updatedAt') {
|
|
113
|
+
if (filter.field !== 'createdAt' && filter.field !== 'updatedAt' && filter.field !== 'status') {
|
|
111
114
|
throw new Error(`Unsupported meta field ${filter.field}`);
|
|
112
115
|
}
|
|
113
116
|
const fieldDef = META_FIELD[filter.field];
|
|
@@ -190,8 +193,10 @@ const isStringFieldMatches = ({
|
|
|
190
193
|
const fieldValue = getDocumentFieldForLocale(field, locale)?.value?.toLowerCase();
|
|
191
194
|
|
|
192
195
|
switch (filter.operator) {
|
|
193
|
-
case 'is-undefined':
|
|
194
|
-
|
|
196
|
+
case 'is-undefined':
|
|
197
|
+
return fieldValue === undefined;
|
|
198
|
+
case 'is-not-undefined':
|
|
199
|
+
return fieldValue !== undefined;
|
|
195
200
|
|
|
196
201
|
case 'eq': // ===
|
|
197
202
|
case 'neq': // !==
|
|
@@ -219,12 +224,22 @@ const isStringFieldMatches = ({
|
|
|
219
224
|
throw new Error(`Not supported operator ${filter.operator} for field ${filter.field}`);
|
|
220
225
|
};
|
|
221
226
|
|
|
222
|
-
const isNumberFieldMatches = ({
|
|
227
|
+
const isNumberFieldMatches = ({
|
|
228
|
+
field,
|
|
229
|
+
filter,
|
|
230
|
+
locale
|
|
231
|
+
}: {
|
|
232
|
+
field: ContentStoreTypes.DocumentFieldForType<'number'>;
|
|
233
|
+
filter: SearchFilterItem;
|
|
234
|
+
locale?: string;
|
|
235
|
+
}) => {
|
|
223
236
|
const fieldValue = getDocumentFieldForLocale(field, locale)?.value;
|
|
224
237
|
|
|
225
238
|
switch (filter.operator) {
|
|
226
|
-
case 'is-undefined':
|
|
227
|
-
|
|
239
|
+
case 'is-undefined':
|
|
240
|
+
return fieldValue === undefined;
|
|
241
|
+
case 'is-not-undefined':
|
|
242
|
+
return fieldValue !== undefined;
|
|
228
243
|
|
|
229
244
|
case 'eq': // ===
|
|
230
245
|
case 'neq': // !==
|
|
@@ -272,8 +287,10 @@ const isBooleanFieldMatches = ({
|
|
|
272
287
|
const fieldValue = getDocumentFieldForLocale(field, locale)?.value;
|
|
273
288
|
|
|
274
289
|
switch (filter.operator) {
|
|
275
|
-
case 'is-undefined':
|
|
276
|
-
|
|
290
|
+
case 'is-undefined':
|
|
291
|
+
return fieldValue === undefined;
|
|
292
|
+
case 'is-not-undefined':
|
|
293
|
+
return fieldValue !== undefined;
|
|
277
294
|
|
|
278
295
|
case 'eq':
|
|
279
296
|
case 'neq': {
|
|
@@ -325,8 +342,10 @@ const isDateFieldMatches = ({
|
|
|
325
342
|
}
|
|
326
343
|
|
|
327
344
|
switch (filter.operator) {
|
|
328
|
-
case 'is-undefined':
|
|
329
|
-
|
|
345
|
+
case 'is-undefined':
|
|
346
|
+
return fieldValue === undefined;
|
|
347
|
+
case 'is-not-undefined':
|
|
348
|
+
return fieldValue !== undefined;
|
|
330
349
|
|
|
331
350
|
case 'eq': // ===
|
|
332
351
|
case 'neq': // !==
|
|
@@ -345,12 +364,12 @@ const isDateFieldMatches = ({
|
|
|
345
364
|
|
|
346
365
|
switch (filter.operator) {
|
|
347
366
|
case 'eq':
|
|
348
|
-
case 'neq': {
|
|
349
|
-
|
|
367
|
+
case 'neq': {
|
|
368
|
+
// check if day is the same
|
|
369
|
+
const result =
|
|
350
370
|
fieldValue?.getFullYear() === filterValue.getFullYear() &&
|
|
351
371
|
fieldValue?.getMonth() === filterValue.getMonth() &&
|
|
352
|
-
fieldValue?.getDate() === filterValue.getDate()
|
|
353
|
-
);
|
|
372
|
+
fieldValue?.getDate() === filterValue.getDate();
|
|
354
373
|
return filter.operator === 'eq' ? result : !result;
|
|
355
374
|
}
|
|
356
375
|
|
|
@@ -380,15 +399,26 @@ const isDateFieldMatches = ({
|
|
|
380
399
|
throw new Error(`Not supported operator ${filter.operator} for field ${filter.field}`);
|
|
381
400
|
};
|
|
382
401
|
|
|
383
|
-
const isEnumFieldMatches = ({
|
|
402
|
+
const isEnumFieldMatches = ({
|
|
403
|
+
field,
|
|
404
|
+
filter,
|
|
405
|
+
locale
|
|
406
|
+
}: {
|
|
407
|
+
field: ContentStoreTypes.DocumentFieldForType<'enum'>;
|
|
408
|
+
filter: SearchFilterItem;
|
|
409
|
+
locale?: string;
|
|
410
|
+
}) => {
|
|
384
411
|
const fieldValue = getDocumentFieldForLocale(field, locale)?.value;
|
|
385
412
|
|
|
386
413
|
switch (filter.operator) {
|
|
387
|
-
case 'is-undefined':
|
|
388
|
-
|
|
414
|
+
case 'is-undefined':
|
|
415
|
+
return fieldValue === undefined;
|
|
416
|
+
case 'is-not-undefined':
|
|
417
|
+
return fieldValue !== undefined;
|
|
389
418
|
|
|
390
419
|
case 'in': // one of
|
|
391
|
-
case 'nin': {
|
|
420
|
+
case 'nin': {
|
|
421
|
+
// none of
|
|
392
422
|
const filterValues = filter.values as any[];
|
|
393
423
|
|
|
394
424
|
switch (filter.operator) {
|
|
@@ -419,7 +449,8 @@ const isListFieldMatches = ({
|
|
|
419
449
|
const fieldModel = model?.fields?.find((field) => field.name === filter.field);
|
|
420
450
|
const listItemsType = fieldModel?.type === 'list' && fieldModel.items?.type;
|
|
421
451
|
const isPrimitiveList =
|
|
422
|
-
listItemsType &&
|
|
452
|
+
listItemsType &&
|
|
453
|
+
['string', 'slug', 'url', 'text', 'markdown', 'boolean', 'date', 'datetime', 'number', 'enum', 'reference', 'cross-reference'].includes(listItemsType);
|
|
423
454
|
if (!isPrimitiveList) {
|
|
424
455
|
throw new Error(`Unsupported filter for list field ${filter.field} with children ${listItemsType}`);
|
|
425
456
|
}
|
|
@@ -427,50 +458,60 @@ const isListFieldMatches = ({
|
|
|
427
458
|
const localizedField = getDocumentFieldForLocale(field, locale);
|
|
428
459
|
|
|
429
460
|
switch (filter.operator) {
|
|
430
|
-
case 'is-empty':
|
|
431
|
-
|
|
461
|
+
case 'is-empty':
|
|
462
|
+
return (localizedField?.items.length ?? 0) === 0;
|
|
463
|
+
case 'is-not-empty':
|
|
464
|
+
return (localizedField?.items.length ?? 0) > 0;
|
|
432
465
|
|
|
433
466
|
case 'in': // one of
|
|
434
467
|
case 'nin': // none of
|
|
435
|
-
case 'all': {
|
|
468
|
+
case 'all': {
|
|
469
|
+
// all of
|
|
436
470
|
const filterValues = filter.values as any[];
|
|
437
471
|
|
|
438
472
|
switch (filter.operator) {
|
|
439
473
|
case 'in':
|
|
440
474
|
case 'nin':
|
|
441
|
-
const result =
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
case 'reference':
|
|
457
|
-
case 'cross-reference': {
|
|
458
|
-
if (item.isUnset) {
|
|
459
|
-
// include unset items for nin operator and not for in
|
|
460
|
-
return false;
|
|
475
|
+
const result =
|
|
476
|
+
localizedField?.items.some((item) => {
|
|
477
|
+
switch (item.type) {
|
|
478
|
+
case 'string':
|
|
479
|
+
case 'slug':
|
|
480
|
+
case 'url':
|
|
481
|
+
case 'text':
|
|
482
|
+
case 'markdown':
|
|
483
|
+
case 'boolean':
|
|
484
|
+
case 'date':
|
|
485
|
+
case 'datetime':
|
|
486
|
+
case 'number':
|
|
487
|
+
case 'enum': {
|
|
488
|
+
return filterValues.includes(item.value);
|
|
461
489
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
490
|
+
|
|
491
|
+
case 'reference':
|
|
492
|
+
case 'cross-reference': {
|
|
493
|
+
if (item.isUnset) {
|
|
494
|
+
// include unset items for nin operator and not for in
|
|
495
|
+
return false;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
let { srcType, srcProjectId } = document;
|
|
499
|
+
if (item.type === 'cross-reference') {
|
|
500
|
+
srcType = item.refSrcType;
|
|
501
|
+
srcProjectId = item.refProjectId;
|
|
502
|
+
}
|
|
503
|
+
return filterValues.find(
|
|
504
|
+
(filterObject) =>
|
|
505
|
+
filterObject.srcType === srcType &&
|
|
506
|
+
filterObject.srcProjectId === srcProjectId &&
|
|
507
|
+
filterObject.srcDocumentId === item.refId
|
|
508
|
+
);
|
|
467
509
|
}
|
|
468
|
-
return filterValues.find((filterObject) => filterObject.srcType === srcType && filterObject.srcProjectId === srcProjectId && filterObject.srcDocumentId === item.refId);
|
|
469
|
-
}
|
|
470
510
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
511
|
+
default:
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
}) ?? false;
|
|
474
515
|
return filter.operator === 'in' ? result : !result;
|
|
475
516
|
case 'all':
|
|
476
517
|
return filterValues.every((filterValue) => {
|
|
@@ -484,27 +525,30 @@ const isListFieldMatches = ({
|
|
|
484
525
|
case 'boolean':
|
|
485
526
|
case 'date':
|
|
486
527
|
case 'datetime':
|
|
487
|
-
case 'number':
|
|
528
|
+
case 'number':
|
|
488
529
|
case 'enum': {
|
|
489
530
|
return item.value === filterValue;
|
|
490
531
|
}
|
|
491
|
-
|
|
532
|
+
|
|
492
533
|
case 'reference':
|
|
493
534
|
case 'cross-reference': {
|
|
494
535
|
if (item.isUnset) {
|
|
495
536
|
return false;
|
|
496
537
|
}
|
|
497
|
-
|
|
538
|
+
|
|
498
539
|
let { srcType, srcProjectId } = document;
|
|
499
540
|
if (item?.type === 'cross-reference') {
|
|
500
541
|
srcType = item.refSrcType;
|
|
501
542
|
srcProjectId = item.refProjectId;
|
|
502
543
|
}
|
|
503
|
-
|
|
504
|
-
return
|
|
544
|
+
|
|
545
|
+
return (
|
|
546
|
+
filterValue.srcType === srcType && filterValue.srcProjectId === srcProjectId && filterValue.srcDocumentId === item.refId
|
|
547
|
+
);
|
|
505
548
|
}
|
|
506
|
-
|
|
507
|
-
default:
|
|
549
|
+
|
|
550
|
+
default:
|
|
551
|
+
return false;
|
|
508
552
|
}
|
|
509
553
|
});
|
|
510
554
|
});
|
|
@@ -530,8 +574,10 @@ const isReferenceFieldMatches = ({
|
|
|
530
574
|
const fieldValue = getDocumentFieldForLocale(field, locale);
|
|
531
575
|
|
|
532
576
|
switch (filter.operator) {
|
|
533
|
-
case 'is-undefined':
|
|
534
|
-
|
|
577
|
+
case 'is-undefined':
|
|
578
|
+
return fieldValue?.isUnset ?? false;
|
|
579
|
+
case 'is-not-undefined':
|
|
580
|
+
return !fieldValue?.isUnset;
|
|
535
581
|
|
|
536
582
|
case 'in':
|
|
537
583
|
case 'nin': {
|
|
@@ -554,9 +600,15 @@ const isReferenceFieldMatches = ({
|
|
|
554
600
|
|
|
555
601
|
switch (filter.operator) {
|
|
556
602
|
case 'in':
|
|
557
|
-
return filterValues.some(
|
|
603
|
+
return filterValues.some(
|
|
604
|
+
(filterValue) =>
|
|
605
|
+
filterValue.srcType === srcType && filterValue.srcProjectId === srcProjectId && filterValue.srcDocumentId === fieldValue?.refId
|
|
606
|
+
);
|
|
558
607
|
case 'nin':
|
|
559
|
-
return filterValues.every(
|
|
608
|
+
return filterValues.every(
|
|
609
|
+
(filterValue) =>
|
|
610
|
+
filterValue.srcType !== srcType || filterValue.srcProjectId !== srcProjectId || filterValue.srcDocumentId !== fieldValue?.refId
|
|
611
|
+
);
|
|
560
612
|
}
|
|
561
613
|
}
|
|
562
614
|
}
|