diff --git a/apps/angular-example/CHANGELOG.md b/apps/angular-example/CHANGELOG.md index a0dc3703..4fd4d2e4 100644 --- a/apps/angular-example/CHANGELOG.md +++ b/apps/angular-example/CHANGELOG.md @@ -1,5 +1,12 @@ # angular-example +## 0.0.19 + +### Patch Changes + +- @tryabby/angular@2.0.9 +- @tryabby/devtools@5.0.1 + ## 0.0.18 ### Patch Changes diff --git a/apps/angular-example/package.json b/apps/angular-example/package.json index 9c066f6f..d96c7f2d 100644 --- a/apps/angular-example/package.json +++ b/apps/angular-example/package.json @@ -1,6 +1,6 @@ { "name": "angular-example", - "version": "0.0.18", + "version": "0.0.19", "private": true, "scripts": { "ng": "ng", diff --git a/apps/web/CHANGELOG.md b/apps/web/CHANGELOG.md index eceadf59..5f1aa96e 100644 --- a/apps/web/CHANGELOG.md +++ b/apps/web/CHANGELOG.md @@ -1,5 +1,14 @@ # web +## 0.2.37 + +### Patch Changes + +- Updated dependencies [d05cb9a] + - @tryabby/core@5.3.1 + - @tryabby/devtools@5.0.1 + - @tryabby/next@5.1.2 + ## 0.2.36 ### Patch Changes diff --git a/apps/web/package.json b/apps/web/package.json index 1ec18f37..c7380661 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "web", - "version": "0.2.36", + "version": "0.2.37", "private": true, "scripts": { "build": "next build", diff --git a/packages/angular/CHANGELOG.md b/packages/angular/CHANGELOG.md index d0c20a2e..c12acf85 100644 --- a/packages/angular/CHANGELOG.md +++ b/packages/angular/CHANGELOG.md @@ -1,5 +1,12 @@ # @tryabby/angular +## 2.0.9 + +### Patch Changes + +- Updated dependencies [d05cb9a] + - @tryabby/core@5.3.1 + ## 2.0.8 ### Patch Changes diff --git a/packages/angular/package.json b/packages/angular/package.json index d072f495..d963fe62 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,6 +1,6 @@ { "name": "@tryabby/angular", - "version": "2.0.8", + "version": "2.0.9", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index de31968a..c3ebede7 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,11 @@ # @tryabby/cli +## 1.1.1 + +### Patch Changes + +- d05cb9a: add feature flag removal command + ## 1.1.0 ### Minor Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 7962a98d..c9cc0af2 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@tryabby/cli", - "version": "1.1.0", + "version": "1.1.1", "private": false, "main": "./dist/index.js", "bin": { @@ -27,6 +27,7 @@ "dotenv": "^16.0.3", "esbuild": "0.18.17", "figlet": "^1.6.0", + "globby": "^14.0.2", "magicast": "^0.3.2", "msw": "^1.2.2", "node-fetch": "^3.3.1", diff --git a/packages/cli/src/ai.ts b/packages/cli/src/ai.ts new file mode 100644 index 00000000..db0a9e70 --- /dev/null +++ b/packages/cli/src/ai.ts @@ -0,0 +1,58 @@ +import { loadLocalConfig } from "./util"; +import { globby } from "globby"; +import { getUseFeatureFlagRegex } from "@tryabby/core"; +import { readFile } from "fs/promises"; +import chalk from "chalk"; +import { HttpService } from "./http"; + +export async function removeFlagInstance(options: { + flagName: string; + apiKey: string; + path: string; + host?: string; + configPath?: string; +}) { + const files = await globby("**/*.tsx", { + cwd: options.path ?? process.cwd(), + absolute: true, + gitignore: true, + onlyFiles: true, + }); + + const regex = getUseFeatureFlagRegex(options.flagName); + + const filesToUse = ( + await Promise.all( + files.flatMap(async (filePath) => { + const content = await readFile(filePath, "utf-8").then((content) => { + const matches = content.match(regex); + return matches ? content : null; + }); + if (!content) return []; + + return { + filePath, + fileContent: content, + }; + }) + ) + ).flat(); + + await HttpService.getFilesWithFlagsRemoved({ + apiKey: options.apiKey, + files: filesToUse, + flagName: options.flagName, + apiUrl: options.host, + }); + + try { + const { mutableConfig, saveMutableConfig } = await loadLocalConfig( + options.configPath + ); + mutableConfig.flags = mutableConfig.flags.filter((flag: string) => flag !== options.flagName); + await saveMutableConfig(); + } catch (e) { + // fail silently + } + console.log(chalk.green("Flag removed successfully")); +} diff --git a/packages/cli/src/http.ts b/packages/cli/src/http.ts index 2fe384b6..2eb72e7f 100644 --- a/packages/cli/src/http.ts +++ b/packages/cli/src/http.ts @@ -3,6 +3,7 @@ import { ABBY_BASE_URL } from "./consts"; import fetch from "node-fetch"; import { multiLineLog } from "./util"; import chalk from "chalk"; +import { writeFile } from "fs/promises"; export abstract class HttpService { static async getConfigFromServer({ @@ -69,4 +70,53 @@ export abstract class HttpService { throw e; } } + + static async getFilesWithFlagsRemoved({ + apiKey, + files, + flagName, + apiUrl, + }: { + apiKey: string; + files: Array<{ filePath: string; fileContent: string }>; + flagName: string; + apiUrl?: string; + }) { + const url = apiUrl ?? ABBY_BASE_URL; + + try { + const response = await fetch(`${url}/api/ee/v1/abby-ai/flag-removal`, { + method: "POST", + headers: { + Authorization: "Bearer " + apiKey, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + flagName, + files, + }), + }); + + const status = response.status; + + if (status === 200) { + const res = await response.json(); + if (!Array.isArray(res)) { + throw new Error("Invalid response from server"); + } + console.log({ res, files }); + await Promise.all(res.map((file) => writeFile(file.filePath, file.fileContent))); + console.log(chalk.green("All files have been updated successfully")); + } else if (status === 500) { + throw new Error("Internal server error trying to update files"); + } else if (status === 401) { + throw new Error("Invalid API Key"); + } else { + throw new Error("Unable to update files"); + } + } catch (e) { + console.log(chalk.red(multiLineLog("Error: " + e))); + throw e; + } + } } diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 4f7928d8..4fd3cee3 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -13,6 +13,7 @@ import { initAbbyConfig } from "./init"; import { addCommandTypeSchema } from "./schemas"; import { addFlag } from "./add-flag"; import { addRemoteConfig } from "./add-remote-config"; +import { removeFlagInstance } from "./ai"; const program = new Command(); @@ -184,4 +185,24 @@ program } }); +const aiCommand = program.command("ai").description("Abby AI helpers"); + +aiCommand + .command("remove") + .description("remove a flag from your code") + .argument("", "The directory to scan for") + .argument("", "The flag name to remove") + .addOption(ConfigOption) + .addOption(HostOption) + .action(async (dir: string, flagName: string, options: { config?: string; host?: string }) => { + const files = await removeFlagInstance({ + apiKey: await getToken(), + flagName, + path: dir, + configPath: options.config, + host: options.host, + }); + console.log(files); + }); + program.parse(process.argv); diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 89d6e7e5..31802c7f 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,11 @@ # @tryabby/core +## 5.3.1 + +### Patch Changes + +- d05cb9a: add feature flag removal command + ## 5.3.0 ### Minor Changes diff --git a/packages/core/package.json b/packages/core/package.json index 8846e6a4..8fdac9fe 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@tryabby/core", - "version": "5.3.0", + "version": "5.3.1", "description": "", "main": "dist/index.js", "files": [ diff --git a/packages/core/src/shared/helpers.ts b/packages/core/src/shared/helpers.ts index 78cfd598..94ec5fea 100644 --- a/packages/core/src/shared/helpers.ts +++ b/packages/core/src/shared/helpers.ts @@ -67,3 +67,6 @@ export function stringifyRemoteConfigValue(value: RemoteConfigValue) { assertUnreachable(value); } } + +export const getUseFeatureFlagRegex = (flagName: string) => + new RegExp(`useFeatureFlag\\s*\\(\\s*['"\`]${flagName}['"\`]\\s*\\)`); diff --git a/packages/next/CHANGELOG.md b/packages/next/CHANGELOG.md index 2d1b0f6d..d9976f8d 100644 --- a/packages/next/CHANGELOG.md +++ b/packages/next/CHANGELOG.md @@ -1,5 +1,11 @@ # @tryabby/next +## 5.1.2 + +### Patch Changes + +- @tryabby/react@5.2.1 + ## 5.1.1 ### Patch Changes diff --git a/packages/next/package.json b/packages/next/package.json index d22f2ed8..f98ad345 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "@tryabby/next", - "version": "5.1.1", + "version": "5.1.2", "description": "", "main": "dist/index.js", "files": [ diff --git a/packages/node/CHANGELOG.md b/packages/node/CHANGELOG.md index 35f9b5c1..9b90bdf7 100644 --- a/packages/node/CHANGELOG.md +++ b/packages/node/CHANGELOG.md @@ -1,5 +1,12 @@ # @tryabby/node +## 5.1.7 + +### Patch Changes + +- Updated dependencies [d05cb9a] + - @tryabby/core@5.3.1 + ## 5.1.6 ### Patch Changes diff --git a/packages/node/package.json b/packages/node/package.json index 1d2c94c4..952cdaf9 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@tryabby/node", - "version": "5.1.6", + "version": "5.1.7", "description": "", "main": "dist/index.js", "files": [ diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index c9c7edbf..285481e3 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,12 @@ # @tryabby/react +## 5.2.1 + +### Patch Changes + +- Updated dependencies [d05cb9a] + - @tryabby/core@5.3.1 + ## 5.2.0 ### Minor Changes diff --git a/packages/react/package.json b/packages/react/package.json index 6775d2e1..925a13af 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@tryabby/react", - "version": "5.2.0", + "version": "5.2.1", "description": "", "main": "dist/index.js", "files": [ diff --git a/packages/remix/CHANGELOG.md b/packages/remix/CHANGELOG.md index 949aea79..1e402f41 100644 --- a/packages/remix/CHANGELOG.md +++ b/packages/remix/CHANGELOG.md @@ -1,5 +1,11 @@ # @tryabby/next +## 1.0.3 + +### Patch Changes + +- @tryabby/react@5.2.1 + ## 1.0.2 ### Patch Changes diff --git a/packages/remix/package.json b/packages/remix/package.json index a5e079ab..f4847f96 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -1,6 +1,6 @@ { "name": "@tryabby/remix", - "version": "1.0.2", + "version": "1.0.3", "description": "", "main": "dist/index.js", "files": [ diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 94a33190..b7b86d8b 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,12 @@ # @tryabby/svelte +## 2.2.1 + +### Patch Changes + +- Updated dependencies [d05cb9a] + - @tryabby/core@5.3.1 + ## 2.2.0 ### Minor Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 3a07efda..e73b9009 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@tryabby/svelte", - "version": "2.2.0", + "version": "2.2.1", "main": "dist/index.umd.cjs", "homepage": "https://docs.tryabby.dev", "type": "module", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5a1a36dc..f840862e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -713,6 +713,9 @@ importers: figlet: specifier: ^1.6.0 version: 1.6.0 + globby: + specifier: ^14.0.2 + version: 14.0.2 magicast: specifier: ^0.3.2 version: 0.3.2 @@ -8537,7 +8540,7 @@ packages: engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} dependencies: cross-spawn: 7.0.3 - fast-glob: 3.2.12 + fast-glob: 3.3.2 is-glob: 4.0.3 open: 9.1.0 picocolors: 1.0.0 @@ -10267,6 +10270,11 @@ packages: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true + /@sindresorhus/merge-streams@2.3.0: + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + dev: false + /@socket.io/component-emitter@3.1.0: resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} @@ -12476,7 +12484,7 @@ packages: '@typescript-eslint/scope-manager': 5.59.9 '@typescript-eslint/types': 5.59.9 '@typescript-eslint/typescript-estree': 5.59.9(typescript@4.9.5) - debug: 4.3.5 + debug: 4.3.4 eslint: 7.32.0 typescript: 4.9.5 transitivePeerDependencies: @@ -12496,7 +12504,7 @@ packages: '@typescript-eslint/scope-manager': 5.59.9 '@typescript-eslint/types': 5.59.9 '@typescript-eslint/typescript-estree': 5.59.9(typescript@4.9.3) - debug: 4.3.5 + debug: 4.3.4 eslint: 8.29.0 typescript: 4.9.3 transitivePeerDependencies: @@ -17569,6 +17577,16 @@ packages: merge2: 1.4.1 micromatch: 4.0.5 + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -18218,7 +18236,7 @@ packages: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.2.12 + fast-glob: 3.3.2 ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 @@ -18233,6 +18251,18 @@ packages: merge2: 1.4.1 slash: 4.0.0 + /globby@14.0.2: + resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==} + engines: {node: '>=18'} + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.2 + ignore: 5.2.4 + path-type: 5.0.0 + slash: 5.1.0 + unicorn-magic: 0.1.0 + dev: false + /globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} dev: true @@ -23479,6 +23509,11 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + /path-type@5.0.0: + resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} + engines: {node: '>=12'} + dev: false + /pathe@1.1.1: resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} @@ -25650,6 +25685,11 @@ packages: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} engines: {node: '>=12'} + /slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + dev: false + /slice-ansi@4.0.0: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} @@ -27414,6 +27454,11 @@ packages: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} + /unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + dev: false + /unified@10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} dependencies: @@ -28241,8 +28286,8 @@ packages: strip-literal: 2.1.0 tinybench: 2.8.0 tinypool: 0.8.4 - vite: 5.3.1(@types/node@20.3.1) - vite-node: 1.5.0(@types/node@20.3.1) + vite: 5.3.1(@types/node@18.16.17) + vite-node: 1.5.0(@types/node@18.16.17) why-is-node-running: 2.2.2 transitivePeerDependencies: - less