@agentforge-ai/cli 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -112,17 +112,137 @@ async function runProject(options) {
112
112
  process.on("SIGTERM", shutdown);
113
113
  }
114
114
 
115
+ // src/commands/deploy.ts
116
+ import path3 from "path";
117
+ import { execSync as execSync2 } from "child_process";
118
+ import fs3 from "fs-extra";
119
+ function parseEnvFile(filePath) {
120
+ const content = fs3.readFileSync(filePath, "utf-8");
121
+ const vars = {};
122
+ for (const line of content.split("\n")) {
123
+ const trimmed = line.trim();
124
+ if (!trimmed || trimmed.startsWith("#")) continue;
125
+ const eqIndex = trimmed.indexOf("=");
126
+ if (eqIndex === -1) continue;
127
+ const key = trimmed.slice(0, eqIndex).trim();
128
+ let value = trimmed.slice(eqIndex + 1).trim();
129
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
130
+ value = value.slice(1, -1);
131
+ }
132
+ if (key) {
133
+ vars[key] = value;
134
+ }
135
+ }
136
+ return vars;
137
+ }
138
+ async function deployProject(options) {
139
+ const projectDir = process.cwd();
140
+ const pkgPath = path3.join(projectDir, "package.json");
141
+ if (!await fs3.pathExists(pkgPath)) {
142
+ console.error(
143
+ "Error: No package.json found. Are you in an AgentForge project directory?"
144
+ );
145
+ process.exit(1);
146
+ }
147
+ const convexDir = path3.join(projectDir, "convex");
148
+ if (!await fs3.pathExists(convexDir)) {
149
+ console.error(
150
+ "Error: No convex/ directory found. Are you in an AgentForge project directory?"
151
+ );
152
+ process.exit(1);
153
+ }
154
+ if (options.rollback) {
155
+ console.log("\n\u{1F504} Rolling back to previous Convex deployment...\n");
156
+ try {
157
+ execSync2("npx convex deploy --rollback", {
158
+ cwd: projectDir,
159
+ stdio: "inherit"
160
+ });
161
+ console.log("\n \u2705 Rollback completed successfully.");
162
+ } catch {
163
+ console.error("\n \u274C Rollback failed.");
164
+ process.exit(1);
165
+ }
166
+ return;
167
+ }
168
+ const envPath = path3.resolve(projectDir, options.env);
169
+ const envExists = await fs3.pathExists(envPath);
170
+ let envVars = {};
171
+ if (envExists) {
172
+ envVars = parseEnvFile(envPath);
173
+ }
174
+ if (options.dryRun) {
175
+ console.log("\n\u{1F50D} Dry run \u2014 previewing deployment plan:\n");
176
+ console.log(` Project directory: ${projectDir}`);
177
+ console.log(` Convex directory: ${convexDir}`);
178
+ console.log(` Environment file: ${envExists ? envPath : "(not found, skipping env vars)"}`);
179
+ if (Object.keys(envVars).length > 0) {
180
+ console.log(`
181
+ Environment variables to set (${Object.keys(envVars).length}):`);
182
+ for (const key of Object.keys(envVars)) {
183
+ console.log(` \u2022 ${key}=${envVars[key].slice(0, 4)}${"*".repeat(Math.max(0, envVars[key].length - 4))}`);
184
+ }
185
+ } else {
186
+ console.log("\n No environment variables to set.");
187
+ }
188
+ console.log("\n \u2139\uFE0F No changes were made (dry run).\n");
189
+ return;
190
+ }
191
+ if (!envExists) {
192
+ console.error(
193
+ `Error: Environment file "${options.env}" not found. Create it or use --env to specify a different path.`
194
+ );
195
+ process.exit(1);
196
+ }
197
+ if (!options.force) {
198
+ console.log("\n\u{1F680} Deployment plan:\n");
199
+ console.log(` Project: ${projectDir}`);
200
+ console.log(` Env file: ${envPath}`);
201
+ console.log(` Env vars: ${Object.keys(envVars).length} variable(s)`);
202
+ console.log("\n Use --force to skip this confirmation.\n");
203
+ }
204
+ console.log("\n\u{1F4E6} Deploying AgentForge project to production...\n");
205
+ if (Object.keys(envVars).length > 0) {
206
+ console.log(" Setting environment variables...");
207
+ for (const [key, value] of Object.entries(envVars)) {
208
+ try {
209
+ execSync2(`npx convex env set ${key} "${value}"`, {
210
+ cwd: projectDir,
211
+ stdio: "pipe"
212
+ });
213
+ console.log(` \u2705 ${key}`);
214
+ } catch {
215
+ console.error(` \u274C Failed to set ${key}`);
216
+ }
217
+ }
218
+ console.log("");
219
+ }
220
+ console.log(" Deploying Convex backend...");
221
+ try {
222
+ execSync2("npx convex deploy", {
223
+ cwd: projectDir,
224
+ stdio: "inherit"
225
+ });
226
+ console.log("\n \u2705 Deployment completed successfully!");
227
+ console.log(' Use "agentforge deploy --rollback" to revert if needed.\n');
228
+ } catch {
229
+ console.error("\n \u274C Deployment failed.");
230
+ console.error(" Check the Convex dashboard for details.");
231
+ process.exit(1);
232
+ }
233
+ }
234
+
115
235
  // src/index.ts
116
236
  var program = new Command();
117
- program.name("agentforge").description("CLI tool for creating, running, and managing AgentForge projects").version("0.1.0");
237
+ program.name("agentforge").description("CLI tool for creating, running, and managing AgentForge projects").version("0.2.0");
118
238
  program.command("create").argument("<project-name>", "Name of the project to create").description("Create a new AgentForge project").option("-t, --template <template>", "Project template to use", "default").action(async (projectName, options) => {
119
239
  await createProject(projectName, options);
120
240
  });
121
241
  program.command("run").description("Start the local development environment").option("-p, --port <port>", "Port for the dev server", "3000").action(async (options) => {
122
242
  await runProject(options);
123
243
  });
124
- program.command("deploy").description("Deploy the project (coming soon)").action(() => {
125
- console.log("Deploy command coming soon. Stay tuned!");
244
+ program.command("deploy").description("Deploy the Convex backend to production").option("--env <path>", "Path to environment file", ".env.production").option("--dry-run", "Preview deployment without executing", false).option("--rollback", "Rollback to previous deployment", false).option("--force", "Skip confirmation prompts", false).action(async (options) => {
245
+ await deployProject(options);
126
246
  });
127
247
  program.parse();
128
248
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/commands/run.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createProject } from './commands/create.js';\nimport { runProject } from './commands/run.js';\n\nconst program = new Command();\n\nprogram\n .name('agentforge')\n .description('CLI tool for creating, running, and managing AgentForge projects')\n .version('0.1.0');\n\nprogram\n .command('create')\n .argument('<project-name>', 'Name of the project to create')\n .description('Create a new AgentForge project')\n .option('-t, --template <template>', 'Project template to use', 'default')\n .action(async (projectName: string, options: { template: string }) => {\n await createProject(projectName, options);\n });\n\nprogram\n .command('run')\n .description('Start the local development environment')\n .option('-p, --port <port>', 'Port for the dev server', '3000')\n .action(async (options: { port: string }) => {\n await runProject(options);\n });\n\nprogram\n .command('deploy')\n .description('Deploy the project (coming soon)')\n .action(() => {\n console.log('Deploy command coming soon. Stay tuned!');\n });\n\nprogram.parse();\n","import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport fs from 'fs-extra';\nimport { execSync } from 'node:child_process';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Options for the create command.\n */\nexport interface CreateOptions {\n /** The project template to use. */\n template: string;\n}\n\n/**\n * Creates a new AgentForge project from a template.\n *\n * @param projectName - The name of the project to create.\n * @param options - Options for the create command.\n */\nexport async function createProject(\n projectName: string,\n options: CreateOptions\n): Promise<void> {\n const targetDir = path.resolve(process.cwd(), projectName);\n\n // Check if directory already exists\n if (await fs.pathExists(targetDir)) {\n console.error(`Error: Directory \"${projectName}\" already exists.`);\n process.exit(1);\n }\n\n console.log(`\\nšŸ”Ø Creating AgentForge project: ${projectName}\\n`);\n\n // Resolve template directory\n const templateDir = path.resolve(\n __dirname,\n '..', // from dist/commands to dist\n 'templates',\n options.template\n );\n\n if (!(await fs.pathExists(templateDir))) {\n console.error(`Error: Template \"${options.template}\" not found.`);\n process.exit(1);\n }\n\n // Copy template to target directory\n await fs.copy(templateDir, targetDir);\n\n // Update package.json with project name\n const pkgPath = path.join(targetDir, 'package.json');\n if (await fs.pathExists(pkgPath)) {\n const pkg = await fs.readJson(pkgPath);\n pkg.name = projectName;\n await fs.writeJson(pkgPath, pkg, { spaces: 2 });\n }\n\n console.log(` āœ… Project scaffolded at ./${projectName}`);\n\n // Install dependencies\n console.log(`\\nšŸ“¦ Installing dependencies...\\n`);\n try {\n execSync('pnpm install', {\n cwd: targetDir,\n stdio: 'inherit',\n });\n console.log(`\\n āœ… Dependencies installed`);\n } catch {\n console.warn(\n `\\n āš ļø Could not install dependencies. Run \"cd ${projectName} && pnpm install\" manually.`\n );\n }\n\n console.log(`\nšŸŽ‰ AgentForge project \"${projectName}\" created successfully!\n\nNext steps:\n cd ${projectName}\n agentforge run\n\nDocumentation: https://github.com/Agentic-Engineering-Agency/agentforge\n`);\n}\n","import { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport fs from 'fs-extra';\n\n/**\n * Options for the run command.\n */\nexport interface RunOptions {\n /** The port for the dev server. */\n port: string;\n}\n\n/**\n * Starts the local development environment for an AgentForge project.\n *\n * This command starts the Convex development server and watches for file changes.\n *\n * @param options - Options for the run command.\n */\nexport async function runProject(options: RunOptions): Promise<void> {\n const projectDir = process.cwd();\n\n // Verify we're in an AgentForge project\n const pkgPath = path.join(projectDir, 'package.json');\n if (!(await fs.pathExists(pkgPath))) {\n console.error(\n 'Error: No package.json found. Are you in an AgentForge project directory?'\n );\n process.exit(1);\n }\n\n const convexDir = path.join(projectDir, 'convex');\n if (!(await fs.pathExists(convexDir))) {\n console.error(\n 'Error: No convex/ directory found. Are you in an AgentForge project directory?'\n );\n process.exit(1);\n }\n\n console.log(`\\nšŸš€ Starting AgentForge development server...\\n`);\n console.log(` Convex dev server starting on port ${options.port}...`);\n\n // Start the Convex dev server\n const convexProcess = spawn('npx', ['convex', 'dev'], {\n cwd: projectDir,\n stdio: 'inherit',\n shell: true,\n });\n\n convexProcess.on('error', (err) => {\n console.error(`Failed to start Convex dev server: ${err.message}`);\n process.exit(1);\n });\n\n convexProcess.on('close', (code) => {\n if (code !== 0) {\n console.error(`Convex dev server exited with code ${code}`);\n }\n });\n\n // Handle graceful shutdown\n const shutdown = () => {\n console.log('\\n\\nšŸ‘‹ Shutting down AgentForge dev server...');\n convexProcess.kill('SIGTERM');\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n"],"mappings":"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","names":["path","fs"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/commands/run.ts","../src/commands/deploy.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createProject } from './commands/create.js';\nimport { runProject } from './commands/run.js';\nimport { deployProject } from './commands/deploy.js';\n\nconst program = new Command();\n\nprogram\n .name('agentforge')\n .description('CLI tool for creating, running, and managing AgentForge projects')\n .version('0.2.0');\n\nprogram\n .command('create')\n .argument('<project-name>', 'Name of the project to create')\n .description('Create a new AgentForge project')\n .option('-t, --template <template>', 'Project template to use', 'default')\n .action(async (projectName: string, options: { template: string }) => {\n await createProject(projectName, options);\n });\n\nprogram\n .command('run')\n .description('Start the local development environment')\n .option('-p, --port <port>', 'Port for the dev server', '3000')\n .action(async (options: { port: string }) => {\n await runProject(options);\n });\n\nprogram\n .command('deploy')\n .description('Deploy the Convex backend to production')\n .option('--env <path>', 'Path to environment file', '.env.production')\n .option('--dry-run', 'Preview deployment without executing', false)\n .option('--rollback', 'Rollback to previous deployment', false)\n .option('--force', 'Skip confirmation prompts', false)\n .action(async (options: { env: string; dryRun: boolean; rollback: boolean; force: boolean }) => {\n await deployProject(options);\n });\n\nprogram.parse();\n","import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport fs from 'fs-extra';\nimport { execSync } from 'node:child_process';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Options for the create command.\n */\nexport interface CreateOptions {\n /** The project template to use. */\n template: string;\n}\n\n/**\n * Creates a new AgentForge project from a template.\n *\n * @param projectName - The name of the project to create.\n * @param options - Options for the create command.\n */\nexport async function createProject(\n projectName: string,\n options: CreateOptions\n): Promise<void> {\n const targetDir = path.resolve(process.cwd(), projectName);\n\n // Check if directory already exists\n if (await fs.pathExists(targetDir)) {\n console.error(`Error: Directory \"${projectName}\" already exists.`);\n process.exit(1);\n }\n\n console.log(`\\nšŸ”Ø Creating AgentForge project: ${projectName}\\n`);\n\n // Resolve template directory\n const templateDir = path.resolve(\n __dirname,\n '..', // from dist/commands to dist\n 'templates',\n options.template\n );\n\n if (!(await fs.pathExists(templateDir))) {\n console.error(`Error: Template \"${options.template}\" not found.`);\n process.exit(1);\n }\n\n // Copy template to target directory\n await fs.copy(templateDir, targetDir);\n\n // Update package.json with project name\n const pkgPath = path.join(targetDir, 'package.json');\n if (await fs.pathExists(pkgPath)) {\n const pkg = await fs.readJson(pkgPath);\n pkg.name = projectName;\n await fs.writeJson(pkgPath, pkg, { spaces: 2 });\n }\n\n console.log(` āœ… Project scaffolded at ./${projectName}`);\n\n // Install dependencies\n console.log(`\\nšŸ“¦ Installing dependencies...\\n`);\n try {\n execSync('pnpm install', {\n cwd: targetDir,\n stdio: 'inherit',\n });\n console.log(`\\n āœ… Dependencies installed`);\n } catch {\n console.warn(\n `\\n āš ļø Could not install dependencies. Run \"cd ${projectName} && pnpm install\" manually.`\n );\n }\n\n console.log(`\nšŸŽ‰ AgentForge project \"${projectName}\" created successfully!\n\nNext steps:\n cd ${projectName}\n agentforge run\n\nDocumentation: https://github.com/Agentic-Engineering-Agency/agentforge\n`);\n}\n","import { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport fs from 'fs-extra';\n\n/**\n * Options for the run command.\n */\nexport interface RunOptions {\n /** The port for the dev server. */\n port: string;\n}\n\n/**\n * Starts the local development environment for an AgentForge project.\n *\n * This command starts the Convex development server and watches for file changes.\n *\n * @param options - Options for the run command.\n */\nexport async function runProject(options: RunOptions): Promise<void> {\n const projectDir = process.cwd();\n\n // Verify we're in an AgentForge project\n const pkgPath = path.join(projectDir, 'package.json');\n if (!(await fs.pathExists(pkgPath))) {\n console.error(\n 'Error: No package.json found. Are you in an AgentForge project directory?'\n );\n process.exit(1);\n }\n\n const convexDir = path.join(projectDir, 'convex');\n if (!(await fs.pathExists(convexDir))) {\n console.error(\n 'Error: No convex/ directory found. Are you in an AgentForge project directory?'\n );\n process.exit(1);\n }\n\n console.log(`\\nšŸš€ Starting AgentForge development server...\\n`);\n console.log(` Convex dev server starting on port ${options.port}...`);\n\n // Start the Convex dev server\n const convexProcess = spawn('npx', ['convex', 'dev'], {\n cwd: projectDir,\n stdio: 'inherit',\n shell: true,\n });\n\n convexProcess.on('error', (err) => {\n console.error(`Failed to start Convex dev server: ${err.message}`);\n process.exit(1);\n });\n\n convexProcess.on('close', (code) => {\n if (code !== 0) {\n console.error(`Convex dev server exited with code ${code}`);\n }\n });\n\n // Handle graceful shutdown\n const shutdown = () => {\n console.log('\\n\\nšŸ‘‹ Shutting down AgentForge dev server...');\n convexProcess.kill('SIGTERM');\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n","import path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport fs from 'fs-extra';\n\n/**\n * Options for the deploy command.\n */\nexport interface DeployOptions {\n /** Path to the environment file. */\n env: string;\n /** Preview deployment without executing. */\n dryRun: boolean;\n /** Rollback to previous deployment. */\n rollback: boolean;\n /** Skip confirmation prompts. */\n force: boolean;\n}\n\n/**\n * Parses a .env file and returns key-value pairs.\n *\n * @param filePath - Absolute path to the .env file.\n * @returns A record of environment variable key-value pairs.\n */\nexport function parseEnvFile(filePath: string): Record<string, string> {\n const content = fs.readFileSync(filePath, 'utf-8');\n const vars: Record<string, string> = {};\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n // Remove surrounding quotes\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n if (key) {\n vars[key] = value;\n }\n }\n\n return vars;\n}\n\n/**\n * Deploys an AgentForge project's Convex backend to production.\n *\n * Handles environment variable configuration, provides deployment status\n * feedback, and supports rollback capabilities.\n *\n * @param options - Options for the deploy command.\n */\nexport async function deployProject(options: DeployOptions): Promise<void> {\n const projectDir = process.cwd();\n\n // Validate project structure\n const pkgPath = path.join(projectDir, 'package.json');\n if (!(await fs.pathExists(pkgPath))) {\n console.error(\n 'Error: No package.json found. Are you in an AgentForge project directory?'\n );\n process.exit(1);\n }\n\n const convexDir = path.join(projectDir, 'convex');\n if (!(await fs.pathExists(convexDir))) {\n console.error(\n 'Error: No convex/ directory found. Are you in an AgentForge project directory?'\n );\n process.exit(1);\n }\n\n // Handle rollback mode\n if (options.rollback) {\n console.log('\\nšŸ”„ Rolling back to previous Convex deployment...\\n');\n try {\n execSync('npx convex deploy --rollback', {\n cwd: projectDir,\n stdio: 'inherit',\n });\n console.log('\\n āœ… Rollback completed successfully.');\n } catch {\n console.error('\\n āŒ Rollback failed.');\n process.exit(1);\n }\n return;\n }\n\n // Resolve and validate env file\n const envPath = path.resolve(projectDir, options.env);\n const envExists = await fs.pathExists(envPath);\n\n // Parse env vars if file exists\n let envVars: Record<string, string> = {};\n if (envExists) {\n envVars = parseEnvFile(envPath);\n }\n\n // Handle dry-run mode\n if (options.dryRun) {\n console.log('\\nšŸ” Dry run — previewing deployment plan:\\n');\n console.log(` Project directory: ${projectDir}`);\n console.log(` Convex directory: ${convexDir}`);\n console.log(` Environment file: ${envExists ? envPath : '(not found, skipping env vars)'}`);\n\n if (Object.keys(envVars).length > 0) {\n console.log(`\\n Environment variables to set (${Object.keys(envVars).length}):`);\n for (const key of Object.keys(envVars)) {\n console.log(` • ${key}=${envVars[key].slice(0, 4)}${'*'.repeat(Math.max(0, envVars[key].length - 4))}`);\n }\n } else {\n console.log('\\n No environment variables to set.');\n }\n\n console.log('\\n ā„¹ļø No changes were made (dry run).\\n');\n return;\n }\n\n // Require env file for actual deployment\n if (!envExists) {\n console.error(\n `Error: Environment file \"${options.env}\" not found. Create it or use --env to specify a different path.`\n );\n process.exit(1);\n }\n\n // Confirmation prompt (unless --force)\n if (!options.force) {\n console.log('\\nšŸš€ Deployment plan:\\n');\n console.log(` Project: ${projectDir}`);\n console.log(` Env file: ${envPath}`);\n console.log(` Env vars: ${Object.keys(envVars).length} variable(s)`);\n console.log('\\n Use --force to skip this confirmation.\\n');\n\n // In a real CLI, we'd use prompts here. For now, auto-proceed.\n // The --force flag is the recommended path for CI/CD.\n }\n\n console.log('\\nšŸ“¦ Deploying AgentForge project to production...\\n');\n\n // Step 1: Push environment variables\n if (Object.keys(envVars).length > 0) {\n console.log(' Setting environment variables...');\n for (const [key, value] of Object.entries(envVars)) {\n try {\n execSync(`npx convex env set ${key} \"${value}\"`, {\n cwd: projectDir,\n stdio: 'pipe',\n });\n console.log(` āœ… ${key}`);\n } catch {\n console.error(` āŒ Failed to set ${key}`);\n }\n }\n console.log('');\n }\n\n // Step 2: Deploy\n console.log(' Deploying Convex backend...');\n try {\n execSync('npx convex deploy', {\n cwd: projectDir,\n stdio: 'inherit',\n });\n console.log('\\n āœ… Deployment completed successfully!');\n console.log(' Use \"agentforge deploy --rollback\" to revert if needed.\\n');\n } catch {\n console.error('\\n āŒ Deployment failed.');\n console.error(' Check the Convex dashboard for details.');\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["path","fs","path","execSync","fs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge-ai/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "CLI tool for creating, running, and managing AgentForge projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,6 +15,7 @@
15
15
  "scripts": {
16
16
  "build": "tsup",
17
17
  "test": "vitest run",
18
+ "test:coverage": "vitest run --coverage",
18
19
  "test:watch": "vitest",
19
20
  "typecheck": "tsc --noEmit",
20
21
  "lint": "eslint src/",
@@ -10,7 +10,7 @@
10
10
  "convex:deploy": "npx convex deploy"
11
11
  },
12
12
  "dependencies": {
13
- "@agentforge-ai/core": "^0.1.0",
13
+ "@agentforge-ai/core": "^0.2.1",
14
14
  "convex": "^1.17.0"
15
15
  },
16
16
  "devDependencies": {