This is an automated email from the ASF dual-hosted git repository.
SvenO3 pushed a commit to branch
4466-add-validation-and-naming-warnings-for-property-field-names-in-adapter-schema-configuration
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to
refs/heads/4466-add-validation-and-naming-warnings-for-property-field-names-in-adapter-schema-configuration
by this push:
new d9380d3848 Add errors and warnings for invalid field names
d9380d3848 is described below
commit d9380d384864f3332c23e39dbb512158d1758752
Author: Sven Oehler <[email protected]>
AuthorDate: Thu Jun 25 17:59:55 2026 +0200
Add errors and warnings for invalid field names
---
.../configure-schema.component.html | 46 ++++++++++++
.../configure-schema/configure-schema.component.ts | 22 +++++-
.../configure-schema/field-name-validation.ts | 87 ++++++++++++++++++++++
3 files changed, 154 insertions(+), 1 deletion(-)
diff --git
a/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.html
b/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.html
index 3b3be24a73..a5ac876f60 100644
---
a/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.html
+++
b/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.html
@@ -16,6 +16,52 @@
~
-->
<div fxFlex="100" fxLayout="column">
+ @if (invalidFieldNames().length > 0) {
+ <sp-alert-banner
+ type="error"
+ [title]="'Invalid field names' | translate"
+ [description]="
+ 'Field names containing comma (,), double quote ("), or
semicolon (;) are invalid and must be renamed before continuing.'
+ | translate
+ "
+ data-cy="configure-schema-invalid-field-names"
+ >
+ <div class="mt-md">
+ @for (fieldName of invalidFieldNames(); track fieldName) {
+ <div
+ class="font-bold text-sm"
+ data-cy="configure-schema-invalid-field-name"
+ >
+ {{ fieldName }}
+ </div>
+ }
+ </div>
+ </sp-alert-banner>
+ }
+
+ @if (warningFieldNames().length > 0) {
+ <sp-alert-banner
+ type="warning"
+ [title]="'Field name recommendation' | translate"
+ [description]="
+ 'It is recommended to use a consistent naming convention for
field names without special characters, except - and _.'
+ | translate
+ "
+ data-cy="configure-schema-warning-field-names"
+ >
+ <div class="mt-md">
+ @for (fieldName of warningFieldNames(); track fieldName) {
+ <div
+ class="font-bold text-sm"
+ data-cy="configure-schema-warning-field-name"
+ >
+ {{ fieldName }}
+ </div>
+ }
+ </div>
+ </sp-alert-banner>
+ }
+
<div fxFlex="100" fxLayout="column">
<sp-adapter-script-editor
[scriptActive]="scriptActive()"
diff --git
a/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.ts
b/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.ts
index afc0eb52c3..c663040b38 100644
---
a/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.ts
+++
b/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.ts
@@ -38,6 +38,7 @@ import {
ConfirmDialogComponent,
DialogService,
PanelType,
+ SpAlertBannerComponent,
} from '@streampipes/shared-ui';
import { CreateAdapterTransformationTemplateDialogComponent } from
'../../../dialog/create-adapter-transformation-template-dialog/create-adapter-transformation-template-dialog.component';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
@@ -57,6 +58,7 @@ import { AdapterSamplePreviewComponent } from
'./sample-preview/adapter-sample-p
import { AdapterResultPreviewComponent } from
'./result-preview/adapter-result-preview.component';
import { MatButton } from '@angular/material/button';
import type { editor as MonacoEditor } from 'monaco-editor';
+import { validateFieldNames } from './field-name-validation';
@Component({
selector: 'sp-configure-schema',
@@ -72,6 +74,7 @@ import type { editor as MonacoEditor } from 'monaco-editor';
LayoutAlignDirective,
MatButton,
TranslatePipe,
+ SpAlertBannerComponent,
],
})
export class ConfigureSchemaComponent implements OnInit {
@@ -147,6 +150,22 @@ export class ConfigureSchemaComponent implements OnInit {
?.outputs?.[0] || {},
);
+ schemaEvent = computed(() =>
+ this.scriptActive() ? this.output() : this.input(),
+ );
+
+ fieldNameValidation = computed(() =>
+ validateFieldNames(this.schemaEvent()),
+ );
+
+ invalidFieldNames = computed(
+ () => this.fieldNameValidation().invalidFieldNames,
+ );
+
+ warningFieldNames = computed(
+ () => this.fieldNameValidation().warningFieldNames,
+ );
+
isNextDisabled = computed(() => {
const state = this.stateService.state();
const hasInputEvents =
@@ -158,7 +177,8 @@ export class ConfigureSchemaComponent implements OnInit {
state.isRunningScript ||
!!state.sampleError ||
!!state.scriptError ||
- !hasInputEvents
+ !hasInputEvents ||
+ this.invalidFieldNames().length > 0
);
});
diff --git
a/ui/src/app/connect/components/adapter-configuration/configure-schema/field-name-validation.ts
b/ui/src/app/connect/components/adapter-configuration/configure-schema/field-name-validation.ts
new file mode 100644
index 0000000000..af4d86b73f
--- /dev/null
+++
b/ui/src/app/connect/components/adapter-configuration/configure-schema/field-name-validation.ts
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+export interface FieldNameValidationResult {
+ invalidFieldNames: string[];
+ warningFieldNames: string[];
+}
+
+const INVALID_FIELD_NAME_CHARACTERS_REGEX = /[,";]/;
+const RECOMMENDED_FIELD_NAME_REGEX = /^[A-Za-z0-9_-]+$/;
+
+export function validateFieldNames(event: unknown): FieldNameValidationResult {
+ const invalidFieldNames = new Set<string>();
+ const warningFieldNames = new Set<string>();
+
+ validateFieldNamesRecursively(
+ event,
+ '',
+ invalidFieldNames,
+ warningFieldNames,
+ );
+
+ return {
+ invalidFieldNames: Array.from(invalidFieldNames),
+ warningFieldNames: Array.from(warningFieldNames),
+ };
+}
+
+function validateFieldNamesRecursively(
+ value: unknown,
+ currentPath: string,
+ invalidFieldNames: Set<string>,
+ warningFieldNames: Set<string>,
+): void {
+ if (Array.isArray(value)) {
+ value.forEach(item =>
+ validateFieldNamesRecursively(
+ item,
+ currentPath ? `${currentPath}[]` : '[]',
+ invalidFieldNames,
+ warningFieldNames,
+ ),
+ );
+ } else if (isRecord(value)) {
+ Object.entries(value).forEach(([fieldName, fieldValue]) => {
+ const fieldPath = currentPath
+ ? `${currentPath}.${fieldName}`
+ : fieldName;
+
+ if (INVALID_FIELD_NAME_CHARACTERS_REGEX.test(fieldName)) {
+ invalidFieldNames.add(fieldPath);
+ } else if (!RECOMMENDED_FIELD_NAME_REGEX.test(fieldName)) {
+ warningFieldNames.add(fieldPath);
+ }
+
+ validateFieldNamesRecursively(
+ fieldValue,
+ fieldPath,
+ invalidFieldNames,
+ warningFieldNames,
+ );
+ });
+ }
+}
+
+function isRecord(value: unknown): value is Record<string, unknown> {
+ return (
+ value !== null &&
+ typeof value === 'object' &&
+ Object.prototype.toString.call(value) === '[object Object]'
+ );
+}