From f4e73fae799e541594ab380d26dcc66c36900b37 Mon Sep 17 00:00:00 2001 From: Zehao Zhang Date: Fri, 17 Jan 2025 15:28:25 +0800 Subject: [PATCH 01/19] feat: entities redis configuration base --- .../entities-redis-configurations/LICENSE | 201 ++++++++++++++++++ .../entities-redis-configurations/README.md | 31 +++ .../package.json | 69 ++++++ .../sandbox/App.vue | 21 ++ .../sandbox/index.html | 25 +++ .../sandbox/index.ts | 31 +++ .../sandbox/pages/HomePage.vue | 9 + .../pages/RedisConfigurationFormPage.vue | 21 ++ .../sandbox/tsconfig.json | 18 ++ .../src/components/RedisConfigurationForm.vue | 79 +++++++ .../src/composables/index.ts | 6 + .../src/composables/useI18n.ts | 16 ++ .../src/global-components.d.ts | 2 + .../src/index.ts | 17 ++ .../src/locales/en.json | 23 ++ .../src/types/index.ts | 3 + .../tsconfig.build.json | 12 ++ .../tsconfig.json | 23 ++ .../vite.config.ts | 30 +++ .../src/types/entity-base-config-card.ts | 1 + pnpm-lock.yaml | 44 ++++ 21 files changed, 682 insertions(+) create mode 100644 packages/entities/entities-redis-configurations/LICENSE create mode 100644 packages/entities/entities-redis-configurations/README.md create mode 100644 packages/entities/entities-redis-configurations/package.json create mode 100644 packages/entities/entities-redis-configurations/sandbox/App.vue create mode 100644 packages/entities/entities-redis-configurations/sandbox/index.html create mode 100644 packages/entities/entities-redis-configurations/sandbox/index.ts create mode 100644 packages/entities/entities-redis-configurations/sandbox/pages/HomePage.vue create mode 100644 packages/entities/entities-redis-configurations/sandbox/pages/RedisConfigurationFormPage.vue create mode 100644 packages/entities/entities-redis-configurations/sandbox/tsconfig.json create mode 100644 packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue create mode 100644 packages/entities/entities-redis-configurations/src/composables/index.ts create mode 100644 packages/entities/entities-redis-configurations/src/composables/useI18n.ts create mode 100644 packages/entities/entities-redis-configurations/src/global-components.d.ts create mode 100644 packages/entities/entities-redis-configurations/src/index.ts create mode 100644 packages/entities/entities-redis-configurations/src/locales/en.json create mode 100644 packages/entities/entities-redis-configurations/src/types/index.ts create mode 100644 packages/entities/entities-redis-configurations/tsconfig.build.json create mode 100644 packages/entities/entities-redis-configurations/tsconfig.json create mode 100644 packages/entities/entities-redis-configurations/vite.config.ts diff --git a/packages/entities/entities-redis-configurations/LICENSE b/packages/entities/entities-redis-configurations/LICENSE new file mode 100644 index 0000000000..b45e572c88 --- /dev/null +++ b/packages/entities/entities-redis-configurations/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 Kong, Inc. + + Licensed 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. diff --git a/packages/entities/entities-redis-configurations/README.md b/packages/entities/entities-redis-configurations/README.md new file mode 100644 index 0000000000..6e22857a2d --- /dev/null +++ b/packages/entities/entities-redis-configurations/README.md @@ -0,0 +1,31 @@ +# @kong-ui-public/entities-redis-configurations + +{A description of this package} + +- [Features](#features) +- [Requirements](#requirements) +- [Usage](#usage) + - [Install](#install) + - [Props](#props) + +## Features + +- List of package features + +## Requirements + +- List of package requirements (e.g. "`vue` and must be initialized in the host application") + +## Usage + +### Install + +{Installation instructions} + +### Props + +#### `example` + +- type: `Boolean` +- required: `false` +- default: `false` diff --git a/packages/entities/entities-redis-configurations/package.json b/packages/entities/entities-redis-configurations/package.json new file mode 100644 index 0000000000..dc3961f8d7 --- /dev/null +++ b/packages/entities/entities-redis-configurations/package.json @@ -0,0 +1,69 @@ +{ + "name": "@kong-ui-public/entities-redis-configurations", + "version": "0.0.1", + "type": "module", + "main": "./dist/entities-redis-configurations.umd.js", + "module": "./dist/entities-redis-configurations.es.js", + "types": "dist/types/index.d.ts", + "files": [ + "dist" + ], + "exports": { + ".": { + "import": "./dist/entities-redis-configurations.es.js", + "require": "./dist/entities-redis-configurations.umd.js", + "types": "./dist/types/index.d.ts" + }, + "./package.json": "./package.json", + "./dist/*": "./dist/*" + }, + "publishConfig": { + "access": "public" + }, + "scripts": { + "dev": "cross-env USE_SANDBOX=true vite", + "build": "run-s typecheck build:package build:types", + "build:package": "vite build -m production", + "build:analyzer": "BUILD_VISUALIZER='entities/entities-redis-configurations' vite build -m production", + "build:types": "vue-tsc -p './tsconfig.build.json' --emitDeclarationOnly", + "build:sandbox": "cross-env USE_SANDBOX=true vite build -m production", + "preview": "cross-env USE_SANDBOX=true vite preview", + "lint": "eslint", + "lint:fix": "eslint --fix", + "stylelint": "stylelint --allow-empty-input './src/**/*.{css,scss,sass,less,styl,vue}'", + "stylelint:fix": "stylelint --allow-empty-input './src/**/*.{css,scss,sass,less,styl,vue}' --fix", + "typecheck": "vue-tsc -p './tsconfig.build.json' --noEmit", + "test:component": "BABEL_ENV=cypress cross-env FORCE_COLOR=1 cypress run --component -b chrome --spec './src/**/*.cy.ts' --project '../../../.'", + "test:component:open": "BABEL_ENV=cypress cross-env FORCE_COLOR=1 cypress open --component -b chrome --project '../../../.'", + "test:unit": "cross-env FORCE_COLOR=1 vitest run", + "test:unit:open": "cross-env FORCE_COLOR=1 vitest --ui" + }, + "devDependencies": { + "@kong/design-tokens": "1.17.2", + "@kong/kongponents": "9.14.8", + "vue": "^3.5.12", + "vue-router": "^4.4.5" + }, + "repository": { + "type": "git", + "url": "https://github.com/Kong/public-ui-components.git", + "directory": "packages/entities/entities-redis-configurations" + }, + "homepage": "https://github.com/Kong/public-ui-components/tree/main/packages/entities/entities-redis-configurations", + "bugs": { + "url": "https://github.com/Kong/public-ui-components/issues" + }, + "author": "Kong, Inc.", + "license": "Apache-2.0", + "volta": { + "extends": "../../../package.json" + }, + "distSizeChecker": { + "errorLimit": "200KB" + }, + "peerDependencies": { + "@kong/kongponents": "9.14.8", + "vue": "^3.5.12", + "vue-router": "^4.4.5" + } +} diff --git a/packages/entities/entities-redis-configurations/sandbox/App.vue b/packages/entities/entities-redis-configurations/sandbox/App.vue new file mode 100644 index 0000000000..b9c9d037ec --- /dev/null +++ b/packages/entities/entities-redis-configurations/sandbox/App.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/packages/entities/entities-redis-configurations/sandbox/index.html b/packages/entities/entities-redis-configurations/sandbox/index.html new file mode 100644 index 0000000000..5d67940102 --- /dev/null +++ b/packages/entities/entities-redis-configurations/sandbox/index.html @@ -0,0 +1,25 @@ + + + + + + + EntitiesRedisConfigurations Component Sandbox + + + + + + + +
+ + + + diff --git a/packages/entities/entities-redis-configurations/sandbox/index.ts b/packages/entities/entities-redis-configurations/sandbox/index.ts new file mode 100644 index 0000000000..c3bc901eaf --- /dev/null +++ b/packages/entities/entities-redis-configurations/sandbox/index.ts @@ -0,0 +1,31 @@ +import { createApp } from 'vue' +import { createRouter, createWebHistory } from 'vue-router' +import Kongponents from '@kong/kongponents' +import '@kong/kongponents/dist/style.css' +import App from './App.vue' + +const app = createApp(App) + +const init = async () => { + const router = createRouter({ + history: createWebHistory(), + routes: [ + { + path: '/', + name: 'home', + component: () => import('./pages/HomePage.vue'), + }, + { + path: '/create', + name: 'create-redis-configuration', + component: () => import('./pages/RedisConfigurationFormPage.vue'), + }, + ], + }) + + app.use(Kongponents) + app.use(router) + app.mount('#app') +} + +init() diff --git a/packages/entities/entities-redis-configurations/sandbox/pages/HomePage.vue b/packages/entities/entities-redis-configurations/sandbox/pages/HomePage.vue new file mode 100644 index 0000000000..b6f59d1922 --- /dev/null +++ b/packages/entities/entities-redis-configurations/sandbox/pages/HomePage.vue @@ -0,0 +1,9 @@ + diff --git a/packages/entities/entities-redis-configurations/sandbox/pages/RedisConfigurationFormPage.vue b/packages/entities/entities-redis-configurations/sandbox/pages/RedisConfigurationFormPage.vue new file mode 100644 index 0000000000..9b06aacb29 --- /dev/null +++ b/packages/entities/entities-redis-configurations/sandbox/pages/RedisConfigurationFormPage.vue @@ -0,0 +1,21 @@ + + + diff --git a/packages/entities/entities-redis-configurations/sandbox/tsconfig.json b/packages/entities/entities-redis-configurations/sandbox/tsconfig.json new file mode 100644 index 0000000000..6b0bff7930 --- /dev/null +++ b/packages/entities/entities-redis-configurations/sandbox/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@entities-shared-sandbox/*": [ + "../../entities-shared/sandbox/shared/*" + ] + } + }, + "include": [ + "**/*.ts", + "**/*.vue", + ], + "exclude": [ + "node_modules" + ] +} diff --git a/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue b/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue new file mode 100644 index 0000000000..bd7195c984 --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/packages/entities/entities-redis-configurations/src/composables/index.ts b/packages/entities/entities-redis-configurations/src/composables/index.ts new file mode 100644 index 0000000000..3893dfc828 --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/composables/index.ts @@ -0,0 +1,6 @@ +import useI18n from './useI18n' + +// All composables must be exported as part of the default object for Cypress test stubs +export default { + useI18n, +} diff --git a/packages/entities/entities-redis-configurations/src/composables/useI18n.ts b/packages/entities/entities-redis-configurations/src/composables/useI18n.ts new file mode 100644 index 0000000000..950be42ab7 --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/composables/useI18n.ts @@ -0,0 +1,16 @@ +import { createI18n, i18nTComponent } from '@kong-ui-public/i18n' +import english from '../locales/en.json' + +interface UseI18nReturn { + i18n: ReturnType> + i18nT: ReturnType> +} + +export default function useI18n(): UseI18nReturn { + const i18n = createI18n('en-us', english) + + return { + i18n, + i18nT: i18nTComponent(i18n), // Translation component + } +} diff --git a/packages/entities/entities-redis-configurations/src/global-components.d.ts b/packages/entities/entities-redis-configurations/src/global-components.d.ts new file mode 100644 index 0000000000..2f0048d672 --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/global-components.d.ts @@ -0,0 +1,2 @@ +// Import globally available components +import '@kong/kongponents/dist/types/global-components' diff --git a/packages/entities/entities-redis-configurations/src/index.ts b/packages/entities/entities-redis-configurations/src/index.ts new file mode 100644 index 0000000000..9281fb235f --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/index.ts @@ -0,0 +1,17 @@ +// import type { App } from 'vue' +import RedisConfigurationForm from './components/RedisConfigurationForm.vue' + +// Export Vue plugin +// We rarely want to export components as a plugin as we prefer to support proper tree-shaking in the host application. Only enable if you're packing a Vue plugin. +// export default { +// // Customize Vue plugin options as desired +// // Providing a `name` property allows for customizing the registered +// // name of your component (useful if exporting a single component). +// install: (app: App, options: { name?: string, [key: string]: any } = {}): void => { +// app.component(options.name || 'EntitiesRedisConfigurations', EntitiesRedisConfigurations) +// }, +// } + +export { RedisConfigurationForm } + +export * from './types' diff --git a/packages/entities/entities-redis-configurations/src/locales/en.json b/packages/entities/entities-redis-configurations/src/locales/en.json new file mode 100644 index 0000000000..95890b1479 --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/locales/en.json @@ -0,0 +1,23 @@ +{ + "form": { + "sections": { + "type": { + "title": "Redis type", + "description": "Both Enterprise and Open Source plugins support Redis. Enterprise plugins can connect to a standalone Redis instance (host/port), Cluster, or Sentinel, while Open Source plugins support only a simplified host/port configuration." + }, + "general": { + "title": "General information", + "description": "Name your Redis configuration." + } + }, + "fields": { + "type": { + "label": "Redis type" + }, + "name": { + "label": "Name", + "placeholder": "Enter unique name" + } + } + } +} diff --git a/packages/entities/entities-redis-configurations/src/types/index.ts b/packages/entities/entities-redis-configurations/src/types/index.ts new file mode 100644 index 0000000000..86fcbd2fde --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/types/index.ts @@ -0,0 +1,3 @@ +import type { KonnectBaseFormConfig } from '@kong-ui-public/entities-shared' + +export interface KonnectRedisConfigurationFormConfig extends KonnectBaseFormConfig {} diff --git a/packages/entities/entities-redis-configurations/tsconfig.build.json b/packages/entities/entities-redis-configurations/tsconfig.build.json new file mode 100644 index 0000000000..577de9d6ae --- /dev/null +++ b/packages/entities/entities-redis-configurations/tsconfig.build.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": [] + }, + "exclude": [ + "src/**/*.cy.ts", + "src/**/*.spec.ts", + "sandbox", + "dist" + ] +} diff --git a/packages/entities/entities-redis-configurations/tsconfig.json b/packages/entities/entities-redis-configurations/tsconfig.json new file mode 100644 index 0000000000..e34e90e4e4 --- /dev/null +++ b/packages/entities/entities-redis-configurations/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "outDir": "dist", + "declarationDir": "dist/types", + "types": [ + "node", + "vite/client", + "cypress", + "cypress/vue", + "../../../cypress/support" + ] + }, + "include": [ + "src/**/*", + "sandbox/**/*" + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/packages/entities/entities-redis-configurations/vite.config.ts b/packages/entities/entities-redis-configurations/vite.config.ts new file mode 100644 index 0000000000..4af9ac3a13 --- /dev/null +++ b/packages/entities/entities-redis-configurations/vite.config.ts @@ -0,0 +1,30 @@ +import sharedViteConfig, { sanitizePackageName } from '../../../vite.config.shared' +import { resolve } from 'path' +import { defineConfig, mergeConfig } from 'vite' + +// Package name MUST always match the kebab-case package name inside the component's package.json file and the name of your `/packages/{package-name}` directory +const packageName = 'entities-redis-configurations' +const sanitizedPackageName = sanitizePackageName(packageName) + +// Merge the shared Vite config with the local one defined below +const config = mergeConfig(sharedViteConfig, defineConfig({ + build: { + lib: { + // The kebab-case name of the exposed global variable. MUST be in the format `kong-ui-public-{package-name}` + // Example: name: 'kong-ui-public-demo-component' + name: `kong-ui-public-${sanitizedPackageName}`, + entry: resolve(__dirname, './src/index.ts'), + fileName: (format) => `${sanitizedPackageName}.${format}.js`, + }, + }, +})) + +// If we are trying to preview a build of the local `package/entities-redis-configurations/sandbox` directory, +// unset the lib, rollupOptions.external and rollupOptions.output.globals properties +if (process.env.USE_SANDBOX) { + config.build.lib = undefined + config.build.rollupOptions.external = undefined + config.build.rollupOptions.output.global = undefined +} + +export default config diff --git a/packages/entities/entities-shared/src/types/entity-base-config-card.ts b/packages/entities/entities-shared/src/types/entity-base-config-card.ts index da7fec3bf4..af85eddb0a 100644 --- a/packages/entities/entities-shared/src/types/entity-base-config-card.ts +++ b/packages/entities/entities-shared/src/types/entity-base-config-card.ts @@ -19,6 +19,7 @@ export enum SupportedEntityType { Upstream = 'upstream', Target = 'target', Vault = 'vault', + RedisConfiguration = 'redis_configuration', // todo(zehao): not sure // Use this for any entity type that is not supported by terraform // If entityType is 'other' terraform scripts will not be available // Note: This is currently only supported by EntityBaseForm not EntityBaseConfigCard!! diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc71e73670..6dd4e2aa8d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -957,6 +957,21 @@ importers: specifier: ^4.4.5 version: 4.4.5(vue@3.5.12(typescript@5.6.3)) + packages/entities/entities-redis-configurations: + devDependencies: + '@kong/design-tokens': + specifier: 1.17.2 + version: 1.17.2 + '@kong/kongponents': + specifier: 9.14.8 + version: 9.14.8(axios@1.7.7)(vue-router@4.4.5(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3)) + vue: + specifier: ^3.5.12 + version: 3.5.12(typescript@5.6.3) + vue-router: + specifier: ^4.4.5 + version: 4.4.5(vue@3.5.12(typescript@5.6.3)) + packages/entities/entities-routes: dependencies: '@kong-ui-public/expressions': @@ -1990,6 +2005,14 @@ packages: vue: '>= 3.3.4 < 4' vue-router: ^4.4.5 + '@kong/kongponents@9.14.8': + resolution: {integrity: sha512-rKOwzVG9kQJxLGk6cyedWyL5N0hgO5wDvHm/ir82Z+YGuEer8iF3wyGEh9EbcB6YukCNzBBcRASkR1PiyPS6Ag==} + engines: {node: '>=v16.20.2 || >=18.12.1 || >=20.14.0'} + peerDependencies: + axios: ^1.7.7 + vue: '>= 3.3.4 < 4' + vue-router: ^4.4.5 + '@kong/markdown@1.7.18': resolution: {integrity: sha512-Bqa94b1W8SYa2lCLp1tL1JUA+cJciRo/k847iC5szDB6P7bm3tDNIFVxvwMAx0cf76jlKQGfsCYSnqTo2n1z9Q==} engines: {node: '>=18.17.0'} @@ -10822,6 +10845,27 @@ snapshots: transitivePeerDependencies: - '@vue/composition-api' + '@kong/kongponents@9.14.8(axios@1.7.7)(vue-router@4.4.5(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))': + dependencies: + '@floating-ui/vue': 1.1.5(vue@3.5.12(typescript@5.6.3)) + '@kong/icons': 1.20.0(vue@3.5.12(typescript@5.6.3)) + '@popperjs/core': 2.11.8 + axios: 1.7.7 + date-fns: 2.30.0 + date-fns-tz: 2.0.1(date-fns@2.30.0) + focus-trap: 7.6.1 + focus-trap-vue: 4.0.3(focus-trap@7.6.1)(vue@3.5.12(typescript@5.6.3)) + nanoid: 5.0.8 + sortablejs: 1.15.3 + swrv: 1.0.4(vue@3.5.12(typescript@5.6.3)) + v-calendar: 3.1.2(@popperjs/core@2.11.8)(vue@3.5.12(typescript@5.6.3)) + vue: 3.5.12(typescript@5.6.3) + vue-bind-once: 0.2.1(vue@3.5.12(typescript@5.6.3)) + vue-draggable-next: 2.2.1(sortablejs@1.15.3)(vue@3.5.12(typescript@5.6.3)) + vue-router: 4.4.5(vue@3.5.12(typescript@5.6.3)) + transitivePeerDependencies: + - '@vue/composition-api' + '@kong/markdown@1.7.18(@types/markdown-it@14.1.1)(vue@3.5.12(typescript@5.6.3))': dependencies: '@kong/icons': 1.20.0(vue@3.5.12(typescript@5.6.3)) From e9185c9f29d473f4586f4e0573f57df073752886 Mon Sep 17 00:00:00 2001 From: Zehao Zhang Date: Mon, 18 Nov 2024 10:07:07 +0800 Subject: [PATCH 02/19] feat(redis): redis configuration form [KM-235] --- .../src/components/ClusterNodes.vue | 71 ++++++ .../components/FieldArrayCardContainer.vue | 60 +++++ .../src/components/RedisConfigurationForm.vue | 226 +++++++++++++++++- .../composables/useRedisConfigurationForm.ts | 30 +++ .../src/locales/en.json | 125 ++++++++++ .../src/types/index.ts | 4 +- .../src/types/redis-configuration-form.ts | 26 ++ 7 files changed, 534 insertions(+), 8 deletions(-) create mode 100644 packages/entities/entities-redis-configurations/src/components/ClusterNodes.vue create mode 100644 packages/entities/entities-redis-configurations/src/components/FieldArrayCardContainer.vue create mode 100644 packages/entities/entities-redis-configurations/src/composables/useRedisConfigurationForm.ts create mode 100644 packages/entities/entities-redis-configurations/src/types/redis-configuration-form.ts diff --git a/packages/entities/entities-redis-configurations/src/components/ClusterNodes.vue b/packages/entities/entities-redis-configurations/src/components/ClusterNodes.vue new file mode 100644 index 0000000000..36f59c1cd9 --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/components/ClusterNodes.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/packages/entities/entities-redis-configurations/src/components/FieldArrayCardContainer.vue b/packages/entities/entities-redis-configurations/src/components/FieldArrayCardContainer.vue new file mode 100644 index 0000000000..4f1f1d1607 --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/components/FieldArrayCardContainer.vue @@ -0,0 +1,60 @@ + + + + + + + diff --git a/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue b/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue index bd7195c984..e750c76715 100644 --- a/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue +++ b/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue @@ -20,10 +20,15 @@ :title="t('form.sections.type.title')" > + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -46,11 +240,17 @@ import { EntityFormSection, SupportedEntityType, } from '@kong-ui-public/entities-shared' -import type { KonnectRedisConfigurationFormConfig } from 'src/types' -import type { PropType } from 'vue' import '@kong-ui-public/entities-shared/dist/style.css' import composables from '../composables' +import ClusterNodes from '../components/ClusterNodes.vue' +import { useRedisConfigurationForm } from '../composables/useRedisConfigurationForm' + +import type { PropType } from 'vue' +import { + RedisType, + type KonnectRedisConfigurationFormConfig, +} from '../types' const props = defineProps({ config: { @@ -67,9 +267,25 @@ const props = defineProps({ }, }) -const { i18nT, i18n: { t } } = composables.useI18n() +const { i18n: { t } } = composables.useI18n() + +const typeOptions = [ + { label: t('form.options.type.host_port'), group: ` ${t('form.options.type.open_source')}`, value: RedisType.HOST_PORT_OPEN_SOURCE }, // the space before the group name is intentional, it makes the group to be the first one + { label: t('form.options.type.host_port'), group: t('form.options.type.enterprise'), value: RedisType.HOST_PORT_ENTERPRISE }, + { label: t('form.options.type.cluster'), group: t('form.options.type.enterprise'), value: RedisType.CLUSTER }, + { label: t('form.options.type.sentinel'), group: t('form.options.type.enterprise'), value: RedisType.SENTINEL }, +] const noop = () => {} + +const getSelectedText = (item: any) => { + const suffix = item.value === RedisType.HOST_PORT_OPEN_SOURCE + ? t('form.options.type.suffix_open_source') + : t('form.options.type.suffix_enterprise') + return `${item.label}${suffix}` +} + +const { form } = useRedisConfigurationForm() diff --git a/packages/entities/entities-redis-configurations/src/components/SentinelNodes.vue b/packages/entities/entities-redis-configurations/src/components/SentinelNodes.vue new file mode 100644 index 0000000000..5617278932 --- /dev/null +++ b/packages/entities/entities-redis-configurations/src/components/SentinelNodes.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/packages/entities/entities-redis-configurations/src/composables/useRedisConfigurationForm.ts b/packages/entities/entities-redis-configurations/src/composables/useRedisConfigurationForm.ts index d044638929..4bd5bc66a8 100644 --- a/packages/entities/entities-redis-configurations/src/composables/useRedisConfigurationForm.ts +++ b/packages/entities/entities-redis-configurations/src/composables/useRedisConfigurationForm.ts @@ -1,6 +1,6 @@ import { computed, reactive } from 'vue' -import { RedisType } from '../types' +import { Mode } from '../types' import type { RedisConfigurationFormState } from '../types' @@ -8,12 +8,28 @@ export const useRedisConfigurationForm = () => { const form = reactive({ fields: { name: '', - type: RedisType.HOST_PORT_OPEN_SOURCE, - port: 0, - host: '', + mode: Mode.HOST_PORT_OPEN_SOURCE, + port: 6379, + host: '127.0.0.1', database: 0, username: '', password: '', + ssl: false, + ssl_verify: false, + server_name: '', + connect_timeout: 2000, + send_timeout: 2000, + read_timeout: 2000, + sentinel_username: '', + sentinel_password: '', + keepalive_pool_size: 256, + keepalive_backlog: 0, + sentinel_master: '', + sentinel_nodes: [], + cluster_nodes: [], + cluster_max_redirections: 0, + connection_is_proxied: false, + timeout: 2000, }, readonly: false, errorMessage: '', diff --git a/packages/entities/entities-redis-configurations/src/locales/en.json b/packages/entities/entities-redis-configurations/src/locales/en.json index 83fcc3893a..5332729a7f 100644 --- a/packages/entities/entities-redis-configurations/src/locales/en.json +++ b/packages/entities/entities-redis-configurations/src/locales/en.json @@ -126,6 +126,24 @@ "connection_is_proxied": { "label": "Connection is proxied", "tooltip": "If the connection to Redis is proxied (e.g. Envoy), set it `true`. Set the `host` and `port` to point to the proxy address." + }, + "cluster_nodes": { + "title": "Cluster nodes", + "tooltip": "This is a really long tooltip. Hopefully we won't have anything this long but we might. I wonder how it handles long inputs", + "add_button": "New item" + }, + "sentinel_nodes": { + "title": "Sentinel nodes", + "tooltip": "Sentinel node addresses to use for Redis connections when the `redis` strategy is defined. Defining this field implies using a Redis Sentinel. The minimum length of the array is 1 element.", + "add_button": "New item" + }, + "sentinel_node_host": { + "label": "Host", + "tooltip": "A string representing a host name, such as example.com." + }, + "sentinel_node_port": { + "label": "Port", + "tooltip": "An integer representing a port number between 0 and 65535, inclusive." } }, "options": { @@ -137,12 +155,12 @@ "enterprise": "Enterprise", "suffix_open_source": " (Open Source)", "suffix_enterprise": " (Enterprise)" + }, + "sentinel_role": { + "master": "master", + "slave": "slave", + "any": "any" } - }, - "cluster_nodes": { - "title": "Cluster nodes", - "tooltip": "This is a really long tooltip. Hopefully we won't have anything this long but we might. I wonder how it handles long inputs", - "add_button": "New item" } } } diff --git a/packages/entities/entities-redis-configurations/src/types/redis-configuration-form.ts b/packages/entities/entities-redis-configurations/src/types/redis-configuration-form.ts index 36f9a73275..f66ecd4ed8 100644 --- a/packages/entities/entities-redis-configurations/src/types/redis-configuration-form.ts +++ b/packages/entities/entities-redis-configurations/src/types/redis-configuration-form.ts @@ -2,21 +2,49 @@ import type { KonnectBaseFormConfig } from '@kong-ui-public/entities-shared' export interface KonnectRedisConfigurationFormConfig extends KonnectBaseFormConfig { } -export enum RedisType { +export enum Mode { HOST_PORT_OPEN_SOURCE = 'host_port_open_source', HOST_PORT_ENTERPRISE = 'host_port_enterprise', SENTINEL = 'sentinel', CLUSTER = 'cluster', } +export interface SentinelNode { + host: string + port: number +} + +export interface ClusterNode { + ip: string + port: number +} + export interface RedisConfigurationFields { name: string - type: RedisType + mode: Mode port: number host: string database: number username: string password: string + ssl: boolean + ssl_verify: boolean + server_name: string + timeout: number + + connect_timeout: number + send_timeout: number + read_timeout: number + sentinel_username: string + sentinel_password: string + keepalive_pool_size: number + keepalive_backlog: number + sentinel_master: string + sentinel_role?: 'master' | 'slave' | 'any' + sentinel_nodes: SentinelNode[] + cluster_nodes: ClusterNode[] + cluster_max_redirections: number + connection_is_proxied: boolean } export interface RedisConfigurationFormState { diff --git a/packages/entities/entities-redis-configurations/vite.config.ts b/packages/entities/entities-redis-configurations/vite.config.ts index 4af9ac3a13..a2cff40155 100644 --- a/packages/entities/entities-redis-configurations/vite.config.ts +++ b/packages/entities/entities-redis-configurations/vite.config.ts @@ -1,4 +1,4 @@ -import sharedViteConfig, { sanitizePackageName } from '../../../vite.config.shared' +import sharedViteConfig, { getApiProxies, sanitizePackageName } from '../../../vite.config.shared' import { resolve } from 'path' import { defineConfig, mergeConfig } from 'vite' @@ -17,6 +17,12 @@ const config = mergeConfig(sharedViteConfig, defineConfig({ fileName: (format) => `${sanitizedPackageName}.${format}.js`, }, }, + server: { + proxy: { + // Add the API proxies to inject the Authorization header + ...getApiProxies(), + }, + }, })) // If we are trying to preview a build of the local `package/entities-redis-configurations/sandbox` directory, From 544b35ea066d5d6b46b99e24087702e1b50464bf Mon Sep 17 00:00:00 2001 From: Zehao Zhang Date: Mon, 25 Nov 2024 17:13:26 +0800 Subject: [PATCH 04/19] wip --- .../package.json | 4 + .../src/components/ClusterNodes.vue | 27 ++--- .../src/components/RedisConfigurationForm.vue | 16 +-- .../src/components/SentinelNodes.vue | 31 +++--- .../composables/useRedisConfigurationForm.ts | 99 ++++++++++++++++++- .../src/constants.ts | 11 +++ .../src/helpers.ts | 17 ++++ .../src/types/redis-configuration-form.ts | 6 +- pnpm-lock.yaml | 8 ++ 9 files changed, 184 insertions(+), 35 deletions(-) create mode 100644 packages/entities/entities-redis-configurations/src/constants.ts create mode 100644 packages/entities/entities-redis-configurations/src/helpers.ts diff --git a/packages/entities/entities-redis-configurations/package.json b/packages/entities/entities-redis-configurations/package.json index dc3961f8d7..dbbc05dbf9 100644 --- a/packages/entities/entities-redis-configurations/package.json +++ b/packages/entities/entities-redis-configurations/package.json @@ -41,6 +41,7 @@ "devDependencies": { "@kong/design-tokens": "1.17.2", "@kong/kongponents": "9.14.8", + "@types/uuid": "^10.0.0", "vue": "^3.5.12", "vue-router": "^4.4.5" }, @@ -65,5 +66,8 @@ "@kong/kongponents": "9.14.8", "vue": "^3.5.12", "vue-router": "^4.4.5" + }, + "dependencies": { + "uuid": "^10.0.0" } } diff --git a/packages/entities/entities-redis-configurations/src/components/ClusterNodes.vue b/packages/entities/entities-redis-configurations/src/components/ClusterNodes.vue index 40d213daf0..960adac82d 100644 --- a/packages/entities/entities-redis-configurations/src/components/ClusterNodes.vue +++ b/packages/entities/entities-redis-configurations/src/components/ClusterNodes.vue @@ -8,14 +8,13 @@
-
+
-import { ref } from 'vue' import { AddCircleIcon } from '@kong/icons' import FieldArrayCardContainer from './FieldArrayCardContainer.vue' import composables from '../composables' +import type { ClusterNode, Identifiable } from '../types' +import { genDefaultClusterNode } from '../helpers' + +const nodes = defineModel[]>({ required: true }) const { i18n: { t } } = composables.useI18n() -type Item = { - ip: string - port: number -} -const items = ref([{ ip: '', port: 0 }]) + const addItem = () => { - items.value.push({ ip: '', port: 0 }) + nodes.value.push(genDefaultClusterNode()) +} + +const removeItem = (index: number) => { + nodes.value.splice(index, 1) } diff --git a/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue b/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue index 750aa7cc9b..99ff26e406 100644 --- a/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue +++ b/packages/entities/entities-redis-configurations/src/components/RedisConfigurationForm.vue @@ -1,14 +1,14 @@