Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
325ad1d
refactor(retainer): adapt new conf in retainer
Kinplemelon Nov 3, 2025
5847047
test(schemas): update schemas
Kinplemelon Nov 4, 2025
0b92825
refactor(listener): default value of `parse_unit`
Kinplemelon Nov 4, 2025
2e94ace
refactor(connector): new configs in greptimedb and kafka
Kinplemelon Nov 4, 2025
4c19cb6
refactor(retainer): adapt new conf in retainer
Kinplemelon Nov 3, 2025
bc1780f
chore(dependencies): update @emqx/shared-ui-i18n to version 0.0.57
Kinplemelon Nov 5, 2025
b63a220
test(schemas): optimize function to sort json
Kinplemelon Nov 5, 2025
7cb19b8
refactor(audit log): adapt new api
Kinplemelon Nov 5, 2025
f50254f
feat(plugin): support divider
Kinplemelon Nov 5, 2025
0a4a2c2
test(schemas): optimize sort function
Kinplemelon Nov 5, 2025
386b4f5
Merge branch 'enterprise-1.10.x' into enterprise
Kinplemelon Nov 6, 2025
3f49cd0
test(schemas): update schemas
Kinplemelon Nov 6, 2025
457ff20
fix(connector): hide `allow_auto_topic_creation` for kafka consumer
Kinplemelon Nov 6, 2025
a626ae3
fix(action): desc for `max_linger_time`
Kinplemelon Nov 7, 2025
3300882
fix(message queue): correct disable logic
Kinplemelon Nov 7, 2025
8e21592
Merge branch 'enterprise-1.10.x' into enterprise
Kinplemelon Nov 7, 2025
3cfd480
fix(flow): cannot save after switching editing mode
Kinplemelon Nov 7, 2025
0aee1e6
chore(dependencies): update @emqx/shared-ui-components to version 0.0.14
Kinplemelon Nov 7, 2025
9c8e0c8
refactor(retainer): hide `dispatch_retry_ttl`
Kinplemelon Nov 10, 2025
d68c03a
Merge branch 'enterprise-1.10.x' into enterprise
Kinplemelon Nov 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
},
"dependencies": {
"@element-plus/icons-vue": "^1.1.0",
"@emqx/shared-ui-components": "~0.0.13",
"@emqx/shared-ui-components": "~0.0.14",
"@emqx/shared-ui-constants": "~0.0.5",
"@emqx/shared-ui-i18n": "~0.0.56",
"@emqx/shared-ui-i18n": "~0.0.57",
"@emqx/shared-ui-utils": "~0.0.22",
"@highlightjs/vue-plugin": "^2.1.0",
"@vue-flow/core": "^1.20.1",
Expand Down
20 changes: 10 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 71 additions & 22 deletions scripts/transformer/filterTagsSchema.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { isObject, get, set, isPlainObject } = require('lodash')
const { isObject, get, set, isArray, isPlainObject } = require('lodash')

const paramRefReg = /^#\/components\/parameters\//
const schemaRefReg = /^#\/components\/schemas\//
Expand Down Expand Up @@ -213,37 +213,86 @@ const specialHandlers = new Map([
['Metrics', handleMetricsJSON],
])

const sortStrArr = (arr) => arr.sort((a, b) => a.localeCompare(b))

const sortObj = (rawObj) => {
const sortedKeys = sortStrArr(Object.keys(rawObj))
if (Array.isArray(rawObj)) {
rawObj.forEach((item, index) => {
if (isPlainObject(item) || isArray(item)) {
rawObj[index] = sortObj(item)
} else {
rawObj[index] = item
}
})
return rawObj.sort((a, b) => {
if (isPlainObject(a)) {
return 2
}
if (isPlainObject(b)) {
return -2
}
if (isArray(a)) {
return 1
}
if (isArray(b)) {
return -1
}
return a.toString().localeCompare(b.toString())
})
}
Object.entries(rawObj).forEach(([key, value]) => {
if (isPlainObject(value) || isArray(value)) {
rawObj[key] = sortObj(value)
} else {
rawObj[key] = value
}
})
const sortedKeys = Object.keys(rawObj).sort((pK, nK) => {
return pK.localeCompare(nK.toString())
})
const sortedObj = sortedKeys.reduce((obj, key) => {
obj[key] = rawObj[key]
return obj
}, {})
return sortedObj
}

const sortResult = (swaggerObj) => {
const sortValue = (value) => {
if (Array.isArray(value)) {
const processedArr = value.map(sortValue)
const sortedStrObjArr = sortStrArr(processedArr.map(JSON.stringify))
const getObjIndex = (obj) => {
const strObj = JSON.stringify(obj)
return sortedStrObjArr.indexOf(strObj)
}
return processedArr.sort((a, b) => getObjIndex(a) - getObjIndex(b))
const sortOneofRefs = (oneofRefs) => {
const sortedRefs = oneofRefs.sort((a, b) => {
const aValue = a.$ref || (a.enum && a.enum[0])
const bValue = b.$ref || (b.enum && b.enum[0])
if (aValue && bValue) {
return aValue.localeCompare(bValue)
}
if (isPlainObject(value)) {
Object.entries(value).forEach(([k, v]) => {
value[k] = sortValue(v)
})
return sortObj(value)
}
return value
return 0
})
return sortedRefs
}

const sortDataContent = (data) => {
if (data.content) {
Object.values(data.content).forEach((content) => {
if (content.schema && content.schema.oneOf) {
content.schema.oneOf = sortOneofRefs(content.schema.oneOf)
}
})
}
return sortValue(swaggerObj)
}

const sortResult = (swaggerJSON) => {
const ret = sortObj(swaggerJSON)
const { paths, components } = ret
Object.values(paths).forEach((path) => {
Object.values(path).forEach((method) => {
if (method.responses) {
Object.values(method.responses).forEach((response) => {
sortDataContent(response)
})
}
if (method.requestBody) {
sortDataContent(method.requestBody)
}
})
})
return ret
}

const filterTargetSchema = (swaggerJSON, tag) => {
Expand Down
4 changes: 2 additions & 2 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,12 +386,12 @@ const websocketUnexposedOptions = {
export const unexposedConfigs = {
tcp: {
...defaultUnexposedConfig,
parse_unit: 'chunk',
parse_unit: 'frame',
tcp_options: tcpUnexposedOptions,
},
ssl: {
...defaultUnexposedConfig,
parse_unit: 'chunk',
parse_unit: 'frame',
tcp_options: {
...tcpUnexposedOptions,
},
Expand Down
8 changes: 6 additions & 2 deletions src/components/Oneof.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
<div class="switch-container">
<el-switch
v-model="switchProxy"
:inactive-value="oneOfInfo.valueDisabled as string"
:disabled="disabled"
:inactive-value="(oneOfInfo as any).valueDisabled"
:disabled="disabled || switchDisabled"
/>
<span class="tip" v-if="valueProxy === oneOfInfo.valueDisabled">
{{ disabledLabel || valueProxy }}
Expand Down Expand Up @@ -108,6 +108,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
switchDisabled: {
type: Boolean,
default: false,
},
disabledLabel: {
type: String,
},
Expand Down
3 changes: 3 additions & 0 deletions src/components/PluginsForm/PluginFormKitItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
v-model="bindValue[key]"
/>
</template>
<el-col v-if="formConfigs.divider" :span="24">
<el-divider>{{ formConfigs.dividerLabel }}</el-divider>
</el-col>
</template>

<script lang="ts">
Expand Down
5 changes: 4 additions & 1 deletion src/hooks/Plugins/useRenderPluginForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,10 @@ function replaceI18nInConfigs(
for (const key in configs) {
if (typeof configs[key] === 'object') {
replaceI18nInConfigs(configs[key], i18nConfigs, lang)
} else if (['label', 'description', 'message'].includes(key) && configs[key].startsWith('$')) {
} else if (
['label', 'description', 'message', 'dividerLabel'].includes(key) &&
configs[key].startsWith('$')
) {
const i18nKey = configs[key]
if (i18nConfigs[i18nKey]) {
configs[key] = i18nConfigs[i18nKey][lang]
Expand Down
20 changes: 16 additions & 4 deletions src/hooks/Rule/connector/useSchemaConnectorPropsLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default (

const azureAdvancedProps = [
'health_check_topic',
'allow_auto_topic_creation',
'min_metadata_refresh_interval',
'metadata_request_timeout',
'socket_opts.sndbuf',
Expand Down Expand Up @@ -91,11 +92,21 @@ export default (

const azureOrderMap = {
...createOrderObj(
['bootstrap_hosts', 'authentication', 'authentication.password', 'ssl', 'health_check_topic'],
[
'bootstrap_hosts',
'authentication',
'authentication.password',
'ssl',
'health_check_topic',
'allow_auto_topic_creation',
],
fieldStartIndex,
),
// put health_check_topic at the start
...omit(createOrderObj(azureAdvancedProps, 150), 'health_check_topic'),
...omit(createOrderObj(azureAdvancedProps, 150), [
'health_check_topic',
'allow_auto_topic_creation',
]),
}
const pgSqlOrderMap = createOrderObj(
['server', 'database', 'username', 'password', 'ssl', 'disable_prepared_statements'],
Expand Down Expand Up @@ -225,7 +236,7 @@ export default (
fieldStartIndex,
),
[BridgeType.GreptimeDB]: createOrderObj(
['server', 'dbname', 'username', 'password', 'ssl', 'ttl'],
['server', 'dbname', 'username', 'password', 'ssl', 'ttl', 'ts_column'],
fieldStartIndex,
),
[BridgeType.TDengine]: createOrderObj(
Expand Down Expand Up @@ -349,6 +360,7 @@ export default (
[BridgeType.GCPProducer]: GCPColClass,
[BridgeType.GCPConsumer]: GCPColClass,
[BridgeType.BigQuery]: GCPColClass,
[BridgeType.KafkaConsumer]: { allow_auto_topic_creation: 'col-hidden' },
[BridgeType.MongoDB]: { 'parameters.mongo_type': 'col-hidden' },
[BridgeType.Redis]: { 'parameters.redis_type': 'col-hidden' },
[BridgeType.InfluxDB]: { 'parameters.influxdb_type': 'col-hidden' },
Expand All @@ -375,7 +387,7 @@ export default (
[BridgeType.PgSQL]: pgSqlAdvancedFields,
[BridgeType.TimescaleDB]: pgSqlAdvancedFields,
[BridgeType.MatrixDB]: pgSqlAdvancedFields,
[BridgeType.GreptimeDB]: ['ttl'],
[BridgeType.GreptimeDB]: ['ttl', 'ts_column'],
[BridgeType.AlloyDB]: pgSqlAdvancedFields,
[BridgeType.CockroachDB]: pgSqlAdvancedFields,
[BridgeType.Redshift]: pgSqlAdvancedFields,
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ export default {
zh: '派发保留消息的最大速率',
en: 'The maximum rate of delivering retained messages',
},
dispatchRetryTtl: {
zh: '派发重试 TTL',
en: 'Dispatch retry TTL',
},
dispatchRetryTtlDesc: {
zh: '指定 EMQX 向单个订阅投递保留消息的最大时间。一旦达到时间限制,即使有额外的保留消息匹配订阅,投递过程也将停止。',
en: 'This option specifies the maximum amount of time EMQX will spend delivering retained messages to a single subscription. Once the time limit is reached, the dispatch process is stopped — even if additional retained messages match the subscription.',
},
maxPublishRate: {
zh: '最大发布速率',
en: 'Max Publish Rate',
Expand Down
3 changes: 3 additions & 0 deletions src/schemaText/actionText/action-desc-en.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"common": {
"max_linger_time": "Maximum duration for a per-partition producer to wait for messages in order to collect a batch to buffer.<br/>The default value <code>0</code> means no wait. For non-memory buffer mode, it's advised to configure at least <code>5ms</code> for less IOPS. <br/>There is no linger time when writing to memory buffer."
},
"mqtt": {
"source_topic": "Message subscription topics support the use of + and # wildcards. When EMQX is running in cluster mode or the connector is configured with a connection pool, shared subscriptions must be used to avoid message duplication."
},
Expand Down
3 changes: 3 additions & 0 deletions src/schemaText/actionText/action-desc-zh.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"common": {
"max_linger_time": "每个分区生产者,等待收集消息以形成批次的最长时间。<br/>默认值 <code>0</code> 表示不等待。对于非内存缓冲模式,建议至少配置 <code>5ms</code> 以减少 I/O 操作。<br/>在写入内存缓冲区时没有等待时间。"
},
"mqtt": {
"source_topic": "消息订阅主题,支持使用 + 和 # 通配符。当 EMQX 运行在集群模式下或连接器配置了连接池时,为了避免消息重复,必须使用共享订阅。"
},
Expand Down
1 change: 1 addition & 0 deletions src/types/extension.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface Retainer {
storage_type: string
max_retained_messages: number
}
// dispatch_retry_ttl: string
}

export interface RetainerMessage {
Expand Down
2 changes: 2 additions & 0 deletions src/types/plugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ interface ConfigField {
rules?: Rule[]
options?: ConfigOption[]
type?: AvroType
divider?: boolean
dividerLabel?: string
items?: {
[key: string]: {
label: string
Expand Down
Loading
Loading