@redpanda-data/docs-extensions-and-macros 4.4.2 → 4.6.0

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.
Files changed (46) hide show
  1. package/README.adoc +0 -163
  2. package/bin/doc-tools.js +808 -151
  3. package/cli-utils/antora-utils.js +127 -0
  4. package/cli-utils/convert-doc-links.js +58 -0
  5. package/cli-utils/generate-cluster-docs.sh +1 -1
  6. package/cli-utils/self-managed-docs-branch.js +91 -0
  7. package/cli-utils/start-cluster.sh +12 -2
  8. package/docker-compose/25.1/bootstrap.yml +67 -0
  9. package/docker-compose/25.1/docker-compose.yml +414 -0
  10. package/docker-compose/25.1/generate-profiles.yaml +77 -0
  11. package/docker-compose/25.1/rpk-profile.yaml +24 -0
  12. package/docker-compose/25.1/transactions-schema.json +37 -0
  13. package/docker-compose/25.1/transactions.md +46 -0
  14. package/docker-compose/25.1/transform/README.adoc +73 -0
  15. package/docker-compose/25.1/transform/go.mod +5 -0
  16. package/docker-compose/25.1/transform/go.sum +2 -0
  17. package/docker-compose/25.1/transform/regex.wasm +0 -0
  18. package/docker-compose/25.1/transform/transform.go +122 -0
  19. package/docker-compose/25.1/transform/transform.yaml +33 -0
  20. package/docker-compose/bootstrap.yml +0 -12
  21. package/package.json +6 -5
  22. package/tools/fetch-from-github.js +2 -2
  23. package/tools/redpanda-connect/generate-rpcn-connector-docs.js +205 -0
  24. package/tools/redpanda-connect/helpers/advancedConfig.js +17 -0
  25. package/tools/redpanda-connect/helpers/buildConfigYaml.js +53 -0
  26. package/tools/redpanda-connect/helpers/commonConfig.js +31 -0
  27. package/tools/redpanda-connect/helpers/eq.js +10 -0
  28. package/tools/redpanda-connect/helpers/index.js +19 -0
  29. package/tools/redpanda-connect/helpers/isObject.js +1 -0
  30. package/tools/redpanda-connect/helpers/join.js +6 -0
  31. package/tools/redpanda-connect/helpers/ne.js +10 -0
  32. package/tools/redpanda-connect/helpers/or.js +4 -0
  33. package/tools/redpanda-connect/helpers/renderConnectExamples.js +37 -0
  34. package/tools/redpanda-connect/helpers/renderConnectFields.js +146 -0
  35. package/tools/redpanda-connect/helpers/renderLeafField.js +64 -0
  36. package/tools/redpanda-connect/helpers/renderObjectField.js +41 -0
  37. package/tools/redpanda-connect/helpers/renderYamlList.js +24 -0
  38. package/tools/redpanda-connect/helpers/toYaml.js +11 -0
  39. package/tools/redpanda-connect/helpers/uppercase.js +9 -0
  40. package/tools/redpanda-connect/parse-csv-connectors.js +63 -0
  41. package/tools/redpanda-connect/report-delta.js +152 -0
  42. package/tools/redpanda-connect/templates/connector.hbs +20 -0
  43. package/tools/redpanda-connect/templates/examples-partials.hbs +7 -0
  44. package/tools/redpanda-connect/templates/fields-partials.hbs +13 -0
  45. package/tools/redpanda-connect/templates/intro.hbs +35 -0
  46. package/macros/data-template.js +0 -591
@@ -0,0 +1,122 @@
1
+ package main
2
+ // This data transform filters records based on a customizable regex pattern.
3
+ // If a record's key or value
4
+ // (determined by an environment variable) matches the specified regex,
5
+ // the record is forwarded to the output.
6
+ // Otherwise, it is dropped.
7
+ //
8
+ // Usage:
9
+ // 1. Provide the following environment variables in your Docker or configuration setup:
10
+ // - PATTERN : (required) a regular expression that determines what you want to match.
11
+ // - MATCH_VALUE : (optional) a boolean to decide whether to check the record value. If false,
12
+ // the record key is checked. Default is false.
13
+ //
14
+ // Example environment variables:
15
+ // PATTERN=".*\\.edu$"
16
+ // MATCH_VALUE="true"
17
+ //
18
+ // Logs:
19
+ // This transform logs information about each record and whether it matched.
20
+ // The logs appear in the _redpanda.transform_logs topic, so you can debug how your records are being processed.
21
+ //
22
+ // Build instructions:
23
+ // go mod tidy
24
+ // rpk transform build
25
+ //
26
+ // For more details on building transforms with the Redpanda SDK, see:
27
+ // https://docs.redpanda.com/current/develop/data-transforms
28
+ //
29
+
30
+ import (
31
+ "log"
32
+ "os"
33
+ "regexp"
34
+ "strings"
35
+
36
+ "github.com/redpanda-data/redpanda/src/transform-sdk/go/transform"
37
+ )
38
+
39
+ var (
40
+ re *regexp.Regexp
41
+ checkValue bool
42
+ )
43
+
44
+ func isTrueVar(v string) bool {
45
+ switch strings.ToLower(v) {
46
+ case "yes", "ok", "1", "true":
47
+ return true
48
+ default:
49
+ return false
50
+ }
51
+ }
52
+
53
+ // The main() function runs only once at startup. It performs all initialization steps:
54
+ // - Reads and compiles the regex pattern.
55
+ // - Determines whether to match on the key or value.
56
+ // - Registers the doRegexFilter() function to process records.
57
+ func main() {
58
+ // Set logging preferences, including timestamp and UTC time.
59
+ log.SetPrefix("[regex-transform] ")
60
+ log.SetFlags(log.Ldate | log.Ltime | log.LUTC | log.Lmicroseconds)
61
+
62
+ // Start logging the transformation process
63
+ log.Println("Starting transform...")
64
+
65
+ // Read the PATTERN environment variable to get the regex pattern.
66
+ pattern, ok := os.LookupEnv("PATTERN")
67
+ if !ok {
68
+ log.Fatal("Missing PATTERN environment variable")
69
+ }
70
+ // Log the regex pattern being used.
71
+ log.Printf("Using PATTERN: %q\n", pattern)
72
+ // Compile the regex pattern for later use.
73
+ re = regexp.MustCompile(pattern)
74
+
75
+ // Read the MATCH_VALUE environment variable to determine whether to check the record's value.
76
+ mk, ok := os.LookupEnv("MATCH_VALUE")
77
+ checkValue = ok && isTrueVar(mk)
78
+ log.Printf("MATCH_VALUE set to: %t\n", checkValue)
79
+
80
+ log.Println("Initialization complete, waiting for records...")
81
+
82
+ // Listen for records to be written, calling doRegexFilter() for each record.
83
+ transform.OnRecordWritten(doRegexFilter)
84
+ }
85
+
86
+ // The doRegexFilter() function executes each time a new record is written.
87
+ // It checks whether the record's key or value (based on MATCH_VALUE) matches the compiled regex.
88
+ // If it matches, the record is forwarded, if not, it's dropped.
89
+ func doRegexFilter(e transform.WriteEvent, w transform.RecordWriter) error {
90
+ // This stores the data to be checked (either the key or value).
91
+ var dataToCheck []byte
92
+
93
+ // Depending on the MATCH_VALUE environment variable, decide whether to check the record's key or value.
94
+ if checkValue {
95
+ // Use the value of the record if MATCH_VALUE is true.
96
+ dataToCheck = e.Record().Value
97
+ log.Printf("Checking record value: %s\n", string(dataToCheck))
98
+ } else {
99
+ // Use the key of the record if MATCH_VALUE is false.
100
+ dataToCheck = e.Record().Key
101
+ log.Printf("Checking record key: %s\n", string(dataToCheck))
102
+ }
103
+
104
+ // If there is no key or value to check, log and skip the record.
105
+ if dataToCheck == nil {
106
+ log.Println("Record has no key/value to check, skipping.")
107
+ return nil
108
+ }
109
+
110
+ // Check if the data matches the regex pattern.
111
+ pass := re.Match(dataToCheck)
112
+ if pass {
113
+ // If the record matches the pattern, log and write the record to the output topic.
114
+ log.Printf("Record matched pattern, passing through. Key: %s, Value: %s\n", string(e.Record().Key), string(e.Record().Value))
115
+ return w.Write(e.Record())
116
+ } else {
117
+ // If the record does not match the pattern, log and drop the record.
118
+ log.Printf("Record did not match pattern, dropping. Key: %s, Value: %s\n", string(e.Record().Key), string(e.Record().Value))
119
+ // Do not write the record if it doesn't match the pattern.
120
+ return nil
121
+ }
122
+ }
@@ -0,0 +1,33 @@
1
+ # Transform metadata used by the rpk transform build command.
2
+ # This metadata file tells rpk:
3
+ # 1) The transform’s display name, which also becomes the base for the .wasm file name.
4
+ # 2) A brief description of what it does.
5
+ # 3) Defaults for environment variables.
6
+ # 4) Input and output topics (if you want to define them here rather than in the deploy command).
7
+
8
+ # Human-readable name of the transform. rpk transform build uses this for the generated .wasm file.
9
+ name: regex
10
+
11
+ description: |
12
+ Filters the input topic to records that only match a regular expression.
13
+
14
+ Regular expressions are implemented using Go's regexp library, which uses the syntax of RE2.
15
+ See the RE2 wiki for allowed syntax: https://github.com/google/re2/wiki/Syntax
16
+
17
+ Environment variables:
18
+ - PATTERN: The regular expression that will match against records (required).
19
+ - MATCH_VALUE: By default, the regex matches keys, but if set to "true", the regex matches values.
20
+
21
+ # By default, no input topic is set here. (You can set it in your deploy command if preferred.)
22
+ input-topic: ""
23
+
24
+ # By default, no output topic is set here. (You can set it in your deploy command if preferred.)
25
+ output-topic: ""
26
+
27
+ # Indicates the specific TinyGo environment used to compile your transform.
28
+ language: tinygo-no-goroutines
29
+
30
+ env:
31
+ # The PATTERN variable must be provided at deploy time.
32
+ # Example: --var=PATTERN=".*@example.com"
33
+ PATTERN: '<required>'
@@ -44,18 +44,6 @@ cloud_storage_segment_max_upload_interval_sec: 60
44
44
  # Continuous Data Balancing (enterprise feature) continuously monitors your node and rack availability and disk usage. This enables self-healing clusters that dynamically balance partitions, ensuring smooth operations and optimal cluster performance.
45
45
  # https://docs.redpanda.com/current/manage/cluster-maintenance/continuous-data-balancing/
46
46
  partition_autobalancing_mode: continuous
47
- # Enable Redpanda to collect consumer group metrics.
48
- # https://docs.redpanda.com/current/reference/properties/cluster-properties/#enable_consumer_group_metrics
49
- enable_consumer_group_metrics:
50
- - "group"
51
- - "partition"
52
- - "consumer_lag"
53
- # Lower the interval for the autogeneration of consumer group metrics.
54
- # https://docs.redpanda.com/current/reference/properties/cluster-properties/#consumer_group_lag_collection_interval_sec
55
- consumer_group_lag_collection_interval_sec: 60
56
- # Enable Redpanda to collect host metrics.
57
- # https://docs.redpanda.com/current/reference/properties/cluster-properties/#enable_host_metrics
58
- enable_host_metrics: true
59
47
  # Enable for Iceberg metrics
60
48
  iceberg_enabled: true
61
49
  # Set up Iceberg REST catalog configuration
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "4.4.2",
3
+ "version": "4.6.0",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -20,7 +20,8 @@
20
20
  "get-redpanda-version": "doc-tools get-redpanda-version",
21
21
  "get-console-version": "doc-tools get-console-version",
22
22
  "build": "antora --to-dir docs --fetch local-antora-playbook.yml",
23
- "serve": "wds --node-resolve --open preview/test/ --watch --root-dir docs"
23
+ "serve": "wds --node-resolve --open preview/test/ --watch --root-dir docs",
24
+ "test": "jest"
24
25
  },
25
26
  "contributors": [
26
27
  {
@@ -56,8 +57,7 @@
56
57
  "./macros/glossary": "./macros/glossary.js",
57
58
  "./macros/rp-connect-components": "./macros/rp-connect-components.js",
58
59
  "./macros/config-ref": "./macros/config-ref.js",
59
- "./macros/helm-ref": "./macros/helm-ref.js",
60
- "./macros/data-template": "./macros/data-template.js"
60
+ "./macros/helm-ref": "./macros/helm-ref.js"
61
61
  },
62
62
  "files": [
63
63
  "extensions",
@@ -101,6 +101,7 @@
101
101
  "devDependencies": {
102
102
  "@antora/cli": "3.1.4",
103
103
  "@antora/site-generator": "3.1.4",
104
- "@web/dev-server": "^0.2.5"
104
+ "@web/dev-server": "^0.2.5",
105
+ "jest": "^29.7.0"
105
106
  }
106
107
  }
@@ -12,8 +12,8 @@ async function loadOctokit() {
12
12
  : new Octokit();
13
13
 
14
14
  if (!process.env.VBOT_GITHUB_API_TOKEN) {
15
- console.warn(
16
- 'Warning: No GitHub token found (VBOT_GITHUB_API_TOKEN). API rate limits will be restricted.'
15
+ console.info(
16
+ 'No GitHub token found (VBOT_GITHUB_API_TOKEN).'
17
17
  );
18
18
  }
19
19
  }
@@ -0,0 +1,205 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const handlebars = require('handlebars');
6
+ const yaml = require('yaml');
7
+ const helpers = require('./helpers');
8
+
9
+ // Register each helper under handlebars, verifying that it’s a function
10
+ Object.entries(helpers).forEach(([name, fn]) => {
11
+ if (typeof fn !== 'function') {
12
+ console.error(`❌ Helper "${name}" is not a function`);
13
+ process.exit(1);
14
+ }
15
+ handlebars.registerHelper(name, fn);
16
+ });
17
+
18
+ // Default “main” template (connector.hbs) which invokes partials {{> intro}}, {{> fields}}, {{> examples}}
19
+ const DEFAULT_TEMPLATE = path.resolve(__dirname, './templates/connector.hbs');
20
+
21
+ /**
22
+ * Reads a file at `filePath` and registers it as a Handlebars partial called `name`.
23
+ * Throws if the file cannot be read.
24
+ */
25
+ function registerPartial(name, filePath) {
26
+ const resolved = path.resolve(filePath);
27
+ let source;
28
+ try {
29
+ source = fs.readFileSync(resolved, 'utf8');
30
+ } catch (err) {
31
+ throw new Error(`Unable to read "${name}" template at ${resolved}: ${err.message}`);
32
+ }
33
+ handlebars.registerPartial(name, source);
34
+ }
35
+
36
+ /**
37
+ * Deep-merge `overrides` into `target`. Only 'description', 'type',
38
+ * plus nested array/object entries get overridden; other keys remain intact.
39
+ */
40
+ function mergeOverrides(target, overrides) {
41
+ if (!overrides || typeof overrides !== 'object') return target;
42
+ if (!target || typeof target !== 'object') {
43
+ throw new Error('Target must be a valid object');
44
+ }
45
+ for (const key in overrides) {
46
+ if (Array.isArray(target[key]) && Array.isArray(overrides[key])) {
47
+ // Merge two parallel arrays by matching items on `.name`
48
+ target[key] = target[key].map(item => {
49
+ const overrideItem = overrides[key].find(o => o.name === item.name);
50
+ if (overrideItem) {
51
+ // Overwrite description/type if present
52
+ ['description', 'type'].forEach(field => {
53
+ if (Object.hasOwn(overrideItem, field)) {
54
+ item[field] = overrideItem[field];
55
+ }
56
+ });
57
+ // Recurse for nested children
58
+ item = mergeOverrides(item, overrideItem);
59
+ }
60
+ return item;
61
+ });
62
+ } else if (
63
+ typeof target[key] === 'object' &&
64
+ typeof overrides[key] === 'object' &&
65
+ !Array.isArray(target[key]) &&
66
+ !Array.isArray(overrides[key])
67
+ ) {
68
+ // Deep-merge plain objects
69
+ target[key] = mergeOverrides(target[key], overrides[key]);
70
+ } else if (['description', 'type'].includes(key) && Object.hasOwn(overrides, key)) {
71
+ // Overwrite the primitive
72
+ target[key] = overrides[key];
73
+ }
74
+ }
75
+ return target;
76
+ }
77
+
78
+ async function generateRpcnConnectorDocs(options) {
79
+ const {
80
+ data,
81
+ overrides,
82
+ template, // main Handlebars template (for full-draft mode)
83
+ templateIntro,
84
+ templateFields,
85
+ templateExamples,
86
+ writeFullDrafts
87
+ } = options;
88
+
89
+ // Read connector index (JSON or YAML)
90
+ const raw = fs.readFileSync(data, 'utf8');
91
+ const ext = path.extname(data).toLowerCase();
92
+ const dataObj = ext === '.json' ? JSON.parse(raw) : yaml.parse(raw);
93
+
94
+ // Apply overrides if provided
95
+ if (overrides) {
96
+ const ovRaw = fs.readFileSync(overrides, 'utf8');
97
+ const ovObj = JSON.parse(ovRaw);
98
+ mergeOverrides(dataObj, ovObj);
99
+ }
100
+
101
+ // Compile the “main” template (used when writeFullDrafts = true)
102
+ const compiledTemplate = handlebars.compile(fs.readFileSync(template, 'utf8'));
103
+
104
+ // Determine which templates to use for “fields” and “examples”
105
+ // If templateFields is not provided, fall back to the single `template`.
106
+ // If templateExamples is not provided, skip examples entirely.
107
+ const fieldsTemplatePath = templateFields || template;
108
+ const examplesTemplatePath = templateExamples || null;
109
+
110
+ // Register partials
111
+ if (!writeFullDrafts) {
112
+ if (fieldsTemplatePath) {
113
+ registerPartial('fields', fieldsTemplatePath);
114
+ }
115
+ if (examplesTemplatePath) {
116
+ registerPartial('examples', examplesTemplatePath);
117
+ }
118
+ } else {
119
+ registerPartial('intro', templateIntro);
120
+ }
121
+
122
+ const outputRoot = path.resolve(process.cwd(), 'modules/components/partials');
123
+ const fieldsOutRoot = path.join(outputRoot, 'fields');
124
+ const examplesOutRoot = path.join(outputRoot, 'examples');
125
+ const draftsRoot = path.join(outputRoot, 'drafts');
126
+
127
+ if (!writeFullDrafts) {
128
+ fs.mkdirSync(fieldsOutRoot, { recursive: true });
129
+ fs.mkdirSync(examplesOutRoot, { recursive: true });
130
+ }
131
+
132
+ let partialsWritten = 0;
133
+ let draftsWritten = 0;
134
+ const partialFiles = [];
135
+ const draftFiles = [];
136
+
137
+ for (const [type, items] of Object.entries(dataObj)) {
138
+ if (!Array.isArray(items)) continue;
139
+
140
+ for (const item of items) {
141
+ if (!item.name) continue;
142
+ const name = item.name;
143
+
144
+ if (!writeFullDrafts) {
145
+ // Render fields using the registered “fields” partial
146
+ const fieldsOut = handlebars
147
+ .compile('{{> fields children=config.children}}')(item);
148
+
149
+ // Render examples only if an examples template was provided
150
+ let examplesOut = '';
151
+ if (examplesTemplatePath) {
152
+ examplesOut = handlebars
153
+ .compile('{{> examples examples=examples}}')(item);
154
+ }
155
+
156
+ if (fieldsOut.trim()) {
157
+ const fPath = path.join(fieldsOutRoot, type, `${name}.adoc`);
158
+ fs.mkdirSync(path.dirname(fPath), { recursive: true });
159
+ fs.writeFileSync(fPath, fieldsOut);
160
+ partialsWritten++;
161
+ partialFiles.push(path.relative(process.cwd(), fPath));
162
+ }
163
+
164
+ if (examplesOut.trim()) {
165
+ const ePath = path.join(examplesOutRoot, type, `${name}.adoc`);
166
+ fs.mkdirSync(path.dirname(ePath), { recursive: true });
167
+ fs.writeFileSync(ePath, examplesOut);
168
+ partialsWritten++;
169
+ partialFiles.push(path.relative(process.cwd(), ePath));
170
+ }
171
+ }
172
+
173
+ if (writeFullDrafts) {
174
+ let content;
175
+ try {
176
+ content = compiledTemplate(item);
177
+ } catch (err) {
178
+ throw new Error(`Template render failed for component "${name}": ${err.message}`);
179
+ }
180
+
181
+ const draftSubdir = name === 'gateway'
182
+ ? path.join(draftsRoot, 'cloud-only')
183
+ : draftsRoot;
184
+
185
+ const destFile = path.join(draftSubdir, `${name}.adoc`);
186
+ fs.mkdirSync(path.dirname(destFile), { recursive: true });
187
+ fs.writeFileSync(destFile, content, 'utf8');
188
+ draftsWritten++;
189
+ draftFiles.push(path.relative(process.cwd(), destFile));
190
+ }
191
+ }
192
+ }
193
+
194
+ return {
195
+ partialsWritten,
196
+ draftsWritten,
197
+ partialFiles,
198
+ draftFiles
199
+ };
200
+ }
201
+
202
+ module.exports = {
203
+ generateRpcnConnectorDocs,
204
+ mergeOverrides
205
+ };
@@ -0,0 +1,17 @@
1
+ const buildConfigYaml = require('./buildConfigYaml.js');
2
+ const handlebars = require('handlebars');
3
+
4
+ /**
5
+ * Handlebars helper “advancedConfig”. Omits only deprecated.
6
+ *
7
+ * Usage in template:
8
+ * {{advancedConfig this.type this.name this.config.children}}
9
+ */
10
+ module.exports = function advancedConfig(type, connectorName, children) {
11
+ if (typeof type !== 'string' || typeof connectorName !== 'string' || !Array.isArray(children)) {
12
+ return '';
13
+ }
14
+
15
+ const yamlText = buildConfigYaml(type, connectorName, children, /*includeAdvanced=*/ true);
16
+ return new handlebars.SafeString(yamlText);
17
+ }
@@ -0,0 +1,53 @@
1
+ const renderLeafField = require('./renderLeafField');
2
+ const renderObjectField = require('./renderObjectField');
3
+
4
+ /**
5
+ * Builds either “Common” or “Advanced” YAML for one connector.
6
+ *
7
+ * - type = “input” or “output” (or whatever type)
8
+ * - connectorName = such as “amqp_1”
9
+ * - children = the array of field‐definitions (entry.config.children)
10
+ * - includeAdvanced = if false → only fields where is_advanced !== true
11
+ * if true → all fields (except deprecated)
12
+ *
13
+ * Structure produced:
14
+ *
15
+ * type:
16
+ * label: ""
17
+ * connectorName:
18
+ * ...child fields (with comments for “no default”)
19
+ */
20
+ module.exports = function buildConfigYaml(type, connectorName, children, includeAdvanced) {
21
+ const lines = [];
22
+
23
+ // “type:” top‐level
24
+ lines.push(`${type}:`);
25
+
26
+ // Two‐space indent for “label”
27
+ lines.push(` label: ""`);
28
+
29
+ // Two‐space indent for connectorName heading
30
+ lines.push(` ${connectorName}:`);
31
+
32
+ // Four‐space indent for children
33
+ const baseIndent = 4;
34
+ children.forEach(field => {
35
+ if (field.is_deprecated) {
36
+ return; // skip deprecated fields
37
+ }
38
+ if (!includeAdvanced && field.is_advanced) {
39
+ return; // skip advanced fields in “common” mode
40
+ }
41
+
42
+ if (field.type === 'object' && Array.isArray(field.children)) {
43
+ // Render nested object
44
+ const nestedLines = renderObjectField(field, baseIndent);
45
+ lines.push(...nestedLines);
46
+ } else {
47
+ // Render a scalar or array leaf
48
+ lines.push(renderLeafField(field, baseIndent));
49
+ }
50
+ });
51
+
52
+ return lines.join('\n');
53
+ }
@@ -0,0 +1,31 @@
1
+ const buildConfigYaml = require('./buildConfigYaml.js');
2
+ const handlebars = require('handlebars');
3
+
4
+ /**
5
+ * Handlebars helper “commonConfig”. Omits deprecated + advanced.
6
+ *
7
+ * Usage in template:
8
+ * {{commonConfig this.type this.name this.config.children}}
9
+ */
10
+ module.exports = function commonConfig(type, connectorName, children) {
11
+ if (typeof type !== 'string' || !type.trim()) {
12
+ console.warn('commonConfig: type must be a non-empty string');
13
+ return '';
14
+ }
15
+ if (typeof connectorName !== 'string' || !connectorName.trim()) {
16
+ console.warn('commonConfig: connectorName must be a non-empty string');
17
+ return '';
18
+ }
19
+ if (!Array.isArray(children)) {
20
+ console.warn('commonConfig: children must be an array');
21
+ return '';
22
+ }
23
+
24
+ try {
25
+ const yamlText = buildConfigYaml(type, connectorName, children, /*includeAdvanced=*/ false);
26
+ return new handlebars.SafeString(yamlText);
27
+ } catch (error) {
28
+ console.error('Error in commonConfig helper:', error);
29
+ return new handlebars.SafeString('<!-- Error generating configuration -->');
30
+ }
31
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Checks if two values are equal.
3
+ *
4
+ * @param {*} a - The first value.
5
+ * @param {*} b - The second value.
6
+ * @returns {boolean} True if the values are equal.
7
+ */
8
+ module.exports = function eq(a, b) {
9
+ return a === b;
10
+ }
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ uppercase: require('./uppercase.js'),
5
+ eq: require('./eq.js'),
6
+ ne: require('./ne.js'),
7
+ join: require('./join.js'),
8
+ or: require('./or.js'),
9
+ toYaml: require('./toYaml.js'),
10
+ isObject: require('./isObject.js'),
11
+ renderYamlList: require('./renderYamlList.js'),
12
+ renderConnectFields: require('./renderConnectFields.js'),
13
+ renderConnectExamples: require('./renderConnectExamples.js'),
14
+ renderLeafField: require('./renderLeafField.js'),
15
+ renderObjectField: require('./renderObjectField.js'),
16
+ buildConfigYaml: require('./buildConfigYaml.js'),
17
+ commonConfig: require('./commonConfig.js'),
18
+ advancedConfig: require('./advancedConfig.js'),
19
+ };
@@ -0,0 +1 @@
1
+ module.exports = v => v !== null && typeof v === 'object' && !Array.isArray(v)
@@ -0,0 +1,6 @@
1
+ module.exports = function join(array, separator) {
2
+ if (!Array.isArray(array)) {
3
+ return '';
4
+ }
5
+ return array.join(separator);
6
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Checks if two values are not equal.
3
+ *
4
+ * @param {*} a - The first value.
5
+ * @param {*} b - The second value.
6
+ * @returns {boolean} True if the values are not equal.
7
+ */
8
+ module.exports = function ne(a, b) {
9
+ return a !== b;
10
+ }
@@ -0,0 +1,4 @@
1
+ module.exports = function (...args) {
2
+ const options = args.pop(); // Last argument is always the options object
3
+ return args.some(Boolean);
4
+ };
@@ -0,0 +1,37 @@
1
+ const handlebars = require('handlebars');
2
+
3
+ /**
4
+ * Renders a list of examples.
5
+ *
6
+ * @param {Array<Object>} examples - An array of example objects.
7
+ * @returns {handlebars.SafeString} The rendered SafeString containing the examples.
8
+ */
9
+ module.exports = function renderConnectExamples(examples) {
10
+ if (!examples || !Array.isArray(examples) || examples.length === 0) {
11
+ return '';
12
+ }
13
+ let output = '';
14
+ examples.forEach(example => {
15
+ if (example.title) {
16
+ const sanitizedTitle = example.title.replace(/[=]/g, '\\=');
17
+ output += `=== ${sanitizedTitle}\n\n`;
18
+ }
19
+ if (example.summary) {
20
+ output += `${example.summary}\n\n`;
21
+ }
22
+ if (example.config) {
23
+ if (typeof example.config !== 'string') {
24
+ console.warn('Example config must be a string, skipping');
25
+ return;
26
+ }
27
+ const configContent = example.config.trim();
28
+ if (configContent.includes('----')) {
29
+ console.warn('Example config contains AsciiDoc delimiters, this may break rendering');
30
+ }
31
+ output += '[source,yaml]\n----\n';
32
+ output += configContent + '\n';
33
+ output += '----\n\n';
34
+ }
35
+ });
36
+ return new handlebars.SafeString(output);
37
+ }