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