dev-env-kit 0.1.3 → 1.1.0

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.
@@ -1,71 +1,71 @@
1
- # Example Dev Environment Configuration
2
- # Copy this file to .dev-env.yml and customize for your project
3
-
4
- name: my-project
5
- version: "1.0.0"
6
-
7
- dependencies:
8
- - type: npm
9
- command: npm install
10
- path: .
11
- # - type: pip
12
- # command: pip install -r requirements.txt
13
- # path: ./backend
14
-
15
- databases:
16
- - type: postgresql
17
- name: myapp_db
18
- version: "15"
19
- port: 5432
20
- host: localhost
21
- user: ${DB_USER} # Use environment variable
22
- password: ${DB_PASSWORD} # Use environment variable
23
- database: myapp
24
- migrations:
25
- - path: ./migrations
26
- command: npm run migrate
27
- seed:
28
- command: npm run seed
29
-
30
- # - type: redis
31
- # version: "7"
32
- # port: 6379
33
- # host: localhost
34
-
35
- services:
36
- # - type: rabbitmq
37
- # version: "3.12"
38
- # port: 5672
39
- # management_port: 15672
40
-
41
- # Environment variables (use .env file for secrets)
42
- env:
43
- NODE_ENV: development
44
- # Use ${VAR_NAME} syntax to reference .env variables
45
- DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@localhost:5432/myapp
46
- # REDIS_URL: redis://localhost:6379
47
-
48
- # Health checks to verify setup
49
- health_checks:
50
- - name: database
51
- type: postgresql
52
- connection_string: postgresql://${DB_USER}:${DB_PASSWORD}@localhost:5432/myapp
53
- # - name: redis
54
- # type: redis
55
- # url: redis://localhost:6379
56
-
57
- # Snapshot configuration
58
- snapshot:
59
- include_databases: true
60
- include_volumes: true
61
- exclude_paths:
62
- - node_modules
63
- - .git
64
- - dist
65
- - build
66
-
67
- # Docker Compose generation
68
- docker:
69
- enabled: true
70
- output_file: docker-compose.yml
71
- network_name: dev-network
1
+ # Example Dev Environment Configuration
2
+ # Copy this file to .dev-env.yml and customize for your project
3
+
4
+ name: my-project
5
+ version: "1.0.0"
6
+
7
+ dependencies:
8
+ - type: npm
9
+ command: npm install
10
+ path: .
11
+ # - type: pip
12
+ # command: pip install -r requirements.txt
13
+ # path: ./backend
14
+
15
+ databases:
16
+ - type: postgresql
17
+ name: myapp_db
18
+ version: "15"
19
+ port: 5432
20
+ host: localhost
21
+ user: ${DB_USER} # Use environment variable
22
+ password: ${DB_PASSWORD} # Use environment variable
23
+ database: myapp
24
+ migrations:
25
+ - path: ./migrations
26
+ command: npm run migrate
27
+ seed:
28
+ command: npm run seed
29
+
30
+ # - type: redis
31
+ # version: "7"
32
+ # port: 6379
33
+ # host: localhost
34
+
35
+ services:
36
+ # - type: rabbitmq
37
+ # version: "3.12"
38
+ # port: 5672
39
+ # management_port: 15672
40
+
41
+ # Environment variables (use .env file for secrets)
42
+ env:
43
+ NODE_ENV: development
44
+ # Use ${VAR_NAME} syntax to reference .env variables
45
+ DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@localhost:5432/myapp
46
+ # REDIS_URL: redis://localhost:6379
47
+
48
+ # Health checks to verify setup
49
+ health_checks:
50
+ - name: database
51
+ type: postgresql
52
+ connection_string: postgresql://${DB_USER}:${DB_PASSWORD}@localhost:5432/myapp
53
+ # - name: redis
54
+ # type: redis
55
+ # url: redis://localhost:6379
56
+
57
+ # Snapshot configuration
58
+ snapshot:
59
+ include_databases: true
60
+ include_volumes: true
61
+ exclude_paths:
62
+ - node_modules
63
+ - .git
64
+ - dist
65
+ - build
66
+
67
+ # Docker Compose generation
68
+ docker:
69
+ enabled: true
70
+ output_file: docker-compose.yml
71
+ network_name: dev-network
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Shabnam
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shabnam
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,128 +1,164 @@
1
- # envkit
2
-
3
- A CLI for local development environments: one-command setup, environment snapshots, and Docker Compose generation from a single config file.
4
-
5
- **Requires:** Node.js >= 16
6
-
7
- ## What it does
8
-
9
- - **Setup** Reads your project’s `.dev-env.yml`, installs dependencies, runs database migrations and seed commands.
10
- - **Generate** — Produces `docker-compose.yml` from the same config (databases, services, network).
11
- - **Snapshots** — Save and list copies of your current config under `.devkit/snapshots/<name>/` for later restore.
12
- - **Share** — Export sanitized config (no secrets) or import a shared config file.
13
-
14
- Config is one YAML file plus optional `.env` for secrets; you reference variables with `${VAR_NAME}`. The CLI finds the project root from the current directory (looks for `.dev-env.yml` or `package.json`).
15
-
16
- ## Install
17
-
18
- ```bash
19
- npm install -g dev-env-kit
20
- ```
21
-
22
- Or run without installing: `npx dev-env-kit <command>`
23
-
24
- ## How to use
25
-
26
- ### 1. Configure your project
27
-
28
- In your project root, add a `.dev-env.yml` that describes your dev environment (dependencies, databases, services). Copy the example file to `.dev-env.yml`, then edit:
29
-
30
- ```bash
31
- cp .dev-env.example.yml .dev-env.yml
32
- ```
33
-
34
- See [.dev-env.example.yml](./.dev-env.example.yml) for all options. Put secrets in a `.env` file and reference them in the config with `${VAR_NAME}`.
35
-
36
- ### 2. Set up the environment
37
-
38
- From the project root (or any subdirectory):
39
-
40
- ```bash
41
- envkit setup
42
- ```
43
-
44
- This installs dependencies, runs database migrations, and runs seed commands according to your config. Options:
45
-
46
- | Option | Description |
47
- |---------------|--------------------------------------|
48
- | `--skip-deps` | Skip installing dependencies |
49
- | `--skip-db` | Skip database migrations and seed |
50
- | `--dry-run` | Show what would run, without running |
51
-
52
- ### 3. Generate Docker Compose
53
-
54
- To create a `docker-compose.yml` from your `.dev-env.yml` (when `docker.enabled` is true):
55
-
56
- ```bash
57
- envkit generate
58
- ```
59
-
60
- Use `-o <file>` to write to a different file, e.g. `envkit generate -o docker-compose.dev.yml`.
61
-
62
- ### 4. Snapshots
63
-
64
- Save the current config and metadata under `.devkit/snapshots/<name>/`:
65
-
66
- ```bash
67
- envkit snapshot create [name]
68
- ```
69
-
70
- If you omit `name`, a timestamped name is used. List snapshots:
71
-
72
- ```bash
73
- envkit snapshot list
74
- ```
75
-
76
- Restore a snapshot to `.dev-env.yml`: `envkit snapshot restore <name>`.
77
-
78
- ### 5. Share (export / import)
79
-
80
- Export a sanitized copy of your config (passwords and secrets replaced with placeholders like `${DB_PASSWORD}`):
81
-
82
- ```bash
83
- envkit share export
84
- ```
85
-
86
- Writes to `dev-env.shared.yml` by default. Use `-o <file>` to choose another path.
87
-
88
- Import a shared config file into your project (validates and writes to `.dev-env.yml` by default):
89
-
90
- ```bash
91
- envkit share import path/to/dev-env.shared.yml
92
- ```
93
-
94
- Use `-o <file>` to write to a different path.
95
-
96
- ### 6. Global options
97
-
98
- - `-v, --verbose` — more log output
99
- - `-q, --quiet` — less output
100
-
101
- Example: `envkit -q setup`
102
-
103
- ### Quick reference
104
-
105
- | Command | Description |
106
- |-----------------------------|------------------------------------------|
107
- | `envkit setup` | Install deps, run migrations & seed |
108
- | `envkit generate` | Generate docker-compose from config |
109
- | `envkit snapshot create [name]` | Save current config to a snapshot |
110
- | `envkit snapshot list` | List snapshots |
111
- | `envkit snapshot restore <name>` | Restore a snapshot to .dev-env.yml |
112
- | `envkit share export` | Export sanitized config (-o file) |
113
- | `envkit share import <file>` | Import shared config (-o file) |
114
-
115
- Use `envkit --help` or `envkit <command> --help` for details.
116
-
117
- ## Testing
118
-
119
- ```bash
120
- npm install
121
- npm test
122
- ```
123
-
124
- Optional: `npm test -- --coverage` for a coverage report.
125
-
126
- ## License
127
-
128
- MIT
1
+ # envkit
2
+
3
+ **envkit** is a CLI that manages local development environments from a single config file. Define dependencies, databases, and services in one place; run one command to set up the project, generate Docker Compose, and optionally snapshot or share configs—without committing secrets.
4
+
5
+ **Requirements:** Node.js >= 16
6
+
7
+ ---
8
+
9
+ ## What it does
10
+
11
+ - **Setup** — Uses your `.dev-env.yml` to install dependencies and run database migrations and seed commands in one go.
12
+ - **Generate** — Builds a `docker-compose.yml` from the same config (databases, services, network).
13
+ - **Snapshots** — Saves and restores config versions under `.devkit/snapshots/` so you can switch between setups.
14
+ - **Share** Exports a sanitized config (secrets replaced with placeholders) or imports a shared config file into your project.
15
+
16
+ Configuration is a single YAML file; secrets live in `.env` and are referenced as `${VAR_NAME}`. The CLI discovers the project root from your current directory (it looks for `.dev-env.yml` or markers like `package.json`).
17
+
18
+ ---
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ npm install -g dev-env-kit
24
+ ```
25
+
26
+ After installation you can use either:
27
+
28
+ - **`envkit <command>`** short name
29
+ - **`dev-env-kit <command>`** — same, using the package name
30
+
31
+ After install, **path-setup** runs automatically: if you're in an interactive terminal, you may be prompted to add envkit to your PATH so `envkit` works from any folder. You can run it again anytime with `npx dev-env-kit path-setup` or `npx dev-env-kit pathsetup` (no hyphen; use `pathsetup` if your shell doesn't like `path-setup`).
32
+
33
+ If the command is still not found, use:
34
+
35
+ ```bash
36
+ npx dev-env-kit <command>
37
+ ```
38
+
39
+ ---
40
+
41
+ ## How to use
42
+
43
+ ### 1. Add a config file
44
+
45
+ You need a `.dev-env.yml` in your project root for **setup**, **generate**, **share export**, and **snapshot create**. If you don’t have one yet:
46
+
47
+ - **Interactive terminal:** Run `envkit init` to create `.dev-env.yml` via a short wizard. If you run a command that needs config (e.g. `envkit setup`) without a config file, the CLI will ask whether to run `envkit init` now.
48
+ - **Non-interactive (CI, scripts):** Create `.dev-env.yml` by hand or run `envkit init` in a terminal first; otherwise those commands exit with a message to create a config or run `envkit init`.
49
+
50
+ **If you already have an example file**, the fastest way to start is to copy it and edit it:
51
+
52
+ ```bash
53
+ cp .dev-env.example.yml .dev-env.yml
54
+ ```
55
+
56
+ The example file documents all options (dependencies, databases, services, env vars, Docker settings). Keep sensitive values in a `.env` file and reference them in the config with `${VAR_NAME}` so they never end up in version control.
57
+
58
+ See [.dev-env.example.yml](./.dev-env.example.yml) for the full reference.
59
+
60
+ ### 2. Set up the environment
61
+
62
+ From the project root (or any subdirectory):
63
+
64
+ ```bash
65
+ envkit setup
66
+ ```
67
+
68
+ This installs dependencies, runs database migrations, and runs seed commands according to your config. You can narrow what runs:
69
+
70
+ | Option | Description |
71
+ |---------------|--------------------------------------|
72
+ | `--skip-deps` | Skip dependency installation |
73
+ | `--skip-db` | Skip database migrations and seed |
74
+ | `--dry-run` | Show what would run, without running |
75
+
76
+ ### 3. Generate Docker Compose
77
+
78
+ When `docker.enabled` is set in your config, you can generate a Compose file from it:
79
+
80
+ ```bash
81
+ envkit generate
82
+ ```
83
+
84
+ Output goes to `docker-compose.yml` by default. Use `-o <file>` to write elsewhere, e.g. `envkit generate -o docker-compose.dev.yml`.
85
+
86
+ ### 4. Snapshots
87
+
88
+ Save the current config as a named snapshot under `.devkit/snapshots/`:
89
+
90
+ ```bash
91
+ envkit snapshot create [name]
92
+ ```
93
+
94
+ If you omit the name, a timestamp-based name is used. List existing snapshots:
95
+
96
+ ```bash
97
+ envkit snapshot list
98
+ ```
99
+
100
+ Restore a snapshot (overwrites `.dev-env.yml`):
101
+
102
+ ```bash
103
+ envkit snapshot restore <name>
104
+ ```
105
+
106
+ ### 5. Share config (export / import)
107
+
108
+ Export a safe-to-share copy of your config (passwords and secrets become placeholders like `${DB_PASSWORD}`):
109
+
110
+ ```bash
111
+ envkit share export
112
+ ```
113
+
114
+ By default this writes `dev-env.shared.yml`. Use `-o <file>` to change the path.
115
+
116
+ Import a shared config file (it is validated and then written to `.dev-env.yml` by default):
117
+
118
+ ```bash
119
+ envkit share import path/to/dev-env.shared.yml
120
+ ```
121
+
122
+ Use `-o <file>` to write to a different path.
123
+
124
+ ### Global options
125
+
126
+ - **`-v, --verbose`** — More detailed log output.
127
+ - **`-q, --quiet`** — Reduce output.
128
+
129
+ Example: `envkit -q setup`
130
+
131
+ ---
132
+
133
+ ## Command reference
134
+
135
+ | Command | Description |
136
+ |--------|-------------|
137
+ | `envkit init` | Create `.dev-env.yml` interactively (wizard) |
138
+ | `envkit setup` | Install deps, run migrations and seed |
139
+ | `envkit generate` | Generate docker-compose from config |
140
+ | `envkit snapshot create [name]` | Save current config as a snapshot |
141
+ | `envkit snapshot list` | List snapshots |
142
+ | `envkit snapshot restore <name>` | Restore a snapshot to `.dev-env.yml` |
143
+ | `envkit share export` | Export sanitized config (optional `-o` path) |
144
+ | `envkit share import <file>` | Import shared config (optional `-o` path) |
145
+
146
+ For more detail: `envkit --help` or `envkit <command> --help`.
147
+ ---
148
+
149
+ ## Development and testing
150
+
151
+ To work on the source or run tests:
152
+
153
+ ```bash
154
+ npm install
155
+ npm test
156
+ ```
157
+
158
+ Use `npm test -- --coverage` for a coverage report.
159
+
160
+ ---
161
+
162
+ ## License
163
+
164
+ MIT
package/dist/cli/index.js CHANGED
@@ -44,8 +44,11 @@ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
44
44
  const version = packageJson.version;
45
45
  const setup_1 = require("../commands/setup");
46
46
  const generate_1 = require("../commands/generate");
47
+ const init_1 = require("../commands/init");
47
48
  const snapshot_1 = require("../commands/snapshot");
48
49
  const share_1 = require("../commands/share");
50
+ const path_setup_1 = require("../commands/path-setup");
51
+ const loader_1 = require("../core/config/loader");
49
52
  const program = new commander_1.Command();
50
53
  program
51
54
  .name('envkit')
@@ -64,6 +67,23 @@ program
64
67
  const os = (0, platform_1.detectOS)();
65
68
  logger_1.logger.debug(`Running on ${os}`);
66
69
  });
70
+ program
71
+ .command('init')
72
+ .description('Create .dev-env.yml interactively (wizard)')
73
+ .action(async () => {
74
+ try {
75
+ if (!(0, init_1.isInteractive)()) {
76
+ logger_1.logger.error('Run `envkit init` in a terminal to create a config file.');
77
+ process.exit(1);
78
+ }
79
+ const projectRoot = await (0, loader_1.findProjectRoot)();
80
+ await (0, init_1.runInit)(projectRoot);
81
+ }
82
+ catch (err) {
83
+ logger_1.logger.error(err.message ?? 'Init failed');
84
+ process.exit(1);
85
+ }
86
+ });
67
87
  program
68
88
  .command('setup')
69
89
  .description('Set up the development environment')
@@ -167,6 +187,19 @@ shareCommand
167
187
  process.exit(1);
168
188
  }
169
189
  });
190
+ program
191
+ .command('path-setup')
192
+ .alias('pathsetup')
193
+ .description('Add envkit to your PATH so you can run "envkit" from any folder')
194
+ .action(async () => {
195
+ try {
196
+ await (0, path_setup_1.runPathSetup)();
197
+ }
198
+ catch (err) {
199
+ logger_1.logger.error(err.message ?? 'Path setup failed');
200
+ process.exit(1);
201
+ }
202
+ });
170
203
  program.parseAsync().catch((error) => {
171
204
  if (error.code !== 'commander.helpDisplayed' && error.code !== 'commander.help') {
172
205
  logger_1.logger.error(error.message || 'An error occurred');
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -47,7 +47,7 @@ async function runGenerate(options = {}) {
47
47
  const outputFile = options.output ?? 'docker-compose.yml';
48
48
  const projectRoot = await (0, loader_1.findProjectRoot)(process.cwd());
49
49
  logger_1.logger.debug(`Project root: ${projectRoot}`);
50
- const config = await (0, loader_1.loadConfig)(projectRoot);
50
+ const config = await (0, loader_1.loadConfigOrPromptInit)(projectRoot);
51
51
  (0, validator_1.checkConfigWarnings)(config);
52
52
  if (config.docker?.enabled === false) {
53
53
  logger_1.logger.info('Docker generation is disabled in config (docker.enabled: false).');
@@ -1 +1 @@
1
- {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,kCAoBC;AAnCD,2CAA6B;AAC7B,kDAAoE;AACpE,wDAA+D;AAC/D,wEAA0E;AAC1E,4CAAyC;AACzC,gDAA8C;AAM9C,SAAS,eAAe;IACtB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AACpD,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,UAA2B,EAAE;IAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,oBAAoB,CAAC;IAE1D,MAAM,WAAW,GAAG,MAAM,IAAA,wBAAe,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,eAAM,CAAC,KAAK,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,MAAM,IAAA,mBAAU,EAAC,WAAW,CAAC,CAAC;IAC7C,IAAA,+BAAmB,EAAC,MAAM,CAAC,CAAC;IAE5B,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK,EAAE,CAAC;QACrC,eAAM,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,IAAA,0CAAsB,EAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAEtD,MAAM,IAAA,oBAAS,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClC,eAAM,CAAC,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,kCAoBC;AAnCD,2CAA6B;AAC7B,kDAAgF;AAChF,wDAA+D;AAC/D,wEAA0E;AAC1E,4CAAyC;AACzC,gDAA8C;AAM9C,SAAS,eAAe;IACtB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AACpD,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,UAA2B,EAAE;IAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,oBAAoB,CAAC;IAE1D,MAAM,WAAW,GAAG,MAAM,IAAA,wBAAe,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,eAAM,CAAC,KAAK,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,MAAM,IAAA,+BAAsB,EAAC,WAAW,CAAC,CAAC;IACzD,IAAA,+BAAmB,EAAC,MAAM,CAAC,CAAC;IAE5B,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK,EAAE,CAAC;QACrC,eAAM,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,IAAA,0CAAsB,EAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAEtD,MAAM,IAAA,oBAAS,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClC,eAAM,CAAC,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare function isInteractive(): boolean;
2
+ export declare function getDefaultProjectName(projectRoot: string): Promise<string>;
3
+ /**
4
+ * Run the init wizard and write `.dev-env.yml` in the project root.
5
+ * Exported for use by the CLI and by loadConfigOrPromptInit.
6
+ */
7
+ export declare function runInit(projectRoot: string): Promise<void>;
8
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA6BA,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahF;AA6PD;;;GAGG;AACH,wBAAsB,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBhE"}