@redpanda-data/docs-extensions-and-macros 4.8.1 → 4.9.1
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/bin/doc-tools.js +334 -35
- package/package.json +1 -1
- package/tools/property-extractor/Makefile +8 -18
- package/tools/property-extractor/cloud_config.py +594 -0
- package/tools/property-extractor/compare-properties.js +378 -0
- package/tools/property-extractor/generate-handlebars-docs.js +132 -32
- package/tools/property-extractor/parser.py +27 -1
- package/tools/property-extractor/property_extractor.py +335 -99
- package/tools/property-extractor/requirements.txt +1 -0
- package/tools/property-extractor/templates/property-cloud.hbs +105 -0
- package/tools/property-extractor/templates/property.hbs +16 -1
- package/tools/property-extractor/templates/topic-property-cloud.hbs +97 -0
- package/tools/property-extractor/templates/topic-property.hbs +26 -12
- package/tools/property-extractor/transformers.py +98 -2
- package/tools/redpanda-connect/generate-rpcn-connector-docs.js +96 -2
- package/tools/redpanda-connect/helpers/bloblangExample.js +42 -0
- package/tools/redpanda-connect/helpers/index.js +4 -3
- package/tools/redpanda-connect/helpers/renderConnectFields.js +32 -5
- package/tools/redpanda-connect/report-delta.js +101 -0
- package/tools/redpanda-connect/templates/bloblang-function.hbs +28 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{{#if cloud_supported}}
|
|
2
|
+
// tag::redpanda-cloud[]
|
|
3
|
+
{{/if}}
|
|
4
|
+
=== {{name}}
|
|
5
|
+
{{#if version}}
|
|
6
|
+
|
|
7
|
+
*Introduced in {{version}}*
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if description}}
|
|
10
|
+
|
|
11
|
+
{{{description}}}
|
|
12
|
+
{{else}}
|
|
13
|
+
|
|
14
|
+
No description available.
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if is_enterprise}}
|
|
17
|
+
|
|
18
|
+
ifndef::env-cloud[]
|
|
19
|
+
*Enterprise license required*: `{{enterprise_value}}` (for license details, see xref:get-started:licensing/index.adoc[Redpanda Licensing])
|
|
20
|
+
endif::[]
|
|
21
|
+
{{/if}}
|
|
22
|
+
{{#if cloud_byoc_only}}
|
|
23
|
+
|
|
24
|
+
NOTE: This property is available only in Redpanda Cloud BYOC deployments.
|
|
25
|
+
{{/if}}
|
|
26
|
+
{{#if units}}
|
|
27
|
+
|
|
28
|
+
*Unit:* {{units}}
|
|
29
|
+
{{else}}
|
|
30
|
+
{{#if (formatUnits name)}}
|
|
31
|
+
|
|
32
|
+
*Unit:* {{formatUnits name}}
|
|
33
|
+
{{/if}}
|
|
34
|
+
{{/if}}
|
|
35
|
+
{{#if (ne defined_in "src/v/config/node_config.cc")}}
|
|
36
|
+
{{#if (ne needs_restart undefined)}}
|
|
37
|
+
|
|
38
|
+
*Requires restart:* {{#if needs_restart}}Yes{{else}}No{{/if}}
|
|
39
|
+
{{/if}}
|
|
40
|
+
{{/if}}
|
|
41
|
+
{{#if visibility}}
|
|
42
|
+
|
|
43
|
+
// tag::self-managed-only[]
|
|
44
|
+
*Visibility:* `{{visibility}}`
|
|
45
|
+
// end::self-managed-only[]
|
|
46
|
+
{{/if}}
|
|
47
|
+
{{#if type}}
|
|
48
|
+
|
|
49
|
+
*Type:* {{type}}
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if (and minimum maximum)}}
|
|
52
|
+
|
|
53
|
+
*Accepted values:* [`{{minimum}}`, `{{maximum}}`]
|
|
54
|
+
{{else}}
|
|
55
|
+
{{#if minimum}}
|
|
56
|
+
|
|
57
|
+
*Minimum value:* `{{minimum}}`
|
|
58
|
+
{{/if}}
|
|
59
|
+
{{#if maximum}}
|
|
60
|
+
|
|
61
|
+
*Maximum value:* `{{maximum}}`
|
|
62
|
+
{{/if}}
|
|
63
|
+
{{/if}}
|
|
64
|
+
{{#if (ne default undefined)}}
|
|
65
|
+
|
|
66
|
+
ifdef::env-cloud[]
|
|
67
|
+
*Default:* Available in the Redpanda Cloud Console
|
|
68
|
+
endif::[]
|
|
69
|
+
ifndef::env-cloud[]
|
|
70
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
71
|
+
endif::[]
|
|
72
|
+
{{/if}}
|
|
73
|
+
|
|
74
|
+
// tag::self-managed-only[]
|
|
75
|
+
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
76
|
+
// end::self-managed-only[]
|
|
77
|
+
{{#if example}}
|
|
78
|
+
|
|
79
|
+
{{{renderPropertyExample this}}}
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{#if related_topics}}
|
|
82
|
+
|
|
83
|
+
*Related topics:*
|
|
84
|
+
|
|
85
|
+
{{#each related_topics}}
|
|
86
|
+
* {{{this}}}
|
|
87
|
+
{{/each}}
|
|
88
|
+
{{/if}}
|
|
89
|
+
{{#if aliases}}
|
|
90
|
+
|
|
91
|
+
// tag::self-managed-only[]
|
|
92
|
+
*Aliases:* {{join aliases ", "}}
|
|
93
|
+
// end::self-managed-only[]
|
|
94
|
+
{{/if}}
|
|
95
|
+
{{#if is_deprecated}}
|
|
96
|
+
|
|
97
|
+
[WARNING]
|
|
98
|
+
====
|
|
99
|
+
This property is deprecated.
|
|
100
|
+
====
|
|
101
|
+
{{/if}}
|
|
102
|
+
---
|
|
103
|
+
{{#if cloud_supported}}
|
|
104
|
+
// end::redpanda-cloud[]
|
|
105
|
+
{{/if}}
|
|
@@ -2,14 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
{{#if version}}
|
|
4
4
|
*Introduced in {{version}}*
|
|
5
|
-
|
|
6
5
|
{{/if}}
|
|
6
|
+
|
|
7
7
|
{{#if description}}
|
|
8
8
|
{{{description}}}
|
|
9
9
|
{{else}}
|
|
10
10
|
No description available.
|
|
11
11
|
{{/if}}
|
|
12
12
|
|
|
13
|
+
{{#if is_enterprise}}
|
|
14
|
+
ifndef::env-cloud[]
|
|
15
|
+
*Enterprise license required*: `{{enterprise_value}}` (for license details, see xref:get-started:licensing/index.adoc[Redpanda Licensing])
|
|
16
|
+
endif::[]
|
|
17
|
+
|
|
18
|
+
{{/if}}
|
|
19
|
+
|
|
13
20
|
{{#if units}}
|
|
14
21
|
*Unit:* {{units}}
|
|
15
22
|
|
|
@@ -56,6 +63,14 @@ No description available.
|
|
|
56
63
|
{{{renderPropertyExample this}}}
|
|
57
64
|
{{/if}}
|
|
58
65
|
|
|
66
|
+
{{#if related_topics}}
|
|
67
|
+
*Related topics:*
|
|
68
|
+
|
|
69
|
+
{{#each related_topics}}
|
|
70
|
+
* {{{this}}}
|
|
71
|
+
{{/each}}
|
|
72
|
+
{{/if}}
|
|
73
|
+
|
|
59
74
|
{{#if aliases}}
|
|
60
75
|
*Aliases:* {{join aliases ", "}}
|
|
61
76
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{{#if cloud_supported}}
|
|
2
|
+
// tag::redpanda-cloud[]
|
|
3
|
+
{{/if}}
|
|
4
|
+
=== {{name}}
|
|
5
|
+
{{#if version}}
|
|
6
|
+
|
|
7
|
+
*Introduced in {{version}}*
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if description}}
|
|
10
|
+
|
|
11
|
+
{{{description}}}
|
|
12
|
+
{{else}}
|
|
13
|
+
|
|
14
|
+
No description available.
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if is_enterprise}}
|
|
17
|
+
|
|
18
|
+
ifndef::env-cloud[]
|
|
19
|
+
*Enterprise license required*: `{{enterprise_value}}` (for license details, see xref:get-started:licensing/index.adoc[Redpanda Licensing])
|
|
20
|
+
endif::[]
|
|
21
|
+
{{/if}}
|
|
22
|
+
{{#if cloud_byoc_only}}
|
|
23
|
+
|
|
24
|
+
NOTE: This property is only available in Redpanda Cloud BYOC deployments.
|
|
25
|
+
{{/if}}
|
|
26
|
+
{{#if type}}
|
|
27
|
+
|
|
28
|
+
*Type:* {{type}}
|
|
29
|
+
{{/if}}
|
|
30
|
+
{{#if acceptable_values}}
|
|
31
|
+
|
|
32
|
+
*Accepted values:* {{{acceptable_values}}}
|
|
33
|
+
{{/if}}
|
|
34
|
+
{{#if corresponding_cluster_property}}
|
|
35
|
+
|
|
36
|
+
*Related cluster property:* xref:reference:cluster-properties.adoc#{{corresponding_cluster_property}}[{{corresponding_cluster_property}}]
|
|
37
|
+
{{/if}}
|
|
38
|
+
{{#if (and minimum maximum)}}
|
|
39
|
+
|
|
40
|
+
*Accepted values:* [`{{minimum}}`, `{{maximum}}`]
|
|
41
|
+
{{else}}
|
|
42
|
+
{{#if minimum}}
|
|
43
|
+
|
|
44
|
+
*Minimum value:* `{{minimum}}`
|
|
45
|
+
{{/if}}
|
|
46
|
+
{{#if maximum}}
|
|
47
|
+
|
|
48
|
+
*Maximum value:* `{{maximum}}`
|
|
49
|
+
{{/if}}
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if (ne default undefined)}}
|
|
52
|
+
{{#if cloud_supported}}
|
|
53
|
+
|
|
54
|
+
ifdef::env-cloud[]
|
|
55
|
+
*Default:* Available in the Redpanda Cloud Console
|
|
56
|
+
endif::[]
|
|
57
|
+
ifndef::env-cloud[]
|
|
58
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
59
|
+
endif::[]
|
|
60
|
+
{{else}}
|
|
61
|
+
|
|
62
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
63
|
+
{{/if}}
|
|
64
|
+
{{/if}}
|
|
65
|
+
|
|
66
|
+
// tag::self-managed-only[]
|
|
67
|
+
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
68
|
+
// end::self-managed-only[]
|
|
69
|
+
{{#if example}}
|
|
70
|
+
|
|
71
|
+
{{{renderPropertyExample this}}}
|
|
72
|
+
{{/if}}
|
|
73
|
+
{{#if related_topics}}
|
|
74
|
+
|
|
75
|
+
*Related topics:*
|
|
76
|
+
|
|
77
|
+
{{#each related_topics}}
|
|
78
|
+
* {{{this}}}
|
|
79
|
+
{{/each}}
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{#if aliases}}
|
|
82
|
+
|
|
83
|
+
// tag::self-managed-only[]
|
|
84
|
+
*Aliases:* {{join aliases ", "}}
|
|
85
|
+
// end::self-managed-only[]
|
|
86
|
+
{{/if}}
|
|
87
|
+
{{#if is_deprecated}}
|
|
88
|
+
|
|
89
|
+
[WARNING]
|
|
90
|
+
====
|
|
91
|
+
This property is deprecated.
|
|
92
|
+
====
|
|
93
|
+
{{/if}}
|
|
94
|
+
---
|
|
95
|
+
{{#if cloud_supported}}
|
|
96
|
+
// end::redpanda-cloud[]
|
|
97
|
+
{{/if}}
|
|
@@ -1,59 +1,73 @@
|
|
|
1
1
|
=== {{name}}
|
|
2
|
-
|
|
3
2
|
{{#if version}}
|
|
4
|
-
*Introduced in {{version}}*
|
|
5
3
|
|
|
4
|
+
*Introduced in {{version}}*
|
|
6
5
|
{{/if}}
|
|
7
6
|
{{#if description}}
|
|
7
|
+
|
|
8
8
|
{{{description}}}
|
|
9
9
|
{{else}}
|
|
10
|
+
|
|
10
11
|
No description available.
|
|
11
12
|
{{/if}}
|
|
13
|
+
{{#if is_enterprise}}
|
|
12
14
|
|
|
15
|
+
ifndef::env-cloud[]
|
|
16
|
+
*Enterprise license required*: `{{enterprise_value}}` (for license details, see xref:get-started:licensing/index.adoc[Redpanda Licensing])
|
|
17
|
+
endif::[]
|
|
18
|
+
{{/if}}
|
|
13
19
|
{{#if type}}
|
|
14
|
-
*Type:* {{type}}
|
|
15
20
|
|
|
21
|
+
*Type:* {{type}}
|
|
16
22
|
{{/if}}
|
|
17
23
|
{{#if acceptable_values}}
|
|
18
|
-
*Accepted values:* {{{acceptable_values}}}
|
|
19
24
|
|
|
25
|
+
*Accepted values:* {{{acceptable_values}}}
|
|
20
26
|
{{/if}}
|
|
21
27
|
{{#if corresponding_cluster_property}}
|
|
22
|
-
*Related cluster property:* xref:reference:cluster-properties.adoc#{{corresponding_cluster_property}}[{{corresponding_cluster_property}}]
|
|
23
28
|
|
|
29
|
+
*Related cluster property:* xref:reference:cluster-properties.adoc#{{corresponding_cluster_property}}[{{corresponding_cluster_property}}]
|
|
24
30
|
{{/if}}
|
|
25
31
|
{{#if (and minimum maximum)}}
|
|
26
|
-
*Accepted values:* [`{{minimum}}`, `{{maximum}}`]
|
|
27
32
|
|
|
33
|
+
*Accepted values:* [`{{minimum}}`, `{{maximum}}`]
|
|
28
34
|
{{else}}
|
|
29
35
|
{{#if minimum}}
|
|
30
|
-
*Minimum value:* `{{minimum}}`
|
|
31
36
|
|
|
37
|
+
*Minimum value:* `{{minimum}}`
|
|
32
38
|
{{/if}}
|
|
33
39
|
{{#if maximum}}
|
|
34
|
-
*Maximum value:* `{{maximum}}`
|
|
35
40
|
|
|
41
|
+
*Maximum value:* `{{maximum}}`
|
|
36
42
|
{{/if}}
|
|
37
43
|
{{/if}}
|
|
38
44
|
{{#if (ne default undefined)}}
|
|
39
|
-
*Default:* `{{formatPropertyValue default type}}`
|
|
40
45
|
|
|
46
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
41
47
|
{{/if}}
|
|
42
|
-
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
43
48
|
|
|
49
|
+
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
44
50
|
{{#if example}}
|
|
51
|
+
|
|
45
52
|
{{{renderPropertyExample this}}}
|
|
46
53
|
{{/if}}
|
|
54
|
+
{{#if related_topics}}
|
|
55
|
+
|
|
56
|
+
*Related topics:*
|
|
47
57
|
|
|
58
|
+
{{#each related_topics}}
|
|
59
|
+
* {{{this}}}
|
|
60
|
+
{{/each}}
|
|
61
|
+
{{/if}}
|
|
48
62
|
{{#if aliases}}
|
|
49
|
-
*Aliases:* {{join aliases ", "}}
|
|
50
63
|
|
|
64
|
+
*Aliases:* {{join aliases ", "}}
|
|
51
65
|
{{/if}}
|
|
52
66
|
{{#if is_deprecated}}
|
|
67
|
+
|
|
53
68
|
[WARNING]
|
|
54
69
|
====
|
|
55
70
|
This property is deprecated.
|
|
56
71
|
====
|
|
57
|
-
|
|
58
72
|
{{/if}}
|
|
59
73
|
---
|
|
@@ -1,13 +1,50 @@
|
|
|
1
1
|
import re
|
|
2
|
+
import logging
|
|
2
3
|
from property_bag import PropertyBag
|
|
3
4
|
from parser import normalize_string
|
|
4
5
|
|
|
6
|
+
# Get logger for this module
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
# Import the process_enterprise_value function from property_extractor
|
|
10
|
+
# Note: We import at function level to avoid circular imports since property_extractor
|
|
11
|
+
# imports transformers.py. This pattern allows the EnterpriseTransformer to access
|
|
12
|
+
# the centralized enterprise value processing logic without creating import cycles.
|
|
13
|
+
def get_process_enterprise_value():
|
|
14
|
+
"""
|
|
15
|
+
Lazily import and return the centralized `process_enterprise_value` function from `property_extractor`.
|
|
16
|
+
|
|
17
|
+
Attempts to import `process_enterprise_value` and return it to avoid circular-import issues. If the import fails an error message is printed and None is returned.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Callable or None: The `process_enterprise_value` callable when available, otherwise `None`.
|
|
21
|
+
"""
|
|
22
|
+
try:
|
|
23
|
+
from property_extractor import process_enterprise_value
|
|
24
|
+
return process_enterprise_value
|
|
25
|
+
except ImportError as e:
|
|
26
|
+
logger.error("Cannot import process_enterprise_value from property_extractor: %s", e)
|
|
27
|
+
return None
|
|
28
|
+
|
|
5
29
|
|
|
6
30
|
class BasicInfoTransformer:
|
|
7
31
|
def accepts(self, info, file_pair):
|
|
32
|
+
"""
|
|
33
|
+
Always accepts the provided info and file_pair.
|
|
34
|
+
|
|
35
|
+
Parameters:
|
|
36
|
+
info (dict): Parsed metadata for a property (annotation/params/declaration).
|
|
37
|
+
file_pair (object): Pair of source/implementation file metadata used by transformers.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
bool: Always returns True, indicating this transformer should be applied.
|
|
41
|
+
"""
|
|
8
42
|
return True
|
|
9
43
|
|
|
10
44
|
def parse(self, property, info, file_pair):
|
|
45
|
+
if not info.get("params") or len(info["params"]) == 0:
|
|
46
|
+
return property
|
|
47
|
+
|
|
11
48
|
property["name"] = info["params"][0]["value"]
|
|
12
49
|
property["defined_in"] = re.sub(
|
|
13
50
|
r"^.*src/", "src/", str(file_pair.implementation)
|
|
@@ -427,13 +464,65 @@ class AliasTransformer:
|
|
|
427
464
|
|
|
428
465
|
|
|
429
466
|
class EnterpriseTransformer:
|
|
467
|
+
"""
|
|
468
|
+
Transforms enterprise property values from C++ expressions to user-friendly JSON.
|
|
469
|
+
|
|
470
|
+
This transformer processes enterprise values by delegating to the
|
|
471
|
+
centralized process_enterprise_value function which handles the full range of
|
|
472
|
+
C++ expression types found in enterprise property definitions.
|
|
473
|
+
"""
|
|
430
474
|
def accepts(self, info, file_pair):
|
|
475
|
+
"""
|
|
476
|
+
Return True if the provided info indicates an enterprise-only property.
|
|
477
|
+
|
|
478
|
+
Parameters:
|
|
479
|
+
info (dict): The metadata dictionary for a property. This function checks for a 'type' key whose string contains 'enterprise'.
|
|
480
|
+
file_pair: Unused; present for transformer interface compatibility.
|
|
481
|
+
|
|
482
|
+
Returns:
|
|
483
|
+
bool: True when info contains a 'type' that includes 'enterprise', otherwise False.
|
|
484
|
+
"""
|
|
431
485
|
return bool(info.get('type') and 'enterprise' in info['type'])
|
|
432
486
|
|
|
433
487
|
def parse(self, property, info, file_pair):
|
|
488
|
+
"""
|
|
489
|
+
Mark a property as enterprise-only and attach its enterprise value.
|
|
490
|
+
|
|
491
|
+
If an enterprise value is present in info['params'][0]['value'], this method attempts to process it using the shared
|
|
492
|
+
process_enterprise_value helper (loaded via get_process_enterprise_value()). If the processor is unavailable or raises
|
|
493
|
+
an exception, the raw enterprise value is used.
|
|
494
|
+
|
|
495
|
+
Side effects:
|
|
496
|
+
- Sets property["enterprise_value"] to the processed or raw value.
|
|
497
|
+
- Sets property["is_enterprise"] = True.
|
|
498
|
+
- Removes the first element from info['params'].
|
|
499
|
+
|
|
500
|
+
Parameters:
|
|
501
|
+
property (dict): Property bag to modify and return.
|
|
502
|
+
info (dict): Parsed metadata; must have a non-None 'params' list for processing.
|
|
503
|
+
file_pair: Unused here but accepted for transformer API compatibility.
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
dict: The updated property bag.
|
|
507
|
+
"""
|
|
434
508
|
if info['params'] is not None:
|
|
435
509
|
enterpriseValue = info['params'][0]['value']
|
|
436
|
-
|
|
510
|
+
|
|
511
|
+
# Get the processing function
|
|
512
|
+
process_enterprise_value = get_process_enterprise_value()
|
|
513
|
+
if process_enterprise_value is None:
|
|
514
|
+
property["enterprise_value"] = enterpriseValue
|
|
515
|
+
property['is_enterprise'] = True
|
|
516
|
+
del info['params'][0]
|
|
517
|
+
return property
|
|
518
|
+
|
|
519
|
+
try:
|
|
520
|
+
processed_value = process_enterprise_value(enterpriseValue)
|
|
521
|
+
property["enterprise_value"] = processed_value
|
|
522
|
+
except Exception:
|
|
523
|
+
# Fallback to raw value if processing fails
|
|
524
|
+
property["enterprise_value"] = enterpriseValue
|
|
525
|
+
|
|
437
526
|
property['is_enterprise'] = True
|
|
438
527
|
del info['params'][0]
|
|
439
528
|
return property
|
|
@@ -462,7 +551,14 @@ class MetaParamTransformer:
|
|
|
462
551
|
iterable_params = info['params']
|
|
463
552
|
for param in iterable_params:
|
|
464
553
|
if isinstance(param['value'], str) and param['value'].startswith("meta{"):
|
|
465
|
-
|
|
554
|
+
# Extract content between meta{ and } using explicit slicing
|
|
555
|
+
param_value = param['value']
|
|
556
|
+
if param_value.endswith('}'):
|
|
557
|
+
meta_content = param_value[5:-1].strip() # Remove "meta{" and "}"
|
|
558
|
+
else:
|
|
559
|
+
# Handle malformed meta{ without closing }
|
|
560
|
+
meta_content = param_value[5:].strip() # Remove "meta{" only
|
|
561
|
+
|
|
466
562
|
meta_dict = {}
|
|
467
563
|
for item in meta_content.split(','):
|
|
468
564
|
item = item.strip()
|
|
@@ -209,6 +209,31 @@ function resolveReferences(obj, root) {
|
|
|
209
209
|
* When generating full drafts, components with a `status` of `'deprecated'` are skipped.
|
|
210
210
|
*/
|
|
211
211
|
async function generateRpcnConnectorDocs(options) {
|
|
212
|
+
// Types and output folders for bloblang function/method partials
|
|
213
|
+
const bloblangTypes = [
|
|
214
|
+
{ key: 'bloblang-functions', folder: 'bloblang-functions' },
|
|
215
|
+
{ key: 'bloblang-methods', folder: 'bloblang-methods' }
|
|
216
|
+
];
|
|
217
|
+
// Recursively mark is_beta on any field/component with description starting with BETA:
|
|
218
|
+
function markBeta(obj) {
|
|
219
|
+
if (!obj || typeof obj !== 'object') return;
|
|
220
|
+
if (Array.isArray(obj)) {
|
|
221
|
+
obj.forEach(markBeta);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Mark as beta if description starts with 'BETA:' (case-insensitive, trims leading whitespace)
|
|
225
|
+
if (typeof obj.description === 'string' && /^\s*BETA:\s*/i.test(obj.description)) {
|
|
226
|
+
obj.is_beta = true;
|
|
227
|
+
}
|
|
228
|
+
// Recurse into children/config/fields
|
|
229
|
+
if (Array.isArray(obj.children)) obj.children.forEach(markBeta);
|
|
230
|
+
if (obj.config && Array.isArray(obj.config.children)) obj.config.children.forEach(markBeta);
|
|
231
|
+
// For connector/component arrays
|
|
232
|
+
for (const key of Object.keys(obj)) {
|
|
233
|
+
if (Array.isArray(obj[key])) obj[key].forEach(markBeta);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
212
237
|
const {
|
|
213
238
|
data,
|
|
214
239
|
overrides,
|
|
@@ -216,6 +241,7 @@ async function generateRpcnConnectorDocs(options) {
|
|
|
216
241
|
templateIntro,
|
|
217
242
|
templateFields,
|
|
218
243
|
templateExamples,
|
|
244
|
+
templateBloblang,
|
|
219
245
|
writeFullDrafts
|
|
220
246
|
} = options;
|
|
221
247
|
|
|
@@ -223,16 +249,38 @@ async function generateRpcnConnectorDocs(options) {
|
|
|
223
249
|
const raw = fs.readFileSync(data, 'utf8');
|
|
224
250
|
const ext = path.extname(data).toLowerCase();
|
|
225
251
|
const dataObj = ext === '.json' ? JSON.parse(raw) : yaml.parse(raw);
|
|
252
|
+
// Mark beta fields/components before overrides
|
|
253
|
+
markBeta(dataObj);
|
|
226
254
|
|
|
227
255
|
// Apply overrides if provided
|
|
228
256
|
if (overrides) {
|
|
229
257
|
const ovRaw = fs.readFileSync(overrides, 'utf8');
|
|
230
258
|
const ovObj = JSON.parse(ovRaw);
|
|
231
|
-
|
|
232
259
|
// Resolve any $ref references in the overrides
|
|
233
260
|
const resolvedOverrides = resolveReferences(ovObj, ovObj);
|
|
234
|
-
|
|
235
261
|
mergeOverrides(dataObj, resolvedOverrides);
|
|
262
|
+
|
|
263
|
+
// Special: merge bloblang_methods and bloblang_functions from overrides into main data
|
|
264
|
+
for (const [overrideKey, mainKey] of [
|
|
265
|
+
['bloblang_methods', 'bloblang-methods'],
|
|
266
|
+
['bloblang_functions', 'bloblang-functions']
|
|
267
|
+
]) {
|
|
268
|
+
if (Array.isArray(resolvedOverrides[overrideKey])) {
|
|
269
|
+
if (!Array.isArray(dataObj[mainKey])) dataObj[mainKey] = [];
|
|
270
|
+
// Merge by name
|
|
271
|
+
const mainArr = dataObj[mainKey];
|
|
272
|
+
const overrideArr = resolvedOverrides[overrideKey];
|
|
273
|
+
for (const overrideItem of overrideArr) {
|
|
274
|
+
if (!overrideItem.name) continue;
|
|
275
|
+
const idx = mainArr.findIndex(i => i.name === overrideItem.name);
|
|
276
|
+
if (idx !== -1) {
|
|
277
|
+
mainArr[idx] = { ...mainArr[idx], ...overrideItem };
|
|
278
|
+
} else {
|
|
279
|
+
mainArr.push(overrideItem);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
236
284
|
}
|
|
237
285
|
|
|
238
286
|
// Compile the “main” template (used when writeFullDrafts = true)
|
|
@@ -260,6 +308,7 @@ async function generateRpcnConnectorDocs(options) {
|
|
|
260
308
|
const fieldsOutRoot = path.join(outputRoot, 'fields');
|
|
261
309
|
const examplesOutRoot = path.join(outputRoot, 'examples');
|
|
262
310
|
const draftsRoot = path.join(outputRoot, 'drafts');
|
|
311
|
+
const configExamplesRoot = path.resolve(process.cwd(), 'modules/components/examples');
|
|
263
312
|
|
|
264
313
|
if (!writeFullDrafts) {
|
|
265
314
|
fs.mkdirSync(fieldsOutRoot, { recursive: true });
|
|
@@ -332,6 +381,51 @@ async function generateRpcnConnectorDocs(options) {
|
|
|
332
381
|
}
|
|
333
382
|
}
|
|
334
383
|
|
|
384
|
+
// Bloblang function/method partials (only if includeBloblang is true)
|
|
385
|
+
if (options.includeBloblang) {
|
|
386
|
+
for (const { key, folder } of bloblangTypes) {
|
|
387
|
+
const items = dataObj[key];
|
|
388
|
+
if (!Array.isArray(items)) continue;
|
|
389
|
+
const outRoot = path.join(outputRoot, folder);
|
|
390
|
+
fs.mkdirSync(outRoot, { recursive: true });
|
|
391
|
+
// Use custom or default template
|
|
392
|
+
const bloblangTemplatePath = templateBloblang || path.resolve(__dirname, './templates/bloblang-function.hbs');
|
|
393
|
+
const bloblangTemplate = handlebars.compile(fs.readFileSync(bloblangTemplatePath, 'utf8'));
|
|
394
|
+
for (const fn of items) {
|
|
395
|
+
if (!fn.name) continue;
|
|
396
|
+
const adoc = bloblangTemplate(fn);
|
|
397
|
+
const outPath = path.join(outRoot, `${fn.name}.adoc`);
|
|
398
|
+
fs.writeFileSync(outPath, adoc, 'utf8');
|
|
399
|
+
partialsWritten++;
|
|
400
|
+
partialFiles.push(path.relative(process.cwd(), outPath));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Common/Advanced config snippet YAMLs in modules/components/examples
|
|
406
|
+
const commonConfig = helpers.commonConfig;
|
|
407
|
+
const advancedConfig = helpers.advancedConfig;
|
|
408
|
+
for (const [type, items] of Object.entries(dataObj)) {
|
|
409
|
+
if (!Array.isArray(items)) continue;
|
|
410
|
+
for (const item of items) {
|
|
411
|
+
if (!item.name || !item.config || !Array.isArray(item.config.children)) continue;
|
|
412
|
+
// Common config
|
|
413
|
+
const commonYaml = commonConfig(type, item.name, item.config.children);
|
|
414
|
+
const commonPath = path.join(configExamplesRoot, 'common', type, `${item.name}.yaml`);
|
|
415
|
+
fs.mkdirSync(path.dirname(commonPath), { recursive: true });
|
|
416
|
+
fs.writeFileSync(commonPath, commonYaml.toString(), 'utf8');
|
|
417
|
+
partialsWritten++;
|
|
418
|
+
partialFiles.push(path.relative(process.cwd(), commonPath));
|
|
419
|
+
// Advanced config
|
|
420
|
+
const advYaml = advancedConfig(type, item.name, item.config.children);
|
|
421
|
+
const advPath = path.join(configExamplesRoot, 'advanced', type, `${item.name}.yaml`);
|
|
422
|
+
fs.mkdirSync(path.dirname(advPath), { recursive: true });
|
|
423
|
+
fs.writeFileSync(advPath, advYaml.toString(), 'utf8');
|
|
424
|
+
partialsWritten++;
|
|
425
|
+
partialFiles.push(path.relative(process.cwd(), advPath));
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
335
429
|
return {
|
|
336
430
|
partialsWritten,
|
|
337
431
|
draftsWritten,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Bloblang example formatting helper for Handlebars
|
|
2
|
+
function bloblangExample(example) {
|
|
3
|
+
if (typeof example === 'object' && example !== null && example.mapping) {
|
|
4
|
+
let codeBlock = '';
|
|
5
|
+
if (example.summary && example.summary.trim()) {
|
|
6
|
+
codeBlock += `# ${example.summary.trim().replace(/\n/g, '\n# ')}\n\n`;
|
|
7
|
+
}
|
|
8
|
+
if (typeof example.mapping === 'string') {
|
|
9
|
+
codeBlock += example.mapping.trim() + '\n';
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(example.results)) {
|
|
12
|
+
for (const pair of example.results) {
|
|
13
|
+
if (Array.isArray(pair) && pair.length === 2) {
|
|
14
|
+
codeBlock += `\n# In: ${pair[0]}\n# Out: ${pair[1]}\n`;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return `[,coffeescript]\n----\n${codeBlock.trim()}\n----\n`;
|
|
19
|
+
} else {
|
|
20
|
+
let exStr = '';
|
|
21
|
+
if (typeof example === 'string') {
|
|
22
|
+
exStr = example;
|
|
23
|
+
} else if (typeof example === 'object' && example !== null) {
|
|
24
|
+
if (example.code) {
|
|
25
|
+
exStr = example.code;
|
|
26
|
+
} else if (example.example) {
|
|
27
|
+
exStr = example.example;
|
|
28
|
+
} else {
|
|
29
|
+
try {
|
|
30
|
+
exStr = require('yaml').stringify(example).trim();
|
|
31
|
+
} catch {
|
|
32
|
+
exStr = JSON.stringify(example, null, 2);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
exStr = String(example);
|
|
37
|
+
}
|
|
38
|
+
return `[source,coffeescript]\n----\n${exStr}\n----\n`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = bloblangExample;
|
|
@@ -4,10 +4,10 @@ module.exports = {
|
|
|
4
4
|
uppercase: require('./uppercase.js'),
|
|
5
5
|
eq: require('./eq.js'),
|
|
6
6
|
ne: require('./ne.js'),
|
|
7
|
-
join:
|
|
7
|
+
join: require('./join.js'),
|
|
8
8
|
or: require('./or.js'),
|
|
9
|
-
toYaml:
|
|
10
|
-
isObject:
|
|
9
|
+
toYaml: require('./toYaml.js'),
|
|
10
|
+
isObject: require('./isObject.js'),
|
|
11
11
|
renderYamlList: require('./renderYamlList.js'),
|
|
12
12
|
renderConnectFields: require('./renderConnectFields.js'),
|
|
13
13
|
renderConnectExamples: require('./renderConnectExamples.js'),
|
|
@@ -16,4 +16,5 @@ module.exports = {
|
|
|
16
16
|
buildConfigYaml: require('./buildConfigYaml.js'),
|
|
17
17
|
commonConfig: require('./commonConfig.js'),
|
|
18
18
|
advancedConfig: require('./advancedConfig.js'),
|
|
19
|
+
bloblangExample: require('./bloblangExample.js'),
|
|
19
20
|
};
|