import { DB_SQL_INITIAL_TEXT, EditorLanguage, FormComponentType, FormItem, InputDataType, Plugin, PluginResponseType, PluginType } from '../../types/index.js'; import { PARAMETERIZED_SQL_DESCRIPTION, PUBLIC_INTEGRATIONS_LOGO_URL, DOCS_BASE_URL } from './constants.js'; import { CONNECTION_METHODS_AND_DISPLAY_NAMES, makeDropdownItem } from './shared/db.js'; import { SqlOperations } from './shared/index.js'; const MicrosoftSQLPluginVersions = { V1: '0.0.1', V2: '0.0.2', V6: '0.0.6', V7: '0.0.7', V8: '0.0.8', V9: '0.0.9', V10: '0.0.10', V11: '0.0.11' }; const BASE_HOST = { label: 'Host', name: 'endpoint.host', componentType: FormComponentType.INPUT_TEXT, placeholder: 'example.database.windows.net', rules: [{ required: true, message: 'Host is required' }] }; const BASE_PORT = { label: 'Port', name: 'endpoint.port', componentType: FormComponentType.INPUT_TEXT, initialValue: '1433', rules: [{ required: true, message: 'Port is required' }] }; const BASE_DATABASE_NAME = { label: 'Database name', name: 'authentication.custom.databaseName.value', componentType: FormComponentType.INPUT_TEXT }; const BASE_DATABASE_USERNAME = { label: 'Database username', name: 'authentication.username', componentType: FormComponentType.INPUT_TEXT }; const BASE_DATABASE_PASSWORD = { label: 'Database password', name: 'authentication.password', componentType: FormComponentType.INPUT_TEXT, dataType: InputDataType.PASSWORD }; const BASE_ENABLE_SSL = { label: 'Enable SSL', name: 'connection.useSsl', initialValue: 'checked', componentType: FormComponentType.CHECKBOX }; export const MicrosoftSQLPlugin: Plugin = { id: 'mssql', name: 'Microsoft SQL Server', moduleName: 'MicrosoftSQLPlugin', modulePath: 'plugins/mssql/MicrosoftSQLPlugin', iconLocation: `${PUBLIC_INTEGRATIONS_LOGO_URL}/mssql.png`, docsUrl: `${DOCS_BASE_URL}/mssql`, type: PluginType.DB, responseType: PluginResponseType.TABLE, hasRawRequest: true, hasMetadata: true, rawRequestName: 'Executed SQL', datasourceTemplate: { sections: [ { name: 'main', items: [ { label: 'Display name', name: 'name', startVersion: MicrosoftSQLPluginVersions.V1, componentType: FormComponentType.INPUT_TEXT, placeholder: 'ProdDB', rules: [{ required: true, message: 'Display name is required' }] }, { label: 'Connection method', name: 'connectionType', startVersion: MicrosoftSQLPluginVersions.V10, componentType: FormComponentType.DROPDOWN, initialValue: 'fields', rules: [{ required: true }], options: Object.entries(CONNECTION_METHODS_AND_DISPLAY_NAMES).map(([value, displayName]) => makeDropdownItem(value, displayName) ) }, { label: 'URI', name: 'connectionUrl', startVersion: MicrosoftSQLPluginVersions.V10, componentType: FormComponentType.INPUT_TEXT, dataType: InputDataType.PASSWORD, // since this can sometimes contain a password placeholder: `Server=[:serverName],[:port];Database=[:database];User Id=[user];Password=[:password];Encrypt=[true/false]`, tooltip: { markdownText: '[Read the docs](https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/connection-string-syntax)' }, rules: [{ required: true, message: 'URI is required' }], display: { show: { connectionType: ['url'] } } }, // HOST { ...BASE_HOST, startVersion: MicrosoftSQLPluginVersions.V1, endVersion: MicrosoftSQLPluginVersions.V9 } as FormItem, { ...BASE_HOST, startVersion: MicrosoftSQLPluginVersions.V10, display: { show: { connectionType: ['fields'] } } } as FormItem, // PORT { ...BASE_PORT, startVersion: MicrosoftSQLPluginVersions.V1, endVersion: MicrosoftSQLPluginVersions.V9 } as FormItem, { ...BASE_PORT, startVersion: MicrosoftSQLPluginVersions.V10, display: { show: { connectionType: ['fields'] } } } as FormItem, // DATABASE NAME { ...BASE_DATABASE_NAME, startVersion: MicrosoftSQLPluginVersions.V1, endVersion: MicrosoftSQLPluginVersions.V9 } as FormItem, { ...BASE_DATABASE_NAME, startVersion: MicrosoftSQLPluginVersions.V10, display: { show: { connectionType: ['fields'] } } } as FormItem, // DATABASE USERNAME { ...BASE_DATABASE_USERNAME, startVersion: MicrosoftSQLPluginVersions.V1, endVersion: MicrosoftSQLPluginVersions.V9 } as FormItem, { ...BASE_DATABASE_USERNAME, startVersion: MicrosoftSQLPluginVersions.V10, display: { show: { connectionType: ['fields'] } } } as FormItem, // DATABASE PASSWORD { ...BASE_DATABASE_PASSWORD, startVersion: MicrosoftSQLPluginVersions.V1, endVersion: MicrosoftSQLPluginVersions.V9 } as FormItem, { ...BASE_DATABASE_PASSWORD, startVersion: MicrosoftSQLPluginVersions.V10, display: { show: { connectionType: ['fields'] } } } as FormItem, // ENABLE SSL { ...BASE_ENABLE_SSL, startVersion: MicrosoftSQLPluginVersions.V1, endVersion: MicrosoftSQLPluginVersions.V9 } as FormItem, { ...BASE_ENABLE_SSL, startVersion: MicrosoftSQLPluginVersions.V10, display: { show: { connectionType: ['fields'] } } } as FormItem ] } ] }, actionTemplate: { sections: [ { name: 'main', items: [ { label: 'Operation', name: 'operation', startVersion: MicrosoftSQLPluginVersions.V7, endVersion: MicrosoftSQLPluginVersions.V8, componentType: FormComponentType.DROPDOWN, options: [ { displayName: 'Run SQL', key: SqlOperations.RUN_SQL, value: SqlOperations.RUN_SQL }, { displayName: 'Update rows with form', key: SqlOperations.UPDATE_ROWS, value: SqlOperations.UPDATE_ROWS } ], initialValue: SqlOperations.RUN_SQL }, { label: 'Operation', name: 'operation', startVersion: MicrosoftSQLPluginVersions.V9, endVersion: MicrosoftSQLPluginVersions.V10, componentType: FormComponentType.DROPDOWN, options: [ { displayName: 'Run SQL', key: SqlOperations.RUN_SQL, value: SqlOperations.RUN_SQL }, { displayName: 'Insert, update, or delete rows with form', key: SqlOperations.UPDATE_ROWS, value: SqlOperations.UPDATE_ROWS } ], initialValue: SqlOperations.RUN_SQL }, { // Only show operation dropdown if UPDATE_ROWS was previously selected // This effectively deprecates UPDATE_ROWS for new actions label: 'Operation', name: 'operation', startVersion: MicrosoftSQLPluginVersions.V11, componentType: FormComponentType.DROPDOWN, options: [ { displayName: 'Run SQL', key: SqlOperations.RUN_SQL, value: SqlOperations.RUN_SQL }, { displayName: 'Insert, update, or delete rows with form', key: SqlOperations.UPDATE_ROWS, value: SqlOperations.UPDATE_ROWS } ], initialValue: SqlOperations.RUN_SQL, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } }, { label: 'Parameters (@PARAM_1, @PARAM_2, ...)', name: 'parameters', startVersion: MicrosoftSQLPluginVersions.V11, ldFlag: 'clark.parameterized-apis.v2.enabled', componentType: FormComponentType.DYNAMIC_INPUT_TEXT, placeholder: '[param1, param2, ...]', tooltip: { markdownText: 'JavaScript expression that evaluates to an array of parameter values. Use `@PARAM_1`, `@PARAM_2`, etc. in your SQL query to reference these parameters.' }, display: { show: { operation: ['undefined', SqlOperations.RUN_SQL] } } }, { label: '', // Query name: 'body', startVersion: MicrosoftSQLPluginVersions.V1, componentType: FormComponentType.CODE_EDITOR, language: EditorLanguage.SQL, initialValue: DB_SQL_INITIAL_TEXT, display: { show: { // Frontend is using string equality checks here operation: ['undefined', SqlOperations.RUN_SQL] } } }, { label: 'Microsoft SQL schema', name: 'schema', startVersion: MicrosoftSQLPluginVersions.V8, componentType: FormComponentType.METADATA_DROPDOWN, placeholder: 'Select a schema', keyAccessor: 'name', valueAccessor: 'name', listAccessor: 'metadata.dbSchema.schemas', displayNameAccessor: 'name', defaultToFirstOption: true, clearDependentFieldsOnChange: ['table'], triggerGetMetadata: true, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } }, rules: [{ required: true, message: 'Schema is required' }], showSearch: true, optionFilterProp: 'value' }, { label: 'Microsoft SQL table', name: 'table', startVersion: MicrosoftSQLPluginVersions.V7, componentType: FormComponentType.METADATA_DROPDOWN, placeholder: 'Select a table', keyAccessor: 'name', valueAccessor: 'name', listAccessor: 'metadata.dbSchema.tables', filterDependency: 'schema', filterFieldName: 'schema', displayNameAccessor: 'name', triggerGetMetadata: true, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } }, rules: [{ required: true, message: 'Table is required' }], showSearch: true, optionFilterProp: 'value' } ] }, { name: 'main2', sectionHeader: 'Step 1 - Match rows', items: [ { label: 'Row matching mode', name: 'useAdvancedMatching', startVersion: MicrosoftSQLPluginVersions.V7, componentType: FormComponentType.DROPDOWN, options: [ { displayName: 'Automatically match against database table primary key', subText: 'Table must have a primary key. Does not allow updates that modify primary key columns.', key: 'auto', value: 'auto' }, { displayName: 'Manually match against any column(s)', subText: 'Use with any column. Allows updates that modify primary key columns.', key: 'advanced', value: 'advanced' } ], initialValue: 'auto', display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } }, { label: 'Primary keys', name: 'primaryKeyDisplay', startVersion: MicrosoftSQLPluginVersions.V7, componentType: FormComponentType.PRIMARY_KEY_DISPLAY, display: { show: { operation: [SqlOperations.UPDATE_ROWS], useAdvancedMatching: ['undefined', 'auto'] } } }, // Group { label: 'Array of original rows to be updated', name: 'oldValues', startVersion: MicrosoftSQLPluginVersions.V7, componentType: FormComponentType.DYNAMIC_INPUT_TEXT, initialValue: '', subHeading: `E.g. for an editable Table, it will be \`{{Table1.editedRows.originalRows}}\``, placeholder: '{{ [{name: “OriginalBilly”, email: “billy@joel.com”}, {name: “OriginalAlice”, email: “a@alice.com”}] }}', tooltip: { markdownText: `Used to identify the Microsoft SQL rows that will be updated.` }, rules: [{ required: true, message: 'Missing required value' }], display: { show: { operation: [SqlOperations.UPDATE_ROWS], useAdvancedMatching: ['advanced'] } } }, { label: 'Microsoft SQL columns to match on', name: 'filterBy', startVersion: MicrosoftSQLPluginVersions.V7, componentType: FormComponentType.FILTER_COLUMNS, tooltip: { markdownText: `Specify which columns are used to find unique matches.` }, rules: [{ required: true, message: 'At least one filter column is required' }], display: { show: { operation: [SqlOperations.UPDATE_ROWS], useAdvancedMatching: ['advanced'] } } } ] }, { name: 'updates', sectionHeader: 'Step 2 - Update matched rows', items: [ { label: 'Rows to insert', name: 'insertedRows', startVersion: MicrosoftSQLPluginVersions.V9, componentType: FormComponentType.DYNAMIC_INPUT_TEXT, initialValue: '', placeholder: '{{ [{name: “Billy”, email: “billy@joel.com”}, {name: “Alice”, email: “a@alice.com”}] }}', subHeading: `E.g for an editable Table, it will be \`{{Table1.editedRows.insertedRows}}\``, tooltip: { markdownText: 'These rows will be inserted' }, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } }, { label: 'Rows to update', name: 'newValues', startVersion: MicrosoftSQLPluginVersions.V7, endVersion: MicrosoftSQLPluginVersions.V8, componentType: FormComponentType.DYNAMIC_INPUT_TEXT, initialValue: '', placeholder: '{{ [{name: “Billy”, email: “billy@joel.com”}, {name: “Alice”, email: “a@alice.com”}] }}', rules: [{ required: true, message: 'Missing required value' }], subHeading: `E.g for an editable Table, it will be \`{{Table1.editedRows.updatedRows}}\``, tooltip: { markdownText: 'Matched rows from Step 1 will be updated to these values' }, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } }, { label: 'Rows to update', name: 'newValues', startVersion: MicrosoftSQLPluginVersions.V9, componentType: FormComponentType.DYNAMIC_INPUT_TEXT, initialValue: '', placeholder: '{{ [{name: “Billy”, email: “billy@joel.com”}, {name: “Alice”, email: “a@alice.com”}] }}', subHeading: `E.g for an editable Table, it will be \`{{Table1.editedRows.updatedRows}}\``, tooltip: { markdownText: 'Matched rows from Step 1 will be updated to these values' }, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } }, { label: 'Rows to delete', name: 'deletedRows', startVersion: MicrosoftSQLPluginVersions.V9, componentType: FormComponentType.DYNAMIC_INPUT_TEXT, initialValue: '', placeholder: '{{ [{name: “Billy”, email: “billy@joel.com”}, {name: “Alice”, email: “a@alice.com”}] }}', subHeading: `E.g for an editable Table, it will be \`{{Table1.editedRows.deletedRows}}\``, tooltip: { markdownText: 'Matched rows from Step 1 will be deleted' }, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } } ] }, { name: 'preview', sectionHeader: 'Step 3 - Match columns', items: [ { label: 'Map JSON keys to MicrosoftSQL columns', name: 'mappingSettingsDisplay', startVersion: MicrosoftSQLPluginVersions.V7, componentType: FormComponentType.KEY_MAPPING, tooltip: { markdownText: 'Used to map JSON keys from the previous steps to Microsoft SQL columns' }, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } }, { label: 'Preview', name: 'preview', startVersion: MicrosoftSQLPluginVersions.V7, endVersion: MicrosoftSQLPluginVersions.V8, componentType: FormComponentType.SQL_PREVIEW, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } }, { label: 'Preview', name: 'preview', startVersion: MicrosoftSQLPluginVersions.V9, componentType: FormComponentType.SQL_PREVIEW_WITH_INSERT_DELETE, display: { show: { operation: [SqlOperations.UPDATE_ROWS] } } } ] }, { name: 'advanced:main', items: [ { label: 'Use parameterized SQL', name: 'usePreparedSql', startVersion: MicrosoftSQLPluginVersions.V6, endVersion: MicrosoftSQLPluginVersions.V10, componentType: FormComponentType.SWITCH, initialValue: true, tooltip: { markdownText: PARAMETERIZED_SQL_DESCRIPTION }, display: { show: { operation: ['undefined', SqlOperations.RUN_SQL] } } }, { label: 'Use parameterized SQL', name: 'usePreparedSql', startVersion: MicrosoftSQLPluginVersions.V11, componentType: FormComponentType.SWITCH, initialValue: true, tooltip: { markdownText: PARAMETERIZED_SQL_DESCRIPTION }, display: { show: { operation: [SqlOperations.RUN_SQL], parameters: ['undefined'] } } } ] } ] } };