@okf/ootils 1.6.13 → 1.6.14

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.
@@ -151,6 +151,51 @@ declare const _recursExtractBlocks: ({ data, cb, sectionStack, blockPathPrefix }
151
151
  blockPathPrefix?: string;
152
152
  }) => void;
153
153
 
154
+ /**
155
+ * Calculates all possible rollup relationships for a tag type
156
+ *
157
+ * Rollups allow indirect filtering (e.g., filter stories by topic type where stories are tagged with topics)
158
+ *
159
+ * Returns two types of possibilities:
160
+ * 1. **valuePathType**: Direct field rollups within the tag (e.g., topics.main.category)
161
+ * 2. **tagType**: Nested tag chain rollups (e.g., topics → themes → categories)
162
+ *
163
+ * Performance optimizations:
164
+ * - Caches template blocks to avoid repeated extractAllBlocksFromTpl calls
165
+ * - Limits recursion depth to MAX_DEPTH_ROLLUP_POSSIBILITIES (10 levels)
166
+ *
167
+ * @param {Object} params - Parameters object
168
+ * @param {string} params.tagType - The tag type to find rollup possibilities for (e.g., 'topics', 'districts')
169
+ * @param {Array} params.allTpls - All templates in the system
170
+ *
171
+ * @returns {Array} Array of rollup possibilities
172
+ *
173
+ * @example
174
+ * // Input:
175
+ * getRollupPossibilities({ tagType: 'topics', allTpls: [...] })
176
+ *
177
+ * // Output:
178
+ * [
179
+ * {
180
+ * rollupType: 'valuePathType',
181
+ * tagTypeCollectionToRollup: 'topics',
182
+ * valuePathInRolledUpCollection: 'main.category.value',
183
+ * filterSourceValuePath: 'main.category',
184
+ * blockValuePath: 'main.category',
185
+ * filterDisplay: 'Topic Category'
186
+ * },
187
+ * {
188
+ * rollupType: 'tagType',
189
+ * tagTypeCollectionToRollup: 'topics',
190
+ * rollupPath: ['topics', 'themes']
191
+ * }
192
+ * ]
193
+ */
194
+ declare function getRollupPossibilities({ tagType, allTpls }: {
195
+ tagType: string;
196
+ allTpls: any[];
197
+ }): any[];
198
+
154
199
  declare namespace BASE_BULLMQ_CONFIG {
155
200
  namespace PLUGIN__MAD_USERS_SYNC_QUEUE {
156
201
  let id: string;
@@ -498,4 +543,4 @@ interface GetPlatformContextContentParams {
498
543
  }
499
544
  declare const getPlatformContextContent: ({ platformConfigs_ai, }: GetPlatformContextContentParams) => string;
500
545
 
501
- export { BASE_BULLMQ_CONFIG, deleteVal, extractAllBlocksFromTpl, genTagId, getPlatformContextContent, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
546
+ export { BASE_BULLMQ_CONFIG, deleteVal, extractAllBlocksFromTpl, genTagId, getPlatformContextContent, getRollupPossibilities, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
package/dist/browser.d.ts CHANGED
@@ -151,6 +151,51 @@ declare const _recursExtractBlocks: ({ data, cb, sectionStack, blockPathPrefix }
151
151
  blockPathPrefix?: string;
152
152
  }) => void;
153
153
 
154
+ /**
155
+ * Calculates all possible rollup relationships for a tag type
156
+ *
157
+ * Rollups allow indirect filtering (e.g., filter stories by topic type where stories are tagged with topics)
158
+ *
159
+ * Returns two types of possibilities:
160
+ * 1. **valuePathType**: Direct field rollups within the tag (e.g., topics.main.category)
161
+ * 2. **tagType**: Nested tag chain rollups (e.g., topics → themes → categories)
162
+ *
163
+ * Performance optimizations:
164
+ * - Caches template blocks to avoid repeated extractAllBlocksFromTpl calls
165
+ * - Limits recursion depth to MAX_DEPTH_ROLLUP_POSSIBILITIES (10 levels)
166
+ *
167
+ * @param {Object} params - Parameters object
168
+ * @param {string} params.tagType - The tag type to find rollup possibilities for (e.g., 'topics', 'districts')
169
+ * @param {Array} params.allTpls - All templates in the system
170
+ *
171
+ * @returns {Array} Array of rollup possibilities
172
+ *
173
+ * @example
174
+ * // Input:
175
+ * getRollupPossibilities({ tagType: 'topics', allTpls: [...] })
176
+ *
177
+ * // Output:
178
+ * [
179
+ * {
180
+ * rollupType: 'valuePathType',
181
+ * tagTypeCollectionToRollup: 'topics',
182
+ * valuePathInRolledUpCollection: 'main.category.value',
183
+ * filterSourceValuePath: 'main.category',
184
+ * blockValuePath: 'main.category',
185
+ * filterDisplay: 'Topic Category'
186
+ * },
187
+ * {
188
+ * rollupType: 'tagType',
189
+ * tagTypeCollectionToRollup: 'topics',
190
+ * rollupPath: ['topics', 'themes']
191
+ * }
192
+ * ]
193
+ */
194
+ declare function getRollupPossibilities({ tagType, allTpls }: {
195
+ tagType: string;
196
+ allTpls: any[];
197
+ }): any[];
198
+
154
199
  declare namespace BASE_BULLMQ_CONFIG {
155
200
  namespace PLUGIN__MAD_USERS_SYNC_QUEUE {
156
201
  let id: string;
@@ -498,4 +543,4 @@ interface GetPlatformContextContentParams {
498
543
  }
499
544
  declare const getPlatformContextContent: ({ platformConfigs_ai, }: GetPlatformContextContentParams) => string;
500
545
 
501
- export { BASE_BULLMQ_CONFIG, deleteVal, extractAllBlocksFromTpl, genTagId, getPlatformContextContent, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
546
+ export { BASE_BULLMQ_CONFIG, deleteVal, extractAllBlocksFromTpl, genTagId, getPlatformContextContent, getRollupPossibilities, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
package/dist/browser.js CHANGED
@@ -25,6 +25,7 @@ __export(browser_exports, {
25
25
  extractAllBlocksFromTpl: () => extractAllBlocksFromTpl,
26
26
  genTagId: () => genTagId,
27
27
  getPlatformContextContent: () => getPlatformContextContent,
28
+ getRollupPossibilities: () => getRollupPossibilities,
28
29
  getVal: () => getVal,
29
30
  recursivelyExtractBlocks: () => _recursExtractBlocks,
30
31
  setVal: () => setVal,
@@ -307,6 +308,85 @@ var _extractBlocksFromSomeBuilders = ({
307
308
  }
308
309
  };
309
310
 
311
+ // src/utils/getRollupPossibilities.ts
312
+ var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
313
+ function getRollupPossibilities({
314
+ tagType,
315
+ allTpls
316
+ }) {
317
+ const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
318
+ if (!thisTagTpl) return [];
319
+ const allBlocks = extractAllBlocksFromTpl({ tpl: thisTagTpl });
320
+ const templateBlocksCache = /* @__PURE__ */ new Map();
321
+ const getCachedTemplateBlocks = (templateTagType) => {
322
+ if (!templateBlocksCache.has(templateTagType)) {
323
+ const template = allTpls.find((d) => d.kp_content_type === templateTagType);
324
+ if (template) {
325
+ templateBlocksCache.set(templateTagType, extractAllBlocksFromTpl({ tpl: template }));
326
+ } else {
327
+ templateBlocksCache.set(templateTagType, []);
328
+ }
329
+ }
330
+ return templateBlocksCache.get(templateTagType);
331
+ };
332
+ const findTagChains = (startTagType, visited = [], maxDepth = 10) => {
333
+ if (visited.includes(startTagType) || visited.length >= maxDepth) {
334
+ return [];
335
+ }
336
+ const tagBlocks = getCachedTemplateBlocks(startTagType).filter(
337
+ (block) => block.valuePath?.startsWith("tags.")
338
+ );
339
+ const chains = [];
340
+ for (const block of tagBlocks) {
341
+ const nextTagType = block.props?.tagType;
342
+ if (nextTagType) {
343
+ chains.push({
344
+ rollupType: "tagType",
345
+ tagTypeCollectionToRollup: tagType,
346
+ rollupPath: [...visited, startTagType, nextTagType]
347
+ });
348
+ if (visited.length < maxDepth - 1) {
349
+ const nextChains = findTagChains(
350
+ nextTagType,
351
+ [...visited, startTagType],
352
+ maxDepth
353
+ );
354
+ chains.push(...nextChains);
355
+ }
356
+ }
357
+ }
358
+ return chains;
359
+ };
360
+ const singleLevelValuePathRollups = allBlocks.map((block) => {
361
+ if (block.props?.options?.length > 0) {
362
+ return {
363
+ rollupType: "valuePathType",
364
+ tagTypeCollectionToRollup: tagType,
365
+ // Handle both string values and object values (with .value accessor)
366
+ valuePathInRolledUpCollection: block.props?.saveValueAsString ? block.valuePath : `${block.valuePath}.value`,
367
+ filterSourceValuePath: block.valuePath,
368
+ blockValuePath: block.valuePath,
369
+ filterDisplay: block.props?.shortLabel || block.props?.label || block.valuePath
370
+ };
371
+ }
372
+ return void 0;
373
+ }).filter(Boolean);
374
+ const nestedTagRollups = allBlocks.filter((block) => block.valuePath?.startsWith("tags.")).flatMap((block) => {
375
+ const directChain = {
376
+ rollupType: "tagType",
377
+ tagTypeCollectionToRollup: tagType,
378
+ rollupPath: [tagType, block.props.tagType]
379
+ };
380
+ const deeperChains = findTagChains(
381
+ block.props?.tagType,
382
+ [tagType],
383
+ MAX_DEPTH_ROLLUP_POSSIBILITIES
384
+ );
385
+ return [directChain, ...deeperChains];
386
+ });
387
+ return [...singleLevelValuePathRollups, ...nestedTagRollups];
388
+ }
389
+
310
390
  // src/bullmq/GLOBAL_BULLMQ_CONFIG.js
311
391
  var BASE_BULLMQ_CONFIG = {
312
392
  PLUGIN__MAD_USERS_SYNC_QUEUE: {
@@ -577,6 +657,7 @@ ${v?.markdownText || ""}` : v?.markdownText || "";
577
657
  extractAllBlocksFromTpl,
578
658
  genTagId,
579
659
  getPlatformContextContent,
660
+ getRollupPossibilities,
580
661
  getVal,
581
662
  recursivelyExtractBlocks,
582
663
  setVal,
package/dist/browser.mjs CHANGED
@@ -273,6 +273,85 @@ var _extractBlocksFromSomeBuilders = ({
273
273
  }
274
274
  };
275
275
 
276
+ // src/utils/getRollupPossibilities.ts
277
+ var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
278
+ function getRollupPossibilities({
279
+ tagType,
280
+ allTpls
281
+ }) {
282
+ const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
283
+ if (!thisTagTpl) return [];
284
+ const allBlocks = extractAllBlocksFromTpl({ tpl: thisTagTpl });
285
+ const templateBlocksCache = /* @__PURE__ */ new Map();
286
+ const getCachedTemplateBlocks = (templateTagType) => {
287
+ if (!templateBlocksCache.has(templateTagType)) {
288
+ const template = allTpls.find((d) => d.kp_content_type === templateTagType);
289
+ if (template) {
290
+ templateBlocksCache.set(templateTagType, extractAllBlocksFromTpl({ tpl: template }));
291
+ } else {
292
+ templateBlocksCache.set(templateTagType, []);
293
+ }
294
+ }
295
+ return templateBlocksCache.get(templateTagType);
296
+ };
297
+ const findTagChains = (startTagType, visited = [], maxDepth = 10) => {
298
+ if (visited.includes(startTagType) || visited.length >= maxDepth) {
299
+ return [];
300
+ }
301
+ const tagBlocks = getCachedTemplateBlocks(startTagType).filter(
302
+ (block) => block.valuePath?.startsWith("tags.")
303
+ );
304
+ const chains = [];
305
+ for (const block of tagBlocks) {
306
+ const nextTagType = block.props?.tagType;
307
+ if (nextTagType) {
308
+ chains.push({
309
+ rollupType: "tagType",
310
+ tagTypeCollectionToRollup: tagType,
311
+ rollupPath: [...visited, startTagType, nextTagType]
312
+ });
313
+ if (visited.length < maxDepth - 1) {
314
+ const nextChains = findTagChains(
315
+ nextTagType,
316
+ [...visited, startTagType],
317
+ maxDepth
318
+ );
319
+ chains.push(...nextChains);
320
+ }
321
+ }
322
+ }
323
+ return chains;
324
+ };
325
+ const singleLevelValuePathRollups = allBlocks.map((block) => {
326
+ if (block.props?.options?.length > 0) {
327
+ return {
328
+ rollupType: "valuePathType",
329
+ tagTypeCollectionToRollup: tagType,
330
+ // Handle both string values and object values (with .value accessor)
331
+ valuePathInRolledUpCollection: block.props?.saveValueAsString ? block.valuePath : `${block.valuePath}.value`,
332
+ filterSourceValuePath: block.valuePath,
333
+ blockValuePath: block.valuePath,
334
+ filterDisplay: block.props?.shortLabel || block.props?.label || block.valuePath
335
+ };
336
+ }
337
+ return void 0;
338
+ }).filter(Boolean);
339
+ const nestedTagRollups = allBlocks.filter((block) => block.valuePath?.startsWith("tags.")).flatMap((block) => {
340
+ const directChain = {
341
+ rollupType: "tagType",
342
+ tagTypeCollectionToRollup: tagType,
343
+ rollupPath: [tagType, block.props.tagType]
344
+ };
345
+ const deeperChains = findTagChains(
346
+ block.props?.tagType,
347
+ [tagType],
348
+ MAX_DEPTH_ROLLUP_POSSIBILITIES
349
+ );
350
+ return [directChain, ...deeperChains];
351
+ });
352
+ return [...singleLevelValuePathRollups, ...nestedTagRollups];
353
+ }
354
+
276
355
  // src/bullmq/GLOBAL_BULLMQ_CONFIG.js
277
356
  var BASE_BULLMQ_CONFIG = {
278
357
  PLUGIN__MAD_USERS_SYNC_QUEUE: {
@@ -542,6 +621,7 @@ export {
542
621
  extractAllBlocksFromTpl,
543
622
  genTagId,
544
623
  getPlatformContextContent,
624
+ getRollupPossibilities,
545
625
  getVal,
546
626
  _recursExtractBlocks as recursivelyExtractBlocks,
547
627
  setVal,
package/dist/node.d.mts CHANGED
@@ -158,6 +158,51 @@ declare const _recursExtractBlocks: ({ data, cb, sectionStack, blockPathPrefix }
158
158
  blockPathPrefix?: string;
159
159
  }) => void;
160
160
 
161
+ /**
162
+ * Calculates all possible rollup relationships for a tag type
163
+ *
164
+ * Rollups allow indirect filtering (e.g., filter stories by topic type where stories are tagged with topics)
165
+ *
166
+ * Returns two types of possibilities:
167
+ * 1. **valuePathType**: Direct field rollups within the tag (e.g., topics.main.category)
168
+ * 2. **tagType**: Nested tag chain rollups (e.g., topics → themes → categories)
169
+ *
170
+ * Performance optimizations:
171
+ * - Caches template blocks to avoid repeated extractAllBlocksFromTpl calls
172
+ * - Limits recursion depth to MAX_DEPTH_ROLLUP_POSSIBILITIES (10 levels)
173
+ *
174
+ * @param {Object} params - Parameters object
175
+ * @param {string} params.tagType - The tag type to find rollup possibilities for (e.g., 'topics', 'districts')
176
+ * @param {Array} params.allTpls - All templates in the system
177
+ *
178
+ * @returns {Array} Array of rollup possibilities
179
+ *
180
+ * @example
181
+ * // Input:
182
+ * getRollupPossibilities({ tagType: 'topics', allTpls: [...] })
183
+ *
184
+ * // Output:
185
+ * [
186
+ * {
187
+ * rollupType: 'valuePathType',
188
+ * tagTypeCollectionToRollup: 'topics',
189
+ * valuePathInRolledUpCollection: 'main.category.value',
190
+ * filterSourceValuePath: 'main.category',
191
+ * blockValuePath: 'main.category',
192
+ * filterDisplay: 'Topic Category'
193
+ * },
194
+ * {
195
+ * rollupType: 'tagType',
196
+ * tagTypeCollectionToRollup: 'topics',
197
+ * rollupPath: ['topics', 'themes']
198
+ * }
199
+ * ]
200
+ */
201
+ declare function getRollupPossibilities({ tagType, allTpls }: {
202
+ tagType: string;
203
+ allTpls: any[];
204
+ }): any[];
205
+
161
206
  declare namespace BASE_BULLMQ_CONFIG {
162
207
  namespace PLUGIN__MAD_USERS_SYNC_QUEUE {
163
208
  let id: string;
@@ -1030,4 +1075,4 @@ declare function GET_GLOBAL_BULLMQ_CONFIG({ env, redisCredentials }: {
1030
1075
  };
1031
1076
  }): Object;
1032
1077
 
1033
- export { AIChatSchema, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, ElasticSearchConnector, GET_GLOBAL_BULLMQ_CONFIG, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, TplSchema, WorkerManager, deleteVal, extractAllBlocksFromTpl, genTagId, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getTplModelByTenant, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
1078
+ export { AIChatSchema, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, ElasticSearchConnector, GET_GLOBAL_BULLMQ_CONFIG, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, TplSchema, WorkerManager, deleteVal, extractAllBlocksFromTpl, genTagId, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getTplModelByTenant, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
package/dist/node.d.ts CHANGED
@@ -158,6 +158,51 @@ declare const _recursExtractBlocks: ({ data, cb, sectionStack, blockPathPrefix }
158
158
  blockPathPrefix?: string;
159
159
  }) => void;
160
160
 
161
+ /**
162
+ * Calculates all possible rollup relationships for a tag type
163
+ *
164
+ * Rollups allow indirect filtering (e.g., filter stories by topic type where stories are tagged with topics)
165
+ *
166
+ * Returns two types of possibilities:
167
+ * 1. **valuePathType**: Direct field rollups within the tag (e.g., topics.main.category)
168
+ * 2. **tagType**: Nested tag chain rollups (e.g., topics → themes → categories)
169
+ *
170
+ * Performance optimizations:
171
+ * - Caches template blocks to avoid repeated extractAllBlocksFromTpl calls
172
+ * - Limits recursion depth to MAX_DEPTH_ROLLUP_POSSIBILITIES (10 levels)
173
+ *
174
+ * @param {Object} params - Parameters object
175
+ * @param {string} params.tagType - The tag type to find rollup possibilities for (e.g., 'topics', 'districts')
176
+ * @param {Array} params.allTpls - All templates in the system
177
+ *
178
+ * @returns {Array} Array of rollup possibilities
179
+ *
180
+ * @example
181
+ * // Input:
182
+ * getRollupPossibilities({ tagType: 'topics', allTpls: [...] })
183
+ *
184
+ * // Output:
185
+ * [
186
+ * {
187
+ * rollupType: 'valuePathType',
188
+ * tagTypeCollectionToRollup: 'topics',
189
+ * valuePathInRolledUpCollection: 'main.category.value',
190
+ * filterSourceValuePath: 'main.category',
191
+ * blockValuePath: 'main.category',
192
+ * filterDisplay: 'Topic Category'
193
+ * },
194
+ * {
195
+ * rollupType: 'tagType',
196
+ * tagTypeCollectionToRollup: 'topics',
197
+ * rollupPath: ['topics', 'themes']
198
+ * }
199
+ * ]
200
+ */
201
+ declare function getRollupPossibilities({ tagType, allTpls }: {
202
+ tagType: string;
203
+ allTpls: any[];
204
+ }): any[];
205
+
161
206
  declare namespace BASE_BULLMQ_CONFIG {
162
207
  namespace PLUGIN__MAD_USERS_SYNC_QUEUE {
163
208
  let id: string;
@@ -1030,4 +1075,4 @@ declare function GET_GLOBAL_BULLMQ_CONFIG({ env, redisCredentials }: {
1030
1075
  };
1031
1076
  }): Object;
1032
1077
 
1033
- export { AIChatSchema, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, ElasticSearchConnector, GET_GLOBAL_BULLMQ_CONFIG, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, TplSchema, WorkerManager, deleteVal, extractAllBlocksFromTpl, genTagId, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getTplModelByTenant, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
1078
+ export { AIChatSchema, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, ElasticSearchConnector, GET_GLOBAL_BULLMQ_CONFIG, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, TplSchema, WorkerManager, deleteVal, extractAllBlocksFromTpl, genTagId, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getTplModelByTenant, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
package/dist/node.js CHANGED
@@ -1390,6 +1390,7 @@ __export(node_exports, {
1390
1390
  getModelByTenant: () => import_getModelByTenant2.getModelByTenant,
1391
1391
  getPlatformConfigsModelByTenant: () => import_getModelByTenant2.getPlatformConfigsModelByTenant,
1392
1392
  getPlatformContextContent: () => getPlatformContextContent,
1393
+ getRollupPossibilities: () => getRollupPossibilities,
1393
1394
  getTplModelByTenant: () => import_getModelByTenant2.getTplModelByTenant,
1394
1395
  getVal: () => getVal,
1395
1396
  recursivelyExtractBlocks: () => _recursExtractBlocks,
@@ -1673,6 +1674,85 @@ var _extractBlocksFromSomeBuilders = ({
1673
1674
  }
1674
1675
  };
1675
1676
 
1677
+ // src/utils/getRollupPossibilities.ts
1678
+ var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
1679
+ function getRollupPossibilities({
1680
+ tagType,
1681
+ allTpls
1682
+ }) {
1683
+ const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
1684
+ if (!thisTagTpl) return [];
1685
+ const allBlocks = extractAllBlocksFromTpl({ tpl: thisTagTpl });
1686
+ const templateBlocksCache = /* @__PURE__ */ new Map();
1687
+ const getCachedTemplateBlocks = (templateTagType) => {
1688
+ if (!templateBlocksCache.has(templateTagType)) {
1689
+ const template = allTpls.find((d) => d.kp_content_type === templateTagType);
1690
+ if (template) {
1691
+ templateBlocksCache.set(templateTagType, extractAllBlocksFromTpl({ tpl: template }));
1692
+ } else {
1693
+ templateBlocksCache.set(templateTagType, []);
1694
+ }
1695
+ }
1696
+ return templateBlocksCache.get(templateTagType);
1697
+ };
1698
+ const findTagChains = (startTagType, visited = [], maxDepth = 10) => {
1699
+ if (visited.includes(startTagType) || visited.length >= maxDepth) {
1700
+ return [];
1701
+ }
1702
+ const tagBlocks = getCachedTemplateBlocks(startTagType).filter(
1703
+ (block) => block.valuePath?.startsWith("tags.")
1704
+ );
1705
+ const chains = [];
1706
+ for (const block of tagBlocks) {
1707
+ const nextTagType = block.props?.tagType;
1708
+ if (nextTagType) {
1709
+ chains.push({
1710
+ rollupType: "tagType",
1711
+ tagTypeCollectionToRollup: tagType,
1712
+ rollupPath: [...visited, startTagType, nextTagType]
1713
+ });
1714
+ if (visited.length < maxDepth - 1) {
1715
+ const nextChains = findTagChains(
1716
+ nextTagType,
1717
+ [...visited, startTagType],
1718
+ maxDepth
1719
+ );
1720
+ chains.push(...nextChains);
1721
+ }
1722
+ }
1723
+ }
1724
+ return chains;
1725
+ };
1726
+ const singleLevelValuePathRollups = allBlocks.map((block) => {
1727
+ if (block.props?.options?.length > 0) {
1728
+ return {
1729
+ rollupType: "valuePathType",
1730
+ tagTypeCollectionToRollup: tagType,
1731
+ // Handle both string values and object values (with .value accessor)
1732
+ valuePathInRolledUpCollection: block.props?.saveValueAsString ? block.valuePath : `${block.valuePath}.value`,
1733
+ filterSourceValuePath: block.valuePath,
1734
+ blockValuePath: block.valuePath,
1735
+ filterDisplay: block.props?.shortLabel || block.props?.label || block.valuePath
1736
+ };
1737
+ }
1738
+ return void 0;
1739
+ }).filter(Boolean);
1740
+ const nestedTagRollups = allBlocks.filter((block) => block.valuePath?.startsWith("tags.")).flatMap((block) => {
1741
+ const directChain = {
1742
+ rollupType: "tagType",
1743
+ tagTypeCollectionToRollup: tagType,
1744
+ rollupPath: [tagType, block.props.tagType]
1745
+ };
1746
+ const deeperChains = findTagChains(
1747
+ block.props?.tagType,
1748
+ [tagType],
1749
+ MAX_DEPTH_ROLLUP_POSSIBILITIES
1750
+ );
1751
+ return [directChain, ...deeperChains];
1752
+ });
1753
+ return [...singleLevelValuePathRollups, ...nestedTagRollups];
1754
+ }
1755
+
1676
1756
  // src/universal.ts
1677
1757
  init_GLOBAL_BULLMQ_CONFIG();
1678
1758
 
@@ -2048,6 +2128,7 @@ var import_GET_GLOBAL_BULLMQ_CONFIG = __toESM(require_GET_GLOBAL_BULLMQ_CONFIG()
2048
2128
  getModelByTenant,
2049
2129
  getPlatformConfigsModelByTenant,
2050
2130
  getPlatformContextContent,
2131
+ getRollupPossibilities,
2051
2132
  getTplModelByTenant,
2052
2133
  getVal,
2053
2134
  recursivelyExtractBlocks,
package/dist/node.mjs CHANGED
@@ -1645,6 +1645,85 @@ var _extractBlocksFromSomeBuilders = ({
1645
1645
  }
1646
1646
  };
1647
1647
 
1648
+ // src/utils/getRollupPossibilities.ts
1649
+ var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
1650
+ function getRollupPossibilities({
1651
+ tagType,
1652
+ allTpls
1653
+ }) {
1654
+ const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
1655
+ if (!thisTagTpl) return [];
1656
+ const allBlocks = extractAllBlocksFromTpl({ tpl: thisTagTpl });
1657
+ const templateBlocksCache = /* @__PURE__ */ new Map();
1658
+ const getCachedTemplateBlocks = (templateTagType) => {
1659
+ if (!templateBlocksCache.has(templateTagType)) {
1660
+ const template = allTpls.find((d) => d.kp_content_type === templateTagType);
1661
+ if (template) {
1662
+ templateBlocksCache.set(templateTagType, extractAllBlocksFromTpl({ tpl: template }));
1663
+ } else {
1664
+ templateBlocksCache.set(templateTagType, []);
1665
+ }
1666
+ }
1667
+ return templateBlocksCache.get(templateTagType);
1668
+ };
1669
+ const findTagChains = (startTagType, visited = [], maxDepth = 10) => {
1670
+ if (visited.includes(startTagType) || visited.length >= maxDepth) {
1671
+ return [];
1672
+ }
1673
+ const tagBlocks = getCachedTemplateBlocks(startTagType).filter(
1674
+ (block) => block.valuePath?.startsWith("tags.")
1675
+ );
1676
+ const chains = [];
1677
+ for (const block of tagBlocks) {
1678
+ const nextTagType = block.props?.tagType;
1679
+ if (nextTagType) {
1680
+ chains.push({
1681
+ rollupType: "tagType",
1682
+ tagTypeCollectionToRollup: tagType,
1683
+ rollupPath: [...visited, startTagType, nextTagType]
1684
+ });
1685
+ if (visited.length < maxDepth - 1) {
1686
+ const nextChains = findTagChains(
1687
+ nextTagType,
1688
+ [...visited, startTagType],
1689
+ maxDepth
1690
+ );
1691
+ chains.push(...nextChains);
1692
+ }
1693
+ }
1694
+ }
1695
+ return chains;
1696
+ };
1697
+ const singleLevelValuePathRollups = allBlocks.map((block) => {
1698
+ if (block.props?.options?.length > 0) {
1699
+ return {
1700
+ rollupType: "valuePathType",
1701
+ tagTypeCollectionToRollup: tagType,
1702
+ // Handle both string values and object values (with .value accessor)
1703
+ valuePathInRolledUpCollection: block.props?.saveValueAsString ? block.valuePath : `${block.valuePath}.value`,
1704
+ filterSourceValuePath: block.valuePath,
1705
+ blockValuePath: block.valuePath,
1706
+ filterDisplay: block.props?.shortLabel || block.props?.label || block.valuePath
1707
+ };
1708
+ }
1709
+ return void 0;
1710
+ }).filter(Boolean);
1711
+ const nestedTagRollups = allBlocks.filter((block) => block.valuePath?.startsWith("tags.")).flatMap((block) => {
1712
+ const directChain = {
1713
+ rollupType: "tagType",
1714
+ tagTypeCollectionToRollup: tagType,
1715
+ rollupPath: [tagType, block.props.tagType]
1716
+ };
1717
+ const deeperChains = findTagChains(
1718
+ block.props?.tagType,
1719
+ [tagType],
1720
+ MAX_DEPTH_ROLLUP_POSSIBILITIES
1721
+ );
1722
+ return [directChain, ...deeperChains];
1723
+ });
1724
+ return [...singleLevelValuePathRollups, ...nestedTagRollups];
1725
+ }
1726
+
1648
1727
  // src/universal.ts
1649
1728
  init_GLOBAL_BULLMQ_CONFIG();
1650
1729
 
@@ -2031,6 +2110,7 @@ export {
2031
2110
  export_getModelByTenant as getModelByTenant,
2032
2111
  export_getPlatformConfigsModelByTenant as getPlatformConfigsModelByTenant,
2033
2112
  getPlatformContextContent,
2113
+ getRollupPossibilities,
2034
2114
  export_getTplModelByTenant as getTplModelByTenant,
2035
2115
  getVal,
2036
2116
  _recursExtractBlocks as recursivelyExtractBlocks,
@@ -151,6 +151,51 @@ declare const _recursExtractBlocks: ({ data, cb, sectionStack, blockPathPrefix }
151
151
  blockPathPrefix?: string;
152
152
  }) => void;
153
153
 
154
+ /**
155
+ * Calculates all possible rollup relationships for a tag type
156
+ *
157
+ * Rollups allow indirect filtering (e.g., filter stories by topic type where stories are tagged with topics)
158
+ *
159
+ * Returns two types of possibilities:
160
+ * 1. **valuePathType**: Direct field rollups within the tag (e.g., topics.main.category)
161
+ * 2. **tagType**: Nested tag chain rollups (e.g., topics → themes → categories)
162
+ *
163
+ * Performance optimizations:
164
+ * - Caches template blocks to avoid repeated extractAllBlocksFromTpl calls
165
+ * - Limits recursion depth to MAX_DEPTH_ROLLUP_POSSIBILITIES (10 levels)
166
+ *
167
+ * @param {Object} params - Parameters object
168
+ * @param {string} params.tagType - The tag type to find rollup possibilities for (e.g., 'topics', 'districts')
169
+ * @param {Array} params.allTpls - All templates in the system
170
+ *
171
+ * @returns {Array} Array of rollup possibilities
172
+ *
173
+ * @example
174
+ * // Input:
175
+ * getRollupPossibilities({ tagType: 'topics', allTpls: [...] })
176
+ *
177
+ * // Output:
178
+ * [
179
+ * {
180
+ * rollupType: 'valuePathType',
181
+ * tagTypeCollectionToRollup: 'topics',
182
+ * valuePathInRolledUpCollection: 'main.category.value',
183
+ * filterSourceValuePath: 'main.category',
184
+ * blockValuePath: 'main.category',
185
+ * filterDisplay: 'Topic Category'
186
+ * },
187
+ * {
188
+ * rollupType: 'tagType',
189
+ * tagTypeCollectionToRollup: 'topics',
190
+ * rollupPath: ['topics', 'themes']
191
+ * }
192
+ * ]
193
+ */
194
+ declare function getRollupPossibilities({ tagType, allTpls }: {
195
+ tagType: string;
196
+ allTpls: any[];
197
+ }): any[];
198
+
154
199
  declare namespace BASE_BULLMQ_CONFIG {
155
200
  namespace PLUGIN__MAD_USERS_SYNC_QUEUE {
156
201
  let id: string;
@@ -498,4 +543,4 @@ interface GetPlatformContextContentParams {
498
543
  }
499
544
  declare const getPlatformContextContent: ({ platformConfigs_ai, }: GetPlatformContextContentParams) => string;
500
545
 
501
- export { BASE_BULLMQ_CONFIG, deleteVal, extractAllBlocksFromTpl, genTagId, getPlatformContextContent, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
546
+ export { BASE_BULLMQ_CONFIG, deleteVal, extractAllBlocksFromTpl, genTagId, getPlatformContextContent, getRollupPossibilities, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
@@ -151,6 +151,51 @@ declare const _recursExtractBlocks: ({ data, cb, sectionStack, blockPathPrefix }
151
151
  blockPathPrefix?: string;
152
152
  }) => void;
153
153
 
154
+ /**
155
+ * Calculates all possible rollup relationships for a tag type
156
+ *
157
+ * Rollups allow indirect filtering (e.g., filter stories by topic type where stories are tagged with topics)
158
+ *
159
+ * Returns two types of possibilities:
160
+ * 1. **valuePathType**: Direct field rollups within the tag (e.g., topics.main.category)
161
+ * 2. **tagType**: Nested tag chain rollups (e.g., topics → themes → categories)
162
+ *
163
+ * Performance optimizations:
164
+ * - Caches template blocks to avoid repeated extractAllBlocksFromTpl calls
165
+ * - Limits recursion depth to MAX_DEPTH_ROLLUP_POSSIBILITIES (10 levels)
166
+ *
167
+ * @param {Object} params - Parameters object
168
+ * @param {string} params.tagType - The tag type to find rollup possibilities for (e.g., 'topics', 'districts')
169
+ * @param {Array} params.allTpls - All templates in the system
170
+ *
171
+ * @returns {Array} Array of rollup possibilities
172
+ *
173
+ * @example
174
+ * // Input:
175
+ * getRollupPossibilities({ tagType: 'topics', allTpls: [...] })
176
+ *
177
+ * // Output:
178
+ * [
179
+ * {
180
+ * rollupType: 'valuePathType',
181
+ * tagTypeCollectionToRollup: 'topics',
182
+ * valuePathInRolledUpCollection: 'main.category.value',
183
+ * filterSourceValuePath: 'main.category',
184
+ * blockValuePath: 'main.category',
185
+ * filterDisplay: 'Topic Category'
186
+ * },
187
+ * {
188
+ * rollupType: 'tagType',
189
+ * tagTypeCollectionToRollup: 'topics',
190
+ * rollupPath: ['topics', 'themes']
191
+ * }
192
+ * ]
193
+ */
194
+ declare function getRollupPossibilities({ tagType, allTpls }: {
195
+ tagType: string;
196
+ allTpls: any[];
197
+ }): any[];
198
+
154
199
  declare namespace BASE_BULLMQ_CONFIG {
155
200
  namespace PLUGIN__MAD_USERS_SYNC_QUEUE {
156
201
  let id: string;
@@ -498,4 +543,4 @@ interface GetPlatformContextContentParams {
498
543
  }
499
544
  declare const getPlatformContextContent: ({ platformConfigs_ai, }: GetPlatformContextContentParams) => string;
500
545
 
501
- export { BASE_BULLMQ_CONFIG, deleteVal, extractAllBlocksFromTpl, genTagId, getPlatformContextContent, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
546
+ export { BASE_BULLMQ_CONFIG, deleteVal, extractAllBlocksFromTpl, genTagId, getPlatformContextContent, getRollupPossibilities, getVal, _recursExtractBlocks as recursivelyExtractBlocks, setVal, toArray };
package/dist/universal.js CHANGED
@@ -25,6 +25,7 @@ __export(universal_exports, {
25
25
  extractAllBlocksFromTpl: () => extractAllBlocksFromTpl,
26
26
  genTagId: () => genTagId,
27
27
  getPlatformContextContent: () => getPlatformContextContent,
28
+ getRollupPossibilities: () => getRollupPossibilities,
28
29
  getVal: () => getVal,
29
30
  recursivelyExtractBlocks: () => _recursExtractBlocks,
30
31
  setVal: () => setVal,
@@ -307,6 +308,85 @@ var _extractBlocksFromSomeBuilders = ({
307
308
  }
308
309
  };
309
310
 
311
+ // src/utils/getRollupPossibilities.ts
312
+ var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
313
+ function getRollupPossibilities({
314
+ tagType,
315
+ allTpls
316
+ }) {
317
+ const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
318
+ if (!thisTagTpl) return [];
319
+ const allBlocks = extractAllBlocksFromTpl({ tpl: thisTagTpl });
320
+ const templateBlocksCache = /* @__PURE__ */ new Map();
321
+ const getCachedTemplateBlocks = (templateTagType) => {
322
+ if (!templateBlocksCache.has(templateTagType)) {
323
+ const template = allTpls.find((d) => d.kp_content_type === templateTagType);
324
+ if (template) {
325
+ templateBlocksCache.set(templateTagType, extractAllBlocksFromTpl({ tpl: template }));
326
+ } else {
327
+ templateBlocksCache.set(templateTagType, []);
328
+ }
329
+ }
330
+ return templateBlocksCache.get(templateTagType);
331
+ };
332
+ const findTagChains = (startTagType, visited = [], maxDepth = 10) => {
333
+ if (visited.includes(startTagType) || visited.length >= maxDepth) {
334
+ return [];
335
+ }
336
+ const tagBlocks = getCachedTemplateBlocks(startTagType).filter(
337
+ (block) => block.valuePath?.startsWith("tags.")
338
+ );
339
+ const chains = [];
340
+ for (const block of tagBlocks) {
341
+ const nextTagType = block.props?.tagType;
342
+ if (nextTagType) {
343
+ chains.push({
344
+ rollupType: "tagType",
345
+ tagTypeCollectionToRollup: tagType,
346
+ rollupPath: [...visited, startTagType, nextTagType]
347
+ });
348
+ if (visited.length < maxDepth - 1) {
349
+ const nextChains = findTagChains(
350
+ nextTagType,
351
+ [...visited, startTagType],
352
+ maxDepth
353
+ );
354
+ chains.push(...nextChains);
355
+ }
356
+ }
357
+ }
358
+ return chains;
359
+ };
360
+ const singleLevelValuePathRollups = allBlocks.map((block) => {
361
+ if (block.props?.options?.length > 0) {
362
+ return {
363
+ rollupType: "valuePathType",
364
+ tagTypeCollectionToRollup: tagType,
365
+ // Handle both string values and object values (with .value accessor)
366
+ valuePathInRolledUpCollection: block.props?.saveValueAsString ? block.valuePath : `${block.valuePath}.value`,
367
+ filterSourceValuePath: block.valuePath,
368
+ blockValuePath: block.valuePath,
369
+ filterDisplay: block.props?.shortLabel || block.props?.label || block.valuePath
370
+ };
371
+ }
372
+ return void 0;
373
+ }).filter(Boolean);
374
+ const nestedTagRollups = allBlocks.filter((block) => block.valuePath?.startsWith("tags.")).flatMap((block) => {
375
+ const directChain = {
376
+ rollupType: "tagType",
377
+ tagTypeCollectionToRollup: tagType,
378
+ rollupPath: [tagType, block.props.tagType]
379
+ };
380
+ const deeperChains = findTagChains(
381
+ block.props?.tagType,
382
+ [tagType],
383
+ MAX_DEPTH_ROLLUP_POSSIBILITIES
384
+ );
385
+ return [directChain, ...deeperChains];
386
+ });
387
+ return [...singleLevelValuePathRollups, ...nestedTagRollups];
388
+ }
389
+
310
390
  // src/bullmq/GLOBAL_BULLMQ_CONFIG.js
311
391
  var BASE_BULLMQ_CONFIG = {
312
392
  PLUGIN__MAD_USERS_SYNC_QUEUE: {
@@ -577,6 +657,7 @@ ${v?.markdownText || ""}` : v?.markdownText || "";
577
657
  extractAllBlocksFromTpl,
578
658
  genTagId,
579
659
  getPlatformContextContent,
660
+ getRollupPossibilities,
580
661
  getVal,
581
662
  recursivelyExtractBlocks,
582
663
  setVal,
@@ -273,6 +273,85 @@ var _extractBlocksFromSomeBuilders = ({
273
273
  }
274
274
  };
275
275
 
276
+ // src/utils/getRollupPossibilities.ts
277
+ var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
278
+ function getRollupPossibilities({
279
+ tagType,
280
+ allTpls
281
+ }) {
282
+ const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
283
+ if (!thisTagTpl) return [];
284
+ const allBlocks = extractAllBlocksFromTpl({ tpl: thisTagTpl });
285
+ const templateBlocksCache = /* @__PURE__ */ new Map();
286
+ const getCachedTemplateBlocks = (templateTagType) => {
287
+ if (!templateBlocksCache.has(templateTagType)) {
288
+ const template = allTpls.find((d) => d.kp_content_type === templateTagType);
289
+ if (template) {
290
+ templateBlocksCache.set(templateTagType, extractAllBlocksFromTpl({ tpl: template }));
291
+ } else {
292
+ templateBlocksCache.set(templateTagType, []);
293
+ }
294
+ }
295
+ return templateBlocksCache.get(templateTagType);
296
+ };
297
+ const findTagChains = (startTagType, visited = [], maxDepth = 10) => {
298
+ if (visited.includes(startTagType) || visited.length >= maxDepth) {
299
+ return [];
300
+ }
301
+ const tagBlocks = getCachedTemplateBlocks(startTagType).filter(
302
+ (block) => block.valuePath?.startsWith("tags.")
303
+ );
304
+ const chains = [];
305
+ for (const block of tagBlocks) {
306
+ const nextTagType = block.props?.tagType;
307
+ if (nextTagType) {
308
+ chains.push({
309
+ rollupType: "tagType",
310
+ tagTypeCollectionToRollup: tagType,
311
+ rollupPath: [...visited, startTagType, nextTagType]
312
+ });
313
+ if (visited.length < maxDepth - 1) {
314
+ const nextChains = findTagChains(
315
+ nextTagType,
316
+ [...visited, startTagType],
317
+ maxDepth
318
+ );
319
+ chains.push(...nextChains);
320
+ }
321
+ }
322
+ }
323
+ return chains;
324
+ };
325
+ const singleLevelValuePathRollups = allBlocks.map((block) => {
326
+ if (block.props?.options?.length > 0) {
327
+ return {
328
+ rollupType: "valuePathType",
329
+ tagTypeCollectionToRollup: tagType,
330
+ // Handle both string values and object values (with .value accessor)
331
+ valuePathInRolledUpCollection: block.props?.saveValueAsString ? block.valuePath : `${block.valuePath}.value`,
332
+ filterSourceValuePath: block.valuePath,
333
+ blockValuePath: block.valuePath,
334
+ filterDisplay: block.props?.shortLabel || block.props?.label || block.valuePath
335
+ };
336
+ }
337
+ return void 0;
338
+ }).filter(Boolean);
339
+ const nestedTagRollups = allBlocks.filter((block) => block.valuePath?.startsWith("tags.")).flatMap((block) => {
340
+ const directChain = {
341
+ rollupType: "tagType",
342
+ tagTypeCollectionToRollup: tagType,
343
+ rollupPath: [tagType, block.props.tagType]
344
+ };
345
+ const deeperChains = findTagChains(
346
+ block.props?.tagType,
347
+ [tagType],
348
+ MAX_DEPTH_ROLLUP_POSSIBILITIES
349
+ );
350
+ return [directChain, ...deeperChains];
351
+ });
352
+ return [...singleLevelValuePathRollups, ...nestedTagRollups];
353
+ }
354
+
276
355
  // src/bullmq/GLOBAL_BULLMQ_CONFIG.js
277
356
  var BASE_BULLMQ_CONFIG = {
278
357
  PLUGIN__MAD_USERS_SYNC_QUEUE: {
@@ -542,6 +621,7 @@ export {
542
621
  extractAllBlocksFromTpl,
543
622
  genTagId,
544
623
  getPlatformContextContent,
624
+ getRollupPossibilities,
545
625
  getVal,
546
626
  _recursExtractBlocks as recursivelyExtractBlocks,
547
627
  setVal,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.6.13",
6
+ "version": "1.6.14",
7
7
  "description": "Utility functions for both browser and Node.js",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.mjs",