@things-factory/integration-base 9.0.4 → 9.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/engine/task/publish.js +4 -1
- package/dist-server/engine/task/publish.js.map +1 -1
- package/dist-server/engine/task/state-read.js +4 -1
- package/dist-server/engine/task/state-read.js.map +1 -1
- package/dist-server/engine/task/state-write.js +4 -1
- package/dist-server/engine/task/state-write.js.map +1 -1
- package/dist-server/engine/task/utils/substitute-multi.d.ts +7 -0
- package/dist-server/engine/task/utils/substitute-multi.js +37 -0
- package/dist-server/engine/task/utils/substitute-multi.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/integration/task/publish.ja.md +46 -8
- package/helps/integration/task/publish.ko.md +40 -2
- package/helps/integration/task/publish.md +42 -4
- package/helps/integration/task/publish.ms.md +42 -4
- package/helps/integration/task/publish.zh.md +45 -4
- package/helps/integration/task/state-read.ja.md +42 -2
- package/helps/integration/task/state-read.ko.md +42 -2
- package/helps/integration/task/state-read.md +42 -2
- package/helps/integration/task/state-read.ms.md +42 -2
- package/helps/integration/task/state-read.zh.md +42 -2
- package/helps/integration/task/state-write.ja.md +43 -0
- package/helps/integration/task/state-write.ko.md +43 -0
- package/helps/integration/task/state-write.md +46 -3
- package/helps/integration/task/state-write.ms.md +43 -0
- package/helps/integration/task/state-write.zh.md +44 -1
- package/package.json +10 -10
@@ -2,13 +2,16 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const utils_1 = require("@things-factory/utils");
|
4
4
|
const task_registry_1 = require("../task-registry");
|
5
|
+
const substitute_multi_1 = require("./utils/substitute-multi");
|
5
6
|
async function Publish(step, { logger, publish, data }) {
|
6
7
|
var { params: { tag, accessor } } = step;
|
7
8
|
if (!tag || !accessor) {
|
8
9
|
throw Error(`tag and accessor should be defined: tag - '${tag}', accessor - '${accessor}'`);
|
9
10
|
}
|
11
|
+
// Support dynamic tag substitution using #{...}, ${...}, {{...}} patterns
|
12
|
+
const dynamicTag = (0, substitute_multi_1.substituteMulti)(tag, data);
|
10
13
|
var value = (0, utils_1.access)(accessor, data);
|
11
|
-
publish(
|
14
|
+
publish(dynamicTag, value);
|
12
15
|
return {
|
13
16
|
data: value
|
14
17
|
};
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../server/engine/task/publish.ts"],"names":[],"mappings":";;AAAA,iDAA8C;AAC9C,oDAA+C;
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../server/engine/task/publish.ts"],"names":[],"mappings":";;AAAA,iDAA8C;AAC9C,oDAA+C;AAG/C,+DAA0D;AAE1D,KAAK,UAAU,OAAO,CAAC,IAAe,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAW;IACxE,IAAI,EACF,MAAM,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,EAC1B,GAAG,IAAI,CAAA;IAER,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,MAAM,KAAK,CAAC,8CAA8C,GAAG,kBAAkB,QAAQ,GAAG,CAAC,CAAA;IAC7F,CAAC;IAED,0EAA0E;IAC1E,MAAM,UAAU,GAAG,IAAA,kCAAe,EAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAE7C,IAAI,KAAK,GAAG,IAAA,cAAM,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAElC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;IAE1B,OAAO;QACL,IAAI,EAAE,KAAK;KACZ,CAAA;AACH,CAAC;AAED,OAAO,CAAC,aAAa,GAAG;IACtB;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,KAAK;KACb;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;KAClB;CACF,CAAA;AAED,OAAO,CAAC,aAAa,GAAG,IAAI,CAAA;AAC5B,OAAO,CAAC,IAAI,GAAG,0BAA0B,CAAA;AAEzC,4BAAY,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA","sourcesContent":["import { access } from '@things-factory/utils'\nimport { TaskRegistry } from '../task-registry'\nimport { InputStep } from '../../service/step/step-type'\nimport { Context } from '../types'\nimport { substituteMulti } from './utils/substitute-multi'\n\nasync function Publish(step: InputStep, { logger, publish, data }: Context) {\n var {\n params: { tag, accessor }\n } = step\n\n if (!tag || !accessor) {\n throw Error(`tag and accessor should be defined: tag - '${tag}', accessor - '${accessor}'`)\n }\n\n // Support dynamic tag substitution using #{...}, ${...}, {{...}} patterns\n const dynamicTag = substituteMulti(tag, data)\n\n var value = access(accessor, data)\n\n publish(dynamicTag, value)\n\n return {\n data: value\n }\n}\n\nPublish.parameterSpec = [\n {\n type: 'string',\n name: 'tag',\n label: 'tag'\n },\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n }\n]\n\nPublish.connectorFree = true\nPublish.help = 'integration/task/publish'\n\nTaskRegistry.registerTaskHandler('publish', Publish)\n"]}
|
@@ -3,11 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
4
4
|
const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
|
5
5
|
const task_registry_1 = require("../task-registry");
|
6
|
+
const substitute_multi_1 = require("./utils/substitute-multi");
|
6
7
|
async function StateRead(step, { logger, publish, data, domain, user, client }) {
|
7
8
|
var { params: { name } } = step;
|
8
9
|
if (!name) {
|
9
10
|
throw Error(`name should be defined: name - '${name}'`);
|
10
11
|
}
|
12
|
+
// Support dynamic name substitution using #{...}, ${...}, {{...}} patterns
|
13
|
+
const dynamicName = (0, substitute_multi_1.substituteMulti)(name, data);
|
11
14
|
var { data: queryResult, errors } = await client.query({
|
12
15
|
query: (0, graphql_tag_1.default) `
|
13
16
|
query ($name: String!) {
|
@@ -17,7 +20,7 @@ async function StateRead(step, { logger, publish, data, domain, user, client })
|
|
17
20
|
}
|
18
21
|
`,
|
19
22
|
variables: {
|
20
|
-
name
|
23
|
+
name: dynamicName
|
21
24
|
},
|
22
25
|
context: {
|
23
26
|
state: {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"state-read.js","sourceRoot":"","sources":["../../../server/engine/task/state-read.ts"],"names":[],"mappings":";;;AAAA,sEAA6B;AAC7B,oDAA+C;
|
1
|
+
{"version":3,"file":"state-read.js","sourceRoot":"","sources":["../../../server/engine/task/state-read.ts"],"names":[],"mappings":";;;AAAA,sEAA6B;AAC7B,oDAA+C;AAG/C,+DAA0D;AAE1D,KAAK,UAAU,SAAS,CAAC,IAAe,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAW;IAChG,IAAI,EACF,MAAM,EAAE,EAAE,IAAI,EAAE,EACjB,GAAG,IAAI,CAAA;IAER,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,KAAK,CAAC,mCAAmC,IAAI,GAAG,CAAC,CAAA;IACzD,CAAC;IAED,2EAA2E;IAC3E,MAAM,WAAW,GAAG,IAAA,kCAAe,EAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAE/C,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QACrD,KAAK,EAAE,IAAA,qBAAG,EAAA;;;;;;KAMT;QACD,SAAS,EAAE;YACT,IAAI,EAAE,WAAW;SAClB;QACD,OAAO,EAAE;YACP,KAAK,EAAE;gBACL,MAAM;gBACN,IAAI;aACL;SACF;KACF,CAAC,CAAA;IAEF,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACrB,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK;KAC9C,CAAA;AACH,CAAC;AAED,SAAS,CAAC,aAAa,GAAG;IACxB;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;KACd;CACF,CAAA;AAED,SAAS,CAAC,aAAa,GAAG,IAAI,CAAA;AAC9B,SAAS,CAAC,IAAI,GAAG,6BAA6B,CAAA;AAE9C,4BAAY,CAAC,mBAAmB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA","sourcesContent":["import gql from 'graphql-tag'\nimport { TaskRegistry } from '../task-registry'\nimport { InputStep } from '../../service/step/step-type'\nimport { Context } from '../types'\nimport { substituteMulti } from './utils/substitute-multi'\n\nasync function StateRead(step: InputStep, { logger, publish, data, domain, user, client }: Context) {\n var {\n params: { name }\n } = step\n\n if (!name) {\n throw Error(`name should be defined: name - '${name}'`)\n }\n\n // Support dynamic name substitution using #{...}, ${...}, {{...}} patterns\n const dynamicName = substituteMulti(name, data)\n\n var { data: queryResult, errors } = await client.query({\n query: gql`\n query ($name: String!) {\n stateRegisterByName(name: $name) {\n state\n }\n }\n `,\n variables: {\n name: dynamicName\n },\n context: {\n state: {\n domain,\n user\n }\n }\n })\n\n if (errors) {\n errors.forEach(error => {\n logger.error('GraphQL Error: %s', error)\n })\n }\n\n return {\n data: queryResult?.stateRegisterByName?.state\n }\n}\n\nStateRead.parameterSpec = [\n {\n type: 'string',\n name: 'name',\n label: 'name'\n }\n]\n\nStateRead.connectorFree = true\nStateRead.help = 'integration/task/state-read'\n\nTaskRegistry.registerTaskHandler('state-read', StateRead)\n"]}
|
@@ -4,11 +4,14 @@ const tslib_1 = require("tslib");
|
|
4
4
|
const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
|
5
5
|
const utils_1 = require("@things-factory/utils");
|
6
6
|
const task_registry_1 = require("../task-registry");
|
7
|
+
const substitute_multi_1 = require("./utils/substitute-multi");
|
7
8
|
async function StateWrite(step, { logger, publish, data, domain, user, client }) {
|
8
9
|
var { params: { name, accessor } } = step;
|
9
10
|
if (!name || !accessor) {
|
10
11
|
throw Error(`name and accessor should be defined: name - '${name}', accessor - '${accessor}'`);
|
11
12
|
}
|
13
|
+
// Support dynamic name substitution using #{...}, ${...}, {{...}} patterns
|
14
|
+
const dynamicName = (0, substitute_multi_1.substituteMulti)(name, data);
|
12
15
|
var state = (0, utils_1.access)(accessor, data);
|
13
16
|
var { data: mutateResult, errors } = await client.mutate({
|
14
17
|
mutation: (0, graphql_tag_1.default) `
|
@@ -19,7 +22,7 @@ async function StateWrite(step, { logger, publish, data, domain, user, client })
|
|
19
22
|
}
|
20
23
|
`,
|
21
24
|
variables: {
|
22
|
-
name,
|
25
|
+
name: dynamicName,
|
23
26
|
state
|
24
27
|
},
|
25
28
|
context: {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"state-write.js","sourceRoot":"","sources":["../../../server/engine/task/state-write.ts"],"names":[],"mappings":";;;AAAA,sEAA6B;AAC7B,iDAA8C;AAC9C,oDAA+C;
|
1
|
+
{"version":3,"file":"state-write.js","sourceRoot":"","sources":["../../../server/engine/task/state-write.ts"],"names":[],"mappings":";;;AAAA,sEAA6B;AAC7B,iDAA8C;AAC9C,oDAA+C;AAG/C,+DAA0D;AAE1D,KAAK,UAAU,UAAU,CAAC,IAAe,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAW;IACjG,IAAI,EACF,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAC3B,GAAG,IAAI,CAAA;IAER,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvB,MAAM,KAAK,CAAC,gDAAgD,IAAI,kBAAkB,QAAQ,GAAG,CAAC,CAAA;IAChG,CAAC;IAED,2EAA2E;IAC3E,MAAM,WAAW,GAAG,IAAA,kCAAe,EAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAE/C,IAAI,KAAK,GAAG,IAAA,cAAM,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAElC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;QACvD,QAAQ,EAAE,IAAA,qBAAG,EAAA;;;;;;KAMZ;QACD,SAAS,EAAE;YACT,IAAI,EAAE,WAAW;YACjB,KAAK;SACN;QACD,OAAO,EAAE;YACP,KAAK,EAAE;gBACL,MAAM;gBACN,IAAI;aACL;SACF;KACF,CAAC,CAAA;IAEF,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACrB,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,YAAY,EAAE,yBAAyB,EAAE,KAAK;KACrD,CAAA;AACH,CAAC;AAED,UAAU,CAAC,aAAa,GAAG;IACzB;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;KACd;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;KAClB;CACF,CAAA;AAED,UAAU,CAAC,aAAa,GAAG,IAAI,CAAA;AAC/B,UAAU,CAAC,IAAI,GAAG,8BAA8B,CAAA;AAEhD,4BAAY,CAAC,mBAAmB,CAAC,aAAa,EAAE,UAAU,CAAC,CAAA","sourcesContent":["import gql from 'graphql-tag'\nimport { access } from '@things-factory/utils'\nimport { TaskRegistry } from '../task-registry'\nimport { InputStep } from '../../service/step/step-type'\nimport { Context } from '../types'\nimport { substituteMulti } from './utils/substitute-multi'\n\nasync function StateWrite(step: InputStep, { logger, publish, data, domain, user, client }: Context) {\n var {\n params: { name, accessor }\n } = step\n\n if (!name || !accessor) {\n throw Error(`name and accessor should be defined: name - '${name}', accessor - '${accessor}'`)\n }\n\n // Support dynamic name substitution using #{...}, ${...}, {{...}} patterns\n const dynamicName = substituteMulti(name, data)\n\n var state = access(accessor, data)\n\n var { data: mutateResult, errors } = await client.mutate({\n mutation: gql`\n mutation ($state: Object!, $name: String!) {\n updateStateRegisterByName(state: $state, name: $name) {\n state\n }\n }\n `,\n variables: {\n name: dynamicName,\n state\n },\n context: {\n state: {\n domain,\n user\n }\n }\n })\n\n if (errors) {\n errors.forEach(error => {\n logger.error('GraphQL Error: %s', error)\n })\n }\n\n return {\n data: mutateResult?.updateStateRegisterByName?.state\n }\n}\n\nStateWrite.parameterSpec = [\n {\n type: 'string',\n name: 'name',\n label: 'name'\n },\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n }\n]\n\nStateWrite.connectorFree = true\nStateWrite.help = 'integration/task/state-write'\n\nTaskRegistry.registerTaskHandler('state-write', StateWrite)\n"]}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/**
|
2
|
+
* Multi-pattern substitution utility that supports #{...}, ${...}, and {{...}} patterns
|
3
|
+
* @param value - The string containing substitution patterns
|
4
|
+
* @param data - The data object to extract values from
|
5
|
+
* @returns The string with all patterns substituted
|
6
|
+
*/
|
7
|
+
export declare function substituteMulti(value: any, data: any): string;
|
@@ -0,0 +1,37 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.substituteMulti = substituteMulti;
|
4
|
+
const utils_1 = require("@things-factory/utils");
|
5
|
+
/**
|
6
|
+
* Multi-pattern substitution utility that supports #{...}, ${...}, and {{...}} patterns
|
7
|
+
* @param value - The string containing substitution patterns
|
8
|
+
* @param data - The data object to extract values from
|
9
|
+
* @returns The string with all patterns substituted
|
10
|
+
*/
|
11
|
+
function substituteMulti(value, data) {
|
12
|
+
let text = String(value);
|
13
|
+
// Define patterns for different substitution styles
|
14
|
+
const patterns = [
|
15
|
+
{ regex: /#\{([^}]*)\}/gi, prefix: '#{', suffix: '}' },
|
16
|
+
{ regex: /\$\{([^}]*)\}/gi, prefix: '${', suffix: '}' },
|
17
|
+
{ regex: /\{\{([^}]*)\}\}/gi, prefix: '{{', suffix: '}}' }
|
18
|
+
];
|
19
|
+
patterns.forEach(pattern => {
|
20
|
+
const matches = text.match(pattern.regex);
|
21
|
+
if (matches) {
|
22
|
+
matches.forEach(match => {
|
23
|
+
const accessor = match.slice(2, -2); // Remove prefix and suffix
|
24
|
+
// Validate accessor pattern (only allow dot notation)
|
25
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*$/.test(accessor)) {
|
26
|
+
throw new Error(`Invalid accessor pattern: ${accessor}`);
|
27
|
+
}
|
28
|
+
// Safely access data using the accessor
|
29
|
+
const value = (0, utils_1.access)(accessor, data);
|
30
|
+
const sanitizedValue = String(value || '').replace(/[^a-zA-Z0-9._-]/g, '_');
|
31
|
+
text = text.replace(match, sanitizedValue);
|
32
|
+
});
|
33
|
+
}
|
34
|
+
});
|
35
|
+
return text;
|
36
|
+
}
|
37
|
+
//# sourceMappingURL=substitute-multi.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"substitute-multi.js","sourceRoot":"","sources":["../../../../server/engine/task/utils/substitute-multi.ts"],"names":[],"mappings":";;AAQA,0CA+BC;AAvCD,iDAA8C;AAE9C;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,KAAU,EAAE,IAAS;IACnD,IAAI,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAExB,oDAAoD;IACpD,MAAM,QAAQ,GAAG;QACf,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QACtD,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QACvD,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;KAC3D,CAAA;IAED,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QACzC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACtB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA,CAAC,2BAA2B;gBAE/D,sDAAsD;gBACtD,IAAI,CAAC,qDAAqD,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1E,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,EAAE,CAAC,CAAA;gBAC1D,CAAC;gBAED,wCAAwC;gBACxC,MAAM,KAAK,GAAG,IAAA,cAAM,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;gBACpC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAA;gBAE3E,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,CAAA;YAC5C,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { access } from '@things-factory/utils'\n\n/**\n * Multi-pattern substitution utility that supports #{...}, ${...}, and {{...}} patterns\n * @param value - The string containing substitution patterns\n * @param data - The data object to extract values from\n * @returns The string with all patterns substituted\n */\nexport function substituteMulti(value: any, data: any): string {\n let text = String(value)\n\n // Define patterns for different substitution styles\n const patterns = [\n { regex: /#\\{([^}]*)\\}/gi, prefix: '#{', suffix: '}' },\n { regex: /\\$\\{([^}]*)\\}/gi, prefix: '${', suffix: '}' },\n { regex: /\\{\\{([^}]*)\\}\\}/gi, prefix: '{{', suffix: '}}' }\n ]\n\n patterns.forEach(pattern => {\n const matches = text.match(pattern.regex)\n if (matches) {\n matches.forEach(match => {\n const accessor = match.slice(2, -2) // Remove prefix and suffix\n\n // Validate accessor pattern (only allow dot notation)\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*$/.test(accessor)) {\n throw new Error(`Invalid accessor pattern: ${accessor}`)\n }\n\n // Safely access data using the accessor\n const value = access(accessor, data)\n const sanitizedValue = String(value || '').replace(/[^a-zA-Z0-9._-]/g, '_')\n\n text = text.replace(match, sanitizedValue)\n })\n }\n })\n\n return text\n}\n"]}
|