diff --git a/CHANGELOG.md b/CHANGELOG.md index abd442d0..13e7704d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + +- Delete schemas function + +### Added + +- Schema client created + ## [1.5.3] - 2023-05-04 ### Fixed diff --git a/graphql/schema.graphql b/graphql/schema.graphql index 91f5c904..71aee29d 100644 --- a/graphql/schema.graphql +++ b/graphql/schema.graphql @@ -13,6 +13,7 @@ type Query { filter: AffiliatesFilterInput sorting: AffliatesSortingInput ): [AffiliateScroll]! + getWorkspaces: [Workspaces] } type Mutation { diff --git a/graphql/types/workspaces.graphql b/graphql/types/workspaces.graphql new file mode 100644 index 00000000..e930216b --- /dev/null +++ b/graphql/types/workspaces.graphql @@ -0,0 +1,4 @@ +type Workspaces { + name: String + production: Boolean +} diff --git a/manifest.json b/manifest.json index 72a11c1b..1b3cba31 100644 --- a/manifest.json +++ b/manifest.json @@ -80,6 +80,9 @@ }, { "name": "colossus-write-logs" + }, + { + "name": "read-write-any-workspace" } ], "settingsSchema": { @@ -100,9 +103,7 @@ }, "billingOptions": { "type": "free", - "availableCountries": [ - "*" - ], + "availableCountries": ["*"], "support": { "url": "https://support.vtex.com/hc/requests" } diff --git a/node/clients/index.ts b/node/clients/index.ts index 6225e619..d26fd1c5 100644 --- a/node/clients/index.ts +++ b/node/clients/index.ts @@ -4,6 +4,7 @@ import type { Affiliates, UserAffiliation } from 'vtex.affiliates' import AuthenticationClient from './authenticationClient' import CheckoutExtended from './checkout' +import SchemasClient from './schemas' export class Clients extends IOClients { public get affiliates() { @@ -24,4 +25,8 @@ export class Clients extends IOClients { public get authentication() { return this.getOrSet('authentication', AuthenticationClient) } + + public get schemas() { + return this.getOrSet('schemas', SchemasClient) + } } diff --git a/node/clients/schemas.ts b/node/clients/schemas.ts new file mode 100644 index 00000000..04c1be06 --- /dev/null +++ b/node/clients/schemas.ts @@ -0,0 +1,36 @@ +import type { InstanceOptions, IOContext, RequestConfig } from '@vtex/api' +import { ExternalClient } from '@vtex/api' + +const routes = { + schemas: (dataEntity: string) => `/dataentities/${dataEntity}/schemas`, + delete: (dataEntity: string, schemaName: string) => + `dataentities/${dataEntity}/schemas/${schemaName}`, +} + +export default class SchemasClient extends ExternalClient { + constructor(context: IOContext, options?: InstanceOptions) { + super(`http://${context.account}.myvtex.com/api`, context, { + ...options, + headers: { + ...options?.headers, + VtexIdclientAutCookie: context.authToken, + 'Content-Type': 'application/json', + }, + }) + } + + public getSchemas( + dataEntity: string, + config?: RequestConfig + ): Promise { + return this.http.get(routes.schemas(dataEntity), config) + } + + public deleteSchemas( + dataEntity: string, + schemaName: string, + config?: RequestConfig + ): Promise { + return this.http.delete(routes.delete(dataEntity, schemaName), config) + } +} diff --git a/node/index.ts b/node/index.ts index 422ab989..e11d7448 100644 --- a/node/index.ts +++ b/node/index.ts @@ -34,6 +34,9 @@ import { updateAffiliate as updateAffiliateResolver } from './resolvers/updateAf import { getAffiliate } from './resolvers/getAffiliate' import { fieldResolvers } from './resolvers/fieldResolvers' import { getAffiliateByEmail } from './resolvers/getAffiliateByEmail' +import { getWorkspaces } from './resolvers/getWorkspaces' +import { getSchemas } from './middlewares/getSchemas' +import { deleteSchemas } from './middlewares/deleteSchemas' const TIMEOUT_MS = 1000 @@ -75,10 +78,10 @@ declare global { // The shape of our State object found in `ctx.state`. This is used as state bag to communicate between middlewares. interface State extends RecorderState { affiliate?: AffiliateInput + schemas?: string[] } - interface UserLoginState extends RecorderState { - affiliate?: AffiliateInput + interface UserLoginState extends State { orderForm: OrderForm userProfileId?: string | null affiliateLead: AffiliateLead @@ -89,6 +92,10 @@ declare global { export default new Service({ clients, routes: { + schemas: method({ + GET: [getSchemas], + DELETE: [getSchemas, deleteSchemas], + }), affiliate: method({ POST: [authenticateRequest, validateCreate, createAffiliate], PATCH: [authenticateRequest, validateUpdate, updateAffiliate], @@ -112,6 +119,7 @@ export default new Service({ getAffiliate, getAffiliateByEmail, getAffiliatesScroll, + getWorkspaces, }, Mutation: { addAffiliate, diff --git a/node/middlewares/deleteSchemas.ts b/node/middlewares/deleteSchemas.ts new file mode 100644 index 00000000..c163974f --- /dev/null +++ b/node/middlewares/deleteSchemas.ts @@ -0,0 +1,30 @@ +export async function deleteSchemas( + ctx: Context, + next: () => Promise +) { + const { + clients: { schemas }, + state, + vtex: { logger }, + } = ctx + + try { + const schemasToDelete = state?.schemas ?? [] + + schemasToDelete.forEach(async (i) => { + await schemas.deleteSchemas('vtex_affiliates_Affiliates', i) + }) + } catch (err) { + logger.error({ + metric: 'delete-affiliate-schema', + message: err.message, + }) + throw new Error('Error deleting affiliate schemas') + } + + ctx.message = `Schema Deleted` + ctx.body = `Schema Deleted` + ctx.status = 200 + + await next() +} diff --git a/node/middlewares/getSchemas.ts b/node/middlewares/getSchemas.ts new file mode 100644 index 00000000..ceabfc9f --- /dev/null +++ b/node/middlewares/getSchemas.ts @@ -0,0 +1,45 @@ +import { getOldVersions } from '../utils/schemas' + +export async function getSchemas(ctx: Context, next: () => Promise) { + const { + clients: { schemas, apps }, + state, + vtex: { logger }, + } = ctx + + const manifest = await apps.getApp(`vtex.affiliates`) + const versionManifest = manifest?.version.split(`+`) + + try { + let allSchemas: string[] = [] + + const schemaList = await schemas.getSchemas('vtex_affiliates_Affiliates') + + schemaList.forEach((s: any) => { + allSchemas = [...allSchemas, s.name] + }) + + const allOldSchemas = allSchemas.filter( + (schema) => !schema.includes(versionManifest[0]) + ) + + const oldVersions = getOldVersions(allOldSchemas, versionManifest[0]) + + const filteredSchemas = allSchemas.filter( + (schema) => + !schema.includes(versionManifest[0]) && + !schema.includes(oldVersions[0]) && + !schema.includes(oldVersions[1]) + ) + + state.schemas = filteredSchemas + } catch (err) { + logger.error({ + metric: 'get-affiliate-schema', + message: err.message, + }) + throw new Error('Error getting affiliate schemas') + } + + await next() +} diff --git a/node/package.json b/node/package.json index 8acd7237..c6cadfdd 100644 --- a/node/package.json +++ b/node/package.json @@ -9,7 +9,7 @@ "@types/jest": "^27.0.2", "@types/node": "^12.0.0", "@types/ramda": "types/npm-ramda#dist", - "@vtex/api": "6.45.12", + "@vtex/api": "6.45.22", "@vtex/test-tools": "^3.4.1", "@vtex/tsconfig": "^0.5.6", "typescript": "3.9.7" diff --git a/node/resolvers/getWorkspaces.ts b/node/resolvers/getWorkspaces.ts new file mode 100644 index 00000000..86e80f21 --- /dev/null +++ b/node/resolvers/getWorkspaces.ts @@ -0,0 +1,6 @@ +export const getWorkspaces = async (_: unknown, __: unknown, ctx: Context) => { + const { workspaces } = ctx.clients + const result = await workspaces.list(ctx.vtex.account) + + return result +} diff --git a/node/service.json b/node/service.json index d5d6998e..da57ba13 100644 --- a/node/service.json +++ b/node/service.json @@ -6,6 +6,10 @@ "maxReplicas": 4, "workers": 1, "routes": { + "schemas": { + "path": "/_v/affiliateSchemas", + "public": true + }, "affiliate": { "path": "/_v/affiliate", "public": true diff --git a/node/utils/schemas.ts b/node/utils/schemas.ts new file mode 100644 index 00000000..97c37766 --- /dev/null +++ b/node/utils/schemas.ts @@ -0,0 +1,46 @@ +function isVersionLower(currentVersion: string, newVersion: string) { + const current = currentVersion.split('.').map(Number) + const newV = newVersion.split('.').map(Number) + + for (let i = 0; i < Math.max(current.length, newV.length); i++) { + if (current[i] > (newV[i] || 0)) { + return false + } + + if (current[i] < (newV[i] || 0)) { + return true + } + } + + return false +} + +function compareVersions(version1: string, version2: string) { + const v1 = version1.split('.').map(Number) + const v2 = version2.split('.').map(Number) + + for (let i = 0; i < Math.max(v1.length, v2.length); i++) { + if (v1[i] > v2[i]) return -1 + if (v1[i] < v2[i]) return 1 + } + + return 0 +} + +export function getOldVersions(versions: any[], manifest: string) { + let versionArray: string[] = [] + + versions.forEach((version) => { + const splitted = version.split('-') + + if ( + splitted[0].match(/^\d/) && + !versionArray.includes(splitted) && + !isVersionLower(manifest, splitted[0]) + ) { + versionArray = [...versionArray, splitted[0]] + } + }) + + return versionArray.slice().sort(compareVersions) +} diff --git a/node/yarn.lock b/node/yarn.lock index 6bd5cb0f..1538fe0a 100644 --- a/node/yarn.lock +++ b/node/yarn.lock @@ -1658,10 +1658,10 @@ resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3" integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== -"@vtex/api@6.45.12": - version "6.45.12" - resolved "https://registry.yarnpkg.com/@vtex/api/-/api-6.45.12.tgz#b13c04398b12f576263ea823369f09c970d57479" - integrity sha512-SVLKo+Q/TxQy+1UKzH8GswTI3F2OCRCLfgaNQOrVAVdbM6Ci4wzTeX8j/S4Q1aEEnqBFlH/wVpHf8I6NBa+g9A== +"@vtex/api@6.45.22": + version "6.45.22" + resolved "https://registry.yarnpkg.com/@vtex/api/-/api-6.45.22.tgz#fa9bbfde1a4d4fbbaf6cce9f6dbc9bb9ee929ba3" + integrity sha512-g5cGUDhF4FADgSMpQmce/bnIZumwGlPG2cabwbQKIQ+cCFMZqOEM/n+YQb1+S8bCyHkzW3u/ZABoyCKi5/nxxg== dependencies: "@types/koa" "^2.11.0" "@types/koa-compose" "^3.2.3" @@ -1681,7 +1681,7 @@ fs-extra "^7.0.0" graphql "^14.5.8" graphql-tools "^4.0.6" - graphql-upload "^8.1.0" + graphql-upload "^13.0.0" jaeger-client "^3.18.0" js-base64 "^2.5.1" koa "^2.11.0" @@ -1692,7 +1692,7 @@ mime-types "^2.1.12" opentracing "^0.14.4" p-limit "^2.2.0" - prom-client "^12.0.0" + prom-client "^14.2.0" qs "^6.5.1" querystring "^0.2.0" ramda "^0.26.0" @@ -3172,10 +3172,10 @@ fresh@~0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -fs-capacitor@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-2.0.4.tgz#5a22e72d40ae5078b4fe64fe4d08c0d3fc88ad3c" - integrity sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA== +fs-capacitor@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-6.2.0.tgz#fa79ac6576629163cb84561995602d8999afb7f5" + integrity sha512-nKcE1UduoSKX27NSZlg879LdQc94OtbOsEmKMN2MBNudXREvijRKx2GEBsTMTfws+BrbkJoEuynbGSVRSpauvw== fs-constants@^1.0.0: version "1.0.0" @@ -3296,15 +3296,15 @@ graphql-tools@^4.0.6: iterall "^1.1.3" uuid "^3.1.0" -graphql-upload@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/graphql-upload/-/graphql-upload-8.1.0.tgz#6d0ab662db5677a68bfb1f2c870ab2544c14939a" - integrity sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q== +graphql-upload@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/graphql-upload/-/graphql-upload-13.0.0.tgz#1a255b64d3cbf3c9f9171fa62a8fb0b9b59bb1d9" + integrity sha512-YKhx8m/uOtKu4Y1UzBFJhbBGJTlk7k4CydlUUiNrtxnwZv0WigbRHP+DVhRNKt7u7DXOtcKZeYJlGtnMXvreXA== dependencies: busboy "^0.3.1" - fs-capacitor "^2.0.4" - http-errors "^1.7.3" - object-path "^0.11.4" + fs-capacitor "^6.2.0" + http-errors "^1.8.1" + object-path "^0.11.8" graphql@^14.0.0, graphql@^14.5.8: version "14.7.0" @@ -3449,7 +3449,7 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" -http-errors@^1.3.1, http-errors@^1.6.3, http-errors@^1.7.3, http-errors@~1.8.0: +http-errors@^1.3.1, http-errors@^1.6.3, http-errors@^1.8.1, http-errors@~1.8.0: version "1.8.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== @@ -4799,7 +4799,7 @@ object-keys@^1.0.12, object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-path@^0.11.4: +object-path@^0.11.8: version "0.11.8" resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.8.tgz#ed002c02bbdd0070b78a27455e8ae01fc14d4742" integrity sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA== @@ -5050,10 +5050,10 @@ process@^0.10.0: resolved "https://registry.yarnpkg.com/process/-/process-0.10.1.tgz#842457cc51cfed72dc775afeeafb8c6034372725" integrity sha1-hCRXzFHP7XLcd1r+6vuMYDQ3JyU= -prom-client@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-12.0.0.tgz#9689379b19bd3f6ab88a9866124db9da3d76c6ed" - integrity sha512-JbzzHnw0VDwCvoqf8y1WDtq4wSBAbthMB1pcVI/0lzdqHGJI3KBJDXle70XK+c7Iv93Gihqo0a5LlOn+g8+DrQ== +prom-client@^14.2.0: + version "14.2.0" + resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-14.2.0.tgz#ca94504e64156f6506574c25fb1c34df7812cf11" + integrity sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA== dependencies: tdigest "^0.1.1" @@ -5709,7 +5709,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -stats-lite@vtex/node-stats-lite#dist: +"stats-lite@github:vtex/node-stats-lite#dist": version "2.2.0" resolved "https://codeload.github.com/vtex/node-stats-lite/tar.gz/1b0d39cc41ef7aaecfd541191f877887a2044797" dependencies: diff --git a/react/components/admin/commissions/CommissionsTable.tsx b/react/components/admin/commissions/CommissionsTable.tsx index cee96658..ab59e322 100644 --- a/react/components/admin/commissions/CommissionsTable.tsx +++ b/react/components/admin/commissions/CommissionsTable.tsx @@ -53,8 +53,8 @@ const CommissionsTable: FC = () => { const { culture: { locale }, } = useRuntime() + const view = useDataViewState() - const modal = useModalState() const showToast = useToast() const [selectedRow, setSelectedRow] = useState()