adamantite 0.25.0 → 0.26.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.
Files changed (2) hide show
  1. package/dist/index.js +772 -686
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -1,19 +1,65 @@
1
1
  // src/index.ts
2
- import yargs from "yargs";
3
- import { hideBin } from "yargs/helpers";
2
+ import process5 from "node:process";
3
+ import { Command as Command9 } from "@effect/cli";
4
+ import { NodeContext, NodeRuntime } from "@effect/platform-node";
5
+ import { Effect as Effect19, Layer as Layer4 } from "effect";
4
6
 
5
7
  // src/commands/analyze.ts
6
- import process3 from "node:process";
7
- import { log } from "@clack/prompts";
8
- import { Fault as Fault3 } from "faultier";
9
- import { ok as ok3, safeTry as safeTry3 } from "neverthrow";
10
- import { dlxCommand } from "nypm";
8
+ import { Command, Options } from "@effect/cli";
9
+ import { Command as ShellCommand2 } from "@effect/platform";
10
+ import { Effect as Effect6 } from "effect";
11
11
 
12
12
  // src/helpers/packages/knip.ts
13
- import { readFile as readFile2, writeFile } from "node:fs/promises";
14
- import { join as join2 } from "node:path";
15
- import { Fault as Fault2 } from "faultier";
16
- import { err as err2, fromPromise as fromPromise2, ok as ok2, safeTry as safeTry2 } from "neverthrow";
13
+ import { FileSystem as FileSystem2, Path as Path2 } from "@effect/platform";
14
+ import { Effect as Effect3 } from "effect";
15
+
16
+ // src/errors.ts
17
+ import { Data } from "effect";
18
+
19
+ class CliNotFound extends Data.TaggedError("CliNotFound") {
20
+ }
21
+
22
+ class FailedToCreateDirectory extends Data.TaggedError("FailedToCreateDirectory") {
23
+ }
24
+
25
+ class FailedToInstallDependency extends Data.TaggedError("FailedToInstallDependency") {
26
+ }
27
+
28
+ class FailedToInstallExtension extends Data.TaggedError("FailedToInstallExtension") {
29
+ }
30
+
31
+ class FailedToMergeConfig extends Data.TaggedError("FailedToMergeConfig") {
32
+ }
33
+
34
+ class FailedToParseFile extends Data.TaggedError("FailedToParseFile") {
35
+ }
36
+
37
+ class FailedToReadFile extends Data.TaggedError("FailedToReadFile") {
38
+ }
39
+
40
+ class FailedToWriteFile extends Data.TaggedError("FailedToWriteFile") {
41
+ }
42
+
43
+ class FileNotFound extends Data.TaggedError("FileNotFound") {
44
+ }
45
+
46
+ class InvalidConfigFormat extends Data.TaggedError("InvalidConfigFormat") {
47
+ }
48
+
49
+ class NoPackageManager extends Data.TaggedError("NoPackageManager") {
50
+ }
51
+
52
+ class MissingPackageVersion extends Data.TaggedError("MissingPackageVersion") {
53
+ }
54
+
55
+ class OperationCancelled extends Data.TaggedError("OperationCancelled") {
56
+ }
57
+
58
+ class UnknownScript extends Data.TaggedError("UnknownScript") {
59
+ }
60
+
61
+ class VscodeCliNotFound extends Data.TaggedError("VscodeCliNotFound") {
62
+ }
17
63
  // presets/knip.json
18
64
  var knip_default = {
19
65
  $schema: "https://unpkg.com/knip@5/schema.json",
@@ -46,64 +92,69 @@ var knip_default = {
46
92
  };
47
93
 
48
94
  // src/utils.ts
49
- import { spawnSync } from "node:child_process";
50
- import { access, readFile } from "node:fs/promises";
51
- import { join } from "node:path";
52
- import process2 from "node:process";
95
+ import process3 from "node:process";
96
+ import { Command as ShellCommand, FileSystem, Path, Terminal } from "@effect/platform";
53
97
  import { defu } from "defu";
54
- import { Fault } from "faultier";
98
+ import { Console, Effect as Effect2 } from "effect";
55
99
  import { parse } from "jsonc-parser";
56
- import { err, fromPromise, fromThrowable, ok, safeTry } from "neverthrow";
57
- import { detectPackageManager } from "nypm";
58
- function defineCommand(input) {
59
- return input;
100
+
101
+ // src/services/cwd.ts
102
+ import process2 from "node:process";
103
+ import { Context, Effect, Layer } from "effect";
104
+
105
+ class Cwd extends Context.Tag("Cwd")() {
60
106
  }
61
- var runCommand = (command) => {
62
- const result = spawnSync(command, {
63
- maxBuffer: 100 * 1024 * 1024,
64
- shell: true,
65
- stdio: "inherit"
66
- });
67
- if (result.error || result.status !== 0) {
68
- const message = result.error?.message ?? "An unknown error occurred while running the command";
69
- return err(Fault.wrap(result.error ?? new Error(message)).withTag("FAILED_TO_RUN_COMMAND").withDebug(`Failed to run command: ${message}`));
70
- }
71
- return ok(result);
72
- };
73
- var getPackageManagerName = () => fromPromise(detectPackageManager(process2.cwd()), () => "Failed to detect package manager").andThen((result) => result ? ok(result.name) : err("Failed to resolve package manager")).mapErr((message) => Fault.create("NO_PACKAGE_MANAGER").withDescription(message, "We're unable to detect the package manager used in this project. Please ensure you have a package.json file in the current directory."));
74
- var checkIfExists = (path) => fromPromise(access(path), () => new Error("File not found")).match(() => true, () => false);
107
+ var CwdLive = Layer.succeed(Cwd, {
108
+ get: Effect.sync(() => process2.cwd())
109
+ });
110
+
111
+ // src/utils.ts
75
112
  var checkCliExists = (command) => {
76
- const result = spawnSync(process2.platform === "win32" ? "where" : "which", [command], {
77
- stdio: "pipe"
78
- });
79
- if (result.status !== 0) {
80
- return err(Fault.create("CLI_NOT_FOUND").withDescription(`CLI '${command}' not found`, `The '${command}' command is not available in your PATH.`).withContext({ command }));
81
- }
82
- return ok(true);
113
+ const executable = process3.platform === "win32" ? "where" : "which";
114
+ return ShellCommand.make(executable, command).pipe(ShellCommand.exitCode, Effect2.flatMap((exitCode) => exitCode === 0 ? Effect2.succeed(true) : Effect2.fail(new CliNotFound({ command }))));
83
115
  };
84
- var parseJson = (content) => {
116
+ var parseJson = (content, path) => Effect2.sync(() => {
85
117
  const errors = [];
86
118
  const parsed = parse(content, errors);
87
- if (errors.length > 0) {
88
- return err(Fault.create("FAILED_TO_PARSE_FILE").withDescription("Failed to parse JSON", "We're unable to parse the provided JSON file.").withContext({ errors }));
89
- }
90
- return ok(parsed);
91
- };
119
+ return { errors, parsed };
120
+ }).pipe(Effect2.flatMap(({ errors, parsed }) => errors.length > 0 ? Effect2.fail(new FailedToParseFile({ errors, path })) : Effect2.succeed(parsed)));
92
121
  var isJsonObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
93
122
  var WORKSPACE_PREFIX_REGEX = /^workspace:/;
94
123
  var RANGE_PREFIX_REGEX = /^[\^~]/;
95
124
  var normalizeDependencyVersion = (specifier) => specifier.trim().replace(WORKSPACE_PREFIX_REGEX, "").replace(RANGE_PREFIX_REGEX, "");
96
- var mergeConfig = fromThrowable(defu, (error) => Fault.wrap(error).withTag("FAILED_TO_MERGE_CONFIG").withDescription("Failed to merge configuration", "We're unable to merge the configuration files."));
97
- var readPackageJson = (cwd = process2.cwd()) => fromPromise(readFile(join(cwd, "package.json"), "utf8"), (error) => Fault.wrap(error).withTag("FAILED_TO_READ_FILE").withDescription("Failed to read package.json", "We're unable to read the package.json file in the current directory.").withContext({ path: join(cwd, "package.json") })).andThen((content) => parseJson(content)).andThen((parsed) => ok(parsed));
98
- var checkIsMonorepo = () => safeTry(async function* () {
99
- const pnpmWorkspace = await checkIfExists(join(process2.cwd(), "pnpm-workspace.yaml"));
125
+ var mergeConfig = (base, override) => Effect2.try({
126
+ catch: (cause) => new FailedToMergeConfig({ cause }),
127
+ try: () => defu(base, override)
128
+ });
129
+ var readPackageJson = (cwd) => Effect2.gen(function* () {
130
+ const fs = yield* FileSystem.FileSystem;
131
+ const path = yield* Path.Path;
132
+ const cwdService = yield* Cwd;
133
+ const workingDir = cwd ?? (yield* cwdService.get);
134
+ const packagePath = path.join(workingDir, "package.json");
135
+ const content = yield* fs.readFileString(packagePath).pipe(Effect2.mapError((cause) => new FailedToReadFile({ cause, path: packagePath })));
136
+ const parsed = yield* parseJson(content, packagePath);
137
+ return parsed;
138
+ });
139
+ var checkIsMonorepo = () => Effect2.gen(function* () {
140
+ const fs = yield* FileSystem.FileSystem;
141
+ const path = yield* Path.Path;
142
+ const cwd = yield* Cwd;
143
+ const currentDir = yield* cwd.get;
144
+ const pnpmWorkspace = yield* fs.exists(path.join(currentDir, "pnpm-workspace.yaml"));
100
145
  if (pnpmWorkspace) {
101
- return ok(true);
146
+ return true;
102
147
  }
103
148
  const packageJson = yield* readPackageJson();
104
- return ok(packageJson?.workspaces !== undefined);
149
+ return packageJson?.workspaces !== undefined;
150
+ });
151
+ var ensureDirectory = (path) => Effect2.gen(function* () {
152
+ const fs = yield* FileSystem.FileSystem;
153
+ yield* fs.makeDirectory(path, { recursive: true }).pipe(Effect2.mapError((cause) => new FailedToCreateDirectory({ cause, path })));
105
154
  });
106
- function printTitle() {
155
+ var printTitle = () => Effect2.gen(function* () {
156
+ const terminal = yield* Terminal.Terminal;
157
+ const terminalColumns = yield* terminal.columns;
107
158
  const title = `
108
159
  .o8 . o8o .
109
160
  "888 .o8 \`"' .o8
@@ -111,127 +162,202 @@ function printTitle() {
111
162
  \`P )88b d88' \`888 \`P )88b \`888P"Y88bP"Y88b \`P )88b \`888P"Y88b 888 \`888 888 d88' \`88b
112
163
  .oP"888 888 888 .oP"888 888 888 888 .oP"888 888 888 888 888 888 888ooo888
113
164
  d8( 888 888 888 d8( 888 888 888 888 d8( 888 888 888 888 . 888 888 . 888 .o
114
- \`Y888""8o \`Y8bod88P" \`Y888""8o o888o o888o o888o \`Y888""8o o888o o888o "888" o888o "888" \`Y8bod8P'
115
- `;
165
+ \`Y888""8o \`Y8bod88P" \`Y888""8o o888o o888o o888o \`Y888""8o o888o o888o "888" o888o "888" \`Y8bod8P'
166
+ `;
116
167
  const columns = title.split(`
117
168
  `).reduce((max, line) => Math.max(max, line.trim().length), 0);
118
- if (process2.stdout.columns && process2.stdout.columns >= columns) {
119
- console.info(title);
169
+ if (!terminalColumns || terminalColumns < columns) {
170
+ return;
120
171
  }
121
- }
172
+ yield* Console.info(title);
173
+ });
174
+ var getPackageVersion = () => readPackageJson().pipe(Effect2.flatMap((packageJson) => packageJson.version ? Effect2.succeed(packageJson.version) : Effect2.fail(new MissingPackageVersion({ path: "package.json" }))));
122
175
 
123
176
  // src/helpers/packages/knip.ts
177
+ var CONFIG_FILE_JSON = "knip.json";
178
+ var CONFIG_FILE_JSONC = "knip.jsonc";
124
179
  var knip = {
125
180
  config: knip_default,
126
- create: () => fromPromise2(writeFile(join2(process.cwd(), "knip.json"), JSON.stringify(knip.config, null, 2)), (error) => Fault2.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write knip configuration", "We're unable to write the knip configuration to the current directory.")),
127
- exists: async () => {
128
- if (await checkIfExists(join2(process.cwd(), "knip.json"))) {
129
- return { path: join2(process.cwd(), "knip.json") };
181
+ create: () => Effect3.gen(function* () {
182
+ const fs = yield* FileSystem2.FileSystem;
183
+ const path = yield* Path2.Path;
184
+ const configPath = path.join(process.cwd(), CONFIG_FILE_JSON);
185
+ const payload = JSON.stringify(knip.config, null, 2);
186
+ yield* fs.writeFileString(configPath, `${payload}
187
+ `).pipe(Effect3.mapError((cause) => new FailedToWriteFile({ cause, path: configPath })));
188
+ }),
189
+ exists: () => Effect3.gen(function* () {
190
+ const fs = yield* FileSystem2.FileSystem;
191
+ const path = yield* Path2.Path;
192
+ const jsonPath = path.join(process.cwd(), CONFIG_FILE_JSON);
193
+ const jsoncPath = path.join(process.cwd(), CONFIG_FILE_JSONC);
194
+ if (yield* fs.exists(jsonPath)) {
195
+ return { path: jsonPath };
130
196
  }
131
- if (await checkIfExists(join2(process.cwd(), "knip.jsonc"))) {
132
- return { path: join2(process.cwd(), "knip.jsonc") };
197
+ if (yield* fs.exists(jsoncPath)) {
198
+ return { path: jsoncPath };
133
199
  }
134
200
  return { path: null };
135
- },
201
+ }),
136
202
  name: "knip",
137
- update: () => safeTry2(async function* () {
138
- const exists = await knip.exists();
139
- if (!exists.path) {
140
- return err2(Fault2.create("FILE_NOT_FOUND").withDescription("No `knip.json` or `knip.jsonc` found", "We're unable to find a knip configuration in the current directory."));
141
- }
142
- const knipFile = yield* fromPromise2(readFile2(exists.path, "utf8"), (error) => Fault2.wrap(error).withTag("FAILED_TO_READ_FILE").withDescription("Failed to read knip configuration", "We're unable to read the knip configuration from the current directory."));
143
- const existingConfig = yield* parseJson(knipFile);
203
+ update: () => Effect3.gen(function* () {
204
+ const fs = yield* FileSystem2.FileSystem;
205
+ const { path: configPath } = yield* knip.exists();
206
+ if (!configPath) {
207
+ return yield* Effect3.fail(new FileNotFound({ path: CONFIG_FILE_JSON }));
208
+ }
209
+ const knipFile = yield* fs.readFileString(configPath).pipe(Effect3.mapError((cause) => new FailedToReadFile({ cause, path: configPath })));
210
+ const existingConfig = yield* parseJson(knipFile, configPath);
144
211
  if (!isJsonObject(existingConfig)) {
145
- return err2(Fault2.create("INVALID_CONFIG_FORMAT").withDescription("Invalid knip configuration format", "The knip configuration must be a JSON object."));
212
+ return yield* Effect3.fail(new InvalidConfigFormat({ path: configPath }));
146
213
  }
147
214
  const mergedConfig = yield* mergeConfig(existingConfig, knip.config);
148
- const isJsonc = exists.path.endsWith(".jsonc");
215
+ const isJsonc = configPath.endsWith(".jsonc");
149
216
  mergedConfig.$schema = isJsonc ? "https://unpkg.com/knip@5/schema-jsonc.json" : "https://unpkg.com/knip@5/schema.json";
150
- yield* fromPromise2(writeFile(exists.path, JSON.stringify(mergedConfig, null, 2)), (error) => Fault2.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write knip configuration", "We're unable to write the knip configuration to the current directory.").withContext({ path: exists.path }));
151
- return ok2();
217
+ yield* fs.writeFileString(configPath, `${JSON.stringify(mergedConfig, null, 2)}
218
+ `).pipe(Effect3.mapError((cause) => new FailedToWriteFile({ cause, path: configPath })));
152
219
  }),
153
220
  version: "5.80.1"
154
221
  };
155
222
 
156
- // src/commands/analyze.ts
157
- var analyze_default = defineCommand({
158
- builder: (yargs) => yargs.positional("files", {
159
- array: true,
160
- describe: "Specific files to analyze (optional)",
161
- type: "string"
162
- }).option("fix", {
163
- description: "Automatically fix issues",
164
- type: "boolean"
165
- }).option("strict", {
166
- description: "Enable strict mode",
167
- type: "boolean"
223
+ // src/services/package-manager.ts
224
+ import process4 from "node:process";
225
+ import { Context as Context3, Effect as Effect5, Layer as Layer3 } from "effect";
226
+ import { detectPackageManager } from "nypm";
227
+
228
+ // src/services/prompter.ts
229
+ import * as p from "@clack/prompts";
230
+ import { Context as Context2, Effect as Effect4, Layer as Layer2 } from "effect";
231
+
232
+ class Prompter extends Context2.Tag("Prompter")() {
233
+ }
234
+ var PrompterLive = Layer2.succeed(Prompter, {
235
+ cancel: (message) => Effect4.sync(() => {
236
+ p.cancel(message);
168
237
  }),
169
- command: "analyze [files..]",
170
- describe: "Find unused dependencies, exports, and files using knip",
171
- handler: (argv) => safeTry3(async function* () {
172
- const packageManager = yield* getPackageManagerName();
173
- const args = [];
174
- if (argv.fix) {
175
- args.push("--fix", "--allow-remove-files");
176
- }
177
- if (argv.strict) {
178
- args.push("--production", "--strict");
179
- }
180
- if (argv.files && argv.files.length > 0) {
181
- args.push(...argv.files);
182
- }
183
- const command = dlxCommand(packageManager, knip.name, { args });
184
- yield* runCommand(command);
185
- return ok3();
186
- }).match(() => {
187
- process3.exit(0);
188
- }, (error) => {
189
- if (Fault3.isFault(error) && error.tag === "NO_PACKAGE_MANAGER") {
190
- log.error(error.flatten());
191
- }
192
- process3.exit(1);
193
- })
238
+ confirm: (options) => Effect4.tryPromise(() => p.confirm(options)).pipe(Effect4.orDie),
239
+ intro: (message) => Effect4.sync(() => {
240
+ p.intro(message);
241
+ }),
242
+ log: {
243
+ error: (message) => Effect4.sync(() => {
244
+ p.log.error(message);
245
+ }),
246
+ info: (message) => Effect4.sync(() => {
247
+ p.log.info(message);
248
+ }),
249
+ success: (message) => Effect4.sync(() => {
250
+ p.log.success(message);
251
+ }),
252
+ warning: (message) => Effect4.sync(() => {
253
+ p.log.warning(message);
254
+ })
255
+ },
256
+ multiselect: (options) => Effect4.tryPromise(() => p.multiselect(options)).pipe(Effect4.orDie),
257
+ outro: (message) => Effect4.sync(() => {
258
+ p.outro(message);
259
+ }),
260
+ spinner: () => p.spinner()
194
261
  });
195
262
 
263
+ // src/services/package-manager.ts
264
+ class PackageManager extends Context3.Tag("PackageManager")() {
265
+ }
266
+ var PackageManagerLive = Layer3.effect(PackageManager, Effect5.gen(function* () {
267
+ const prompter = yield* Prompter;
268
+ const result = yield* Effect5.tryPromise({
269
+ catch: (cause) => new NoPackageManager({ cause }),
270
+ try: () => detectPackageManager(process4.cwd())
271
+ });
272
+ if (!result?.name) {
273
+ return yield* Effect5.fail(new NoPackageManager({}));
274
+ }
275
+ if (result.warnings && result.warnings.length > 0) {
276
+ for (const warning of result.warnings) {
277
+ yield* prompter.log.warning(warning);
278
+ }
279
+ }
280
+ const command = (() => {
281
+ switch (result.name) {
282
+ case "bun":
283
+ return ["bunx"];
284
+ case "pnpm":
285
+ return ["pnpm", "dlx"];
286
+ case "yarn":
287
+ return ["yarn", "dlx"];
288
+ case "npm":
289
+ return ["npx"];
290
+ case "deno":
291
+ return ["deno", "run", "-A"];
292
+ default:
293
+ return ["npx"];
294
+ }
295
+ })();
296
+ return {
297
+ command,
298
+ name: result.name
299
+ };
300
+ })).pipe(Layer3.provide(PrompterLive));
301
+
302
+ // src/commands/analyze.ts
303
+ var fix = Options.boolean("fix").pipe(Options.withDescription("Automatically fix issues"));
304
+ var strict = Options.boolean("strict").pipe(Options.withDescription("Enable strict mode"));
305
+ var analyze_default = Command.make("analyze", { fix, strict }).pipe(Command.withDescription("Find unused dependencies, exports, and files using knip"), Command.withHandler(({ fix: fix2, strict: strict2 }) => Effect6.gen(function* () {
306
+ const pm = yield* PackageManager;
307
+ const [command, ...commandArgs] = pm.command;
308
+ const args = [];
309
+ if (fix2) {
310
+ args.push("--fix", "--allow-remove-files");
311
+ }
312
+ if (strict2) {
313
+ args.push("--production", "--strict");
314
+ }
315
+ return yield* ShellCommand2.make(command, ...commandArgs, knip.name, ...args).pipe(ShellCommand2.stdout("inherit"), ShellCommand2.stderr("inherit"), ShellCommand2.exitCode);
316
+ })));
317
+
196
318
  // src/commands/check.ts
197
- import process4 from "node:process";
198
- import { log as log2 } from "@clack/prompts";
199
- import { Fault as Fault5 } from "faultier";
200
- import { ok as ok5, safeTry as safeTry5 } from "neverthrow";
201
- import { dlxCommand as dlxCommand2 } from "nypm";
319
+ import { Args, Command as Command2 } from "@effect/cli";
320
+ import { Command as ShellCommand3 } from "@effect/platform";
321
+ import { Effect as Effect8, Option } from "effect";
202
322
 
203
323
  // src/helpers/packages/oxlint.ts
204
- import { readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
205
- import { join as join3 } from "node:path";
206
- import { Fault as Fault4 } from "faultier";
207
- import { err as err3, fromPromise as fromPromise3, ok as ok4, safeTry as safeTry4 } from "neverthrow";
324
+ import { FileSystem as FileSystem3, Path as Path3 } from "@effect/platform";
325
+ import { Effect as Effect7 } from "effect";
326
+ var CONFIG_FILE = ".oxlintrc.json";
208
327
  var oxlint = {
209
328
  config: {
210
329
  $schema: "./node_modules/oxlint/configuration_schema.json"
211
330
  },
212
- create: (presets = []) => {
331
+ create: (presets = []) => Effect7.gen(function* () {
332
+ const fs = yield* FileSystem3.FileSystem;
333
+ const path = yield* Path3.Path;
213
334
  const extendsArray = ["./node_modules/adamantite/presets/lint/core.json"];
214
335
  for (const preset of presets) {
215
336
  extendsArray.push(`./node_modules/adamantite/presets/lint/${preset}.json`);
216
337
  }
217
- return fromPromise3(writeFile2(join3(process.cwd(), ".oxlintrc.json"), JSON.stringify({ ...oxlint.config, extends: extendsArray }, null, 2)), (error) => Fault4.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write oxlint configuration", "We're unable to write the oxlint configuration to the current directory."));
218
- },
219
- exists: async () => {
220
- if (await checkIfExists(join3(process.cwd(), ".oxlintrc.json"))) {
221
- return { path: join3(process.cwd(), ".oxlintrc.json") };
222
- }
223
- return { path: null };
224
- },
338
+ const configPath = path.join(process.cwd(), CONFIG_FILE);
339
+ const payload = JSON.stringify({ ...oxlint.config, extends: extendsArray }, null, 2);
340
+ yield* fs.writeFileString(configPath, `${payload}
341
+ `).pipe(Effect7.mapError((cause) => new FailedToWriteFile({ cause, path: configPath })));
342
+ }),
343
+ exists: () => Effect7.gen(function* () {
344
+ const fs = yield* FileSystem3.FileSystem;
345
+ const path = yield* Path3.Path;
346
+ const configPath = path.join(process.cwd(), CONFIG_FILE);
347
+ const exists = yield* fs.exists(configPath);
348
+ return { path: exists ? configPath : null };
349
+ }),
225
350
  name: "oxlint",
226
- update: (presets = []) => safeTry4(async function* () {
227
- const exists = await oxlint.exists();
228
- if (!exists.path) {
229
- return err3(Fault4.create("FILE_NOT_FOUND").withDescription("No `.oxlintrc.json` found", "We're unable to find an oxlint configuration in the current directory."));
230
- }
231
- const oxlintFile = yield* fromPromise3(readFile3(exists.path, "utf8"), (error) => Fault4.wrap(error).withTag("FAILED_TO_READ_FILE").withDescription("Failed to read oxlint configuration", "We're unable to read the oxlint configuration from the current directory."));
232
- const existingConfig = yield* parseJson(oxlintFile);
351
+ update: (presets = []) => Effect7.gen(function* () {
352
+ const fs = yield* FileSystem3.FileSystem;
353
+ const { path: configPath } = yield* oxlint.exists();
354
+ if (!configPath) {
355
+ return yield* Effect7.fail(new FileNotFound({ path: CONFIG_FILE }));
356
+ }
357
+ const oxlintFile = yield* fs.readFileString(configPath).pipe(Effect7.mapError((cause) => new FailedToReadFile({ cause, path: configPath })));
358
+ const existingConfig = yield* parseJson(oxlintFile, configPath);
233
359
  if (!isJsonObject(existingConfig)) {
234
- return err3(Fault4.create("INVALID_CONFIG_FORMAT").withDescription("Invalid oxlint configuration format", "The oxlint configuration must be a JSON object."));
360
+ return yield* Effect7.fail(new InvalidConfigFormat({ path: configPath }));
235
361
  }
236
362
  const newConfig = { ...existingConfig };
237
363
  const extendsArray = Array.isArray(newConfig.extends) ? newConfig.extends : typeof newConfig.extends === "string" ? [newConfig.extends] : [];
@@ -248,8 +374,8 @@ var oxlint = {
248
374
  newConfig.extends = extendsArray;
249
375
  const mergedConfig = yield* mergeConfig(newConfig, oxlint.config);
250
376
  mergedConfig.$schema = oxlint.config.$schema;
251
- yield* fromPromise3(writeFile2(exists.path, JSON.stringify(mergedConfig, null, 2)), (error) => Fault4.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write oxlint configuration", "We're unable to write the oxlint configuration to the current directory.").withContext({ path: exists.path }));
252
- return ok4();
377
+ yield* fs.writeFileString(configPath, `${JSON.stringify(mergedConfig, null, 2)}
378
+ `).pipe(Effect7.mapError((cause) => new FailedToWriteFile({ cause, path: configPath })));
253
379
  }),
254
380
  version: "1.38.0"
255
381
  };
@@ -259,102 +385,51 @@ var tsgolint = {
259
385
  };
260
386
 
261
387
  // src/commands/check.ts
262
- var check_default = defineCommand({
263
- builder: (yargs) => yargs.positional("files", {
264
- array: true,
265
- describe: "Specific files to lint (optional)",
266
- type: "string"
267
- }),
268
- command: "check [files..]",
269
- describe: "Find issues in code using oxlint",
270
- handler: (argv) => safeTry5(async function* () {
271
- const packageManager = yield* getPackageManagerName();
272
- const args = ["--type-aware"];
273
- if (argv.files && argv.files.length > 0) {
274
- args.push(...argv.files);
275
- }
276
- const command = dlxCommand2(packageManager, oxlint.name, { args });
277
- const result = yield* runCommand(command);
278
- return ok5(result);
279
- }).match(() => {
280
- process4.exit(0);
281
- }, (error) => {
282
- if (Fault5.isFault(error) && error.tag === "NO_PACKAGE_MANAGER") {
283
- log2.error(error.flatten());
284
- }
285
- process4.exit(1);
286
- })
287
- });
388
+ var files = Args.file({ exists: "yes" }).pipe(Args.withDescription("Specific files to lint (optional)"), Args.repeated, Args.optional);
389
+ var check_default = Command2.make("check", { files }).pipe(Command2.withDescription("Find issues in code using oxlint"), Command2.withHandler(({ files: files2 }) => Effect8.gen(function* () {
390
+ const pm = yield* PackageManager;
391
+ const [command, ...commandArgs] = pm.command;
392
+ const args = ["--type-aware"];
393
+ if (Option.isSome(files2)) {
394
+ args.push(...files2.value);
395
+ }
396
+ return yield* ShellCommand3.make(command, ...commandArgs, oxlint.name, ...args).pipe(ShellCommand3.stdout("inherit"), ShellCommand3.stderr("inherit"), ShellCommand3.exitCode);
397
+ })));
288
398
 
289
399
  // src/commands/fix.ts
290
- import process5 from "node:process";
291
- import { log as log3 } from "@clack/prompts";
292
- import { Fault as Fault6 } from "faultier";
293
- import { ok as ok6, safeTry as safeTry6 } from "neverthrow";
294
- import { dlxCommand as dlxCommand3 } from "nypm";
295
- var fix_default = defineCommand({
296
- builder: (yargs) => yargs.positional("files", {
297
- array: true,
298
- describe: "Specific files to fix (optional)",
299
- type: "string"
300
- }).option("suggested", {
301
- default: false,
302
- description: "Apply suggested fixes",
303
- type: "boolean"
304
- }).option("dangerous", {
305
- default: false,
306
- description: "Apply dangerous fixes",
307
- type: "boolean"
308
- }).option("all", {
309
- default: false,
310
- description: "Apply all fixes, including suggested and dangerous fixes",
311
- type: "boolean"
312
- }),
313
- command: "fix [files..]",
314
- describe: "Fix issues in code using oxlint",
315
- handler: (argv) => safeTry6(async function* () {
316
- const packageManager = yield* getPackageManagerName();
317
- const args = new Set(["--type-aware", "--fix"]);
318
- if (argv.suggested) {
319
- args.add("--fix-suggestions");
320
- }
321
- if (argv.dangerous) {
322
- args.add("--fix-dangerously");
323
- }
324
- if (argv.all) {
325
- args.add("--fix-suggestions");
326
- args.add("--fix-dangerously");
327
- }
328
- if (argv.files && argv.files.length > 0) {
329
- for (const file of argv.files) {
330
- args.add(file);
331
- }
332
- }
333
- const command = dlxCommand3(packageManager, oxlint.name, { args: Array.from(args) });
334
- yield* runCommand(command);
335
- return ok6();
336
- }).match(() => {
337
- process5.exit(0);
338
- }, (error) => {
339
- if (Fault6.isFault(error) && error.tag === "NO_PACKAGE_MANAGER") {
340
- log3.error(error.flatten());
400
+ import { Args as Args2, Command as Command3, Options as Options2 } from "@effect/cli";
401
+ import { Command as ShellCommand4 } from "@effect/platform";
402
+ import { Effect as Effect9, Option as Option2 } from "effect";
403
+ var files2 = Args2.file({ exists: "yes" }).pipe(Args2.withDescription("Specific files to fix (optional)"), Args2.repeated, Args2.optional);
404
+ var suggested = Options2.boolean("suggested").pipe(Options2.withDescription("Apply suggested fixes"));
405
+ var dangerous = Options2.boolean("dangerous").pipe(Options2.withDescription("Apply dangerous fixes"));
406
+ var all = Options2.boolean("all").pipe(Options2.withDescription("Apply all fixes, including suggested and dangerous fixes"));
407
+ var fix_default = Command3.make("fix", { all, dangerous, files: files2, suggested }).pipe(Command3.withDescription("Fix issues in code using oxlint"), Command3.withHandler(({ all: all2, dangerous: dangerous2, files: files3, suggested: suggested2 }) => Effect9.gen(function* () {
408
+ const pm = yield* PackageManager;
409
+ const [command, ...commandArgs] = pm.command;
410
+ const args = new Set(["--type-aware", "--fix"]);
411
+ if (suggested2 || all2) {
412
+ args.add("--fix-suggestions");
413
+ }
414
+ if (dangerous2 || all2) {
415
+ args.add("--fix-dangerously");
416
+ }
417
+ if (Option2.isSome(files3)) {
418
+ for (const file of files3.value) {
419
+ args.add(file);
341
420
  }
342
- process5.exit(1);
343
- })
344
- });
421
+ }
422
+ return yield* ShellCommand4.make(command, ...commandArgs, oxlint.name, ...args).pipe(ShellCommand4.stdout("inherit"), ShellCommand4.stderr("inherit"), ShellCommand4.exitCode);
423
+ })));
345
424
 
346
425
  // src/commands/format.ts
347
- import process6 from "node:process";
348
- import { log as log4 } from "@clack/prompts";
349
- import { Fault as Fault8 } from "faultier";
350
- import { ok as ok8, safeTry as safeTry8 } from "neverthrow";
351
- import { dlxCommand as dlxCommand4 } from "nypm";
426
+ import { Args as Args3, Command as Command4, Options as Options3 } from "@effect/cli";
427
+ import { Command as ShellCommand5 } from "@effect/platform";
428
+ import { Effect as Effect11, Option as Option3 } from "effect";
352
429
 
353
430
  // src/helpers/packages/oxfmt.ts
354
- import { readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
355
- import { join as join4 } from "node:path";
356
- import { Fault as Fault7 } from "faultier";
357
- import { err as err4, fromPromise as fromPromise4, ok as ok7, safeTry as safeTry7 } from "neverthrow";
431
+ import { FileSystem as FileSystem4, Path as Path4 } from "@effect/platform";
432
+ import { Effect as Effect10 } from "effect";
358
433
  // presets/format.json
359
434
  var format_default = {
360
435
  $schema: "../node_modules/oxfmt/configuration_schema.json",
@@ -402,89 +477,80 @@ var format_default = {
402
477
  };
403
478
 
404
479
  // src/helpers/packages/oxfmt.ts
480
+ var CONFIG_FILE_JSONC2 = ".oxfmtrc.jsonc";
481
+ var CONFIG_FILE_JSON2 = ".oxfmtrc.json";
405
482
  var oxfmt = {
406
483
  config: {
407
484
  ...format_default,
408
485
  $schema: "./node_modules/oxfmt/configuration_schema.json"
409
486
  },
410
- create: () => fromPromise4(writeFile3(join4(process.cwd(), ".oxfmtrc.jsonc"), JSON.stringify(oxfmt.config, null, 2)), (error) => Fault7.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write oxfmt configuration", "We're unable to write the oxfmt configuration to the current directory.")),
411
- exists: async () => {
412
- if (await checkIfExists(join4(process.cwd(), ".oxfmtrc.jsonc"))) {
413
- return { path: join4(process.cwd(), ".oxfmtrc.jsonc") };
487
+ create: () => Effect10.gen(function* () {
488
+ const fs = yield* FileSystem4.FileSystem;
489
+ const path = yield* Path4.Path;
490
+ const configPath = path.join(process.cwd(), CONFIG_FILE_JSONC2);
491
+ const payload = JSON.stringify(oxfmt.config, null, 2);
492
+ yield* fs.writeFileString(configPath, `${payload}
493
+ `).pipe(Effect10.mapError((cause) => new FailedToWriteFile({ cause, path: configPath })));
494
+ }),
495
+ exists: () => Effect10.gen(function* () {
496
+ const fs = yield* FileSystem4.FileSystem;
497
+ const path = yield* Path4.Path;
498
+ const jsoncPath = path.join(process.cwd(), CONFIG_FILE_JSONC2);
499
+ const jsonPath = path.join(process.cwd(), CONFIG_FILE_JSON2);
500
+ if (yield* fs.exists(jsoncPath)) {
501
+ return { path: jsoncPath };
414
502
  }
415
- if (await checkIfExists(join4(process.cwd(), ".oxfmtrc.json"))) {
416
- return { path: join4(process.cwd(), ".oxfmtrc.json") };
503
+ if (yield* fs.exists(jsonPath)) {
504
+ return { path: jsonPath };
417
505
  }
418
506
  return { path: null };
419
- },
507
+ }),
420
508
  name: "oxfmt",
421
- update: () => safeTry7(async function* () {
422
- const exists = await oxfmt.exists();
423
- if (!exists.path) {
424
- return err4(Fault7.create("FILE_NOT_FOUND").withDescription("No `.oxfmtrc.jsonc` or `.oxfmtrc.json` found", "We're unable to find an oxfmt configuration in the current directory."));
425
- }
426
- const oxfmtFile = yield* fromPromise4(readFile4(exists.path, "utf8"), (error) => Fault7.wrap(error).withTag("FAILED_TO_READ_FILE").withDescription("Failed to read oxfmt configuration", "We're unable to read the oxfmt configuration from the current directory."));
427
- const existingConfig = yield* parseJson(oxfmtFile);
509
+ update: () => Effect10.gen(function* () {
510
+ const fs = yield* FileSystem4.FileSystem;
511
+ const { path: configPath } = yield* oxfmt.exists();
512
+ if (!configPath) {
513
+ return yield* Effect10.fail(new FileNotFound({ path: CONFIG_FILE_JSONC2 }));
514
+ }
515
+ const oxfmtFile = yield* fs.readFileString(configPath).pipe(Effect10.mapError((cause) => new FailedToReadFile({ cause, path: configPath })));
516
+ const existingConfig = yield* parseJson(oxfmtFile, configPath);
428
517
  if (!isJsonObject(existingConfig)) {
429
- return err4(Fault7.create("INVALID_CONFIG_FORMAT").withDescription("Invalid oxfmt configuration format", "The oxfmt configuration must be a JSON object."));
518
+ return yield* Effect10.fail(new InvalidConfigFormat({ path: configPath }));
430
519
  }
431
520
  const mergedConfig = yield* mergeConfig(existingConfig, oxfmt.config);
432
521
  mergedConfig.$schema = oxfmt.config.$schema;
433
- yield* fromPromise4(writeFile3(exists.path, JSON.stringify(mergedConfig, null, 2)), (error) => Fault7.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write oxfmt configuration", "We're unable to write the oxfmt configuration to the current directory.").withContext({ path: exists.path }));
434
- return ok7();
522
+ yield* fs.writeFileString(configPath, `${JSON.stringify(mergedConfig, null, 2)}
523
+ `).pipe(Effect10.mapError((cause) => new FailedToWriteFile({ cause, path: configPath })));
435
524
  }),
436
525
  version: "0.23.0"
437
526
  };
438
527
 
439
528
  // src/commands/format.ts
440
- var format_default2 = defineCommand({
441
- builder: (yargs) => yargs.positional("files", {
442
- array: true,
443
- describe: "Specific files to format (optional)",
444
- type: "string"
445
- }).option("check", {
446
- description: "Check if files are formatted without writing",
447
- type: "boolean"
448
- }),
449
- command: "format [files..]",
450
- describe: "Format files using oxfmt",
451
- handler: (argv) => safeTry8(async function* () {
452
- const packageManager = yield* getPackageManagerName();
453
- const args = [];
454
- if (argv.check) {
455
- args.push("--check");
456
- }
457
- if (argv.files && argv.files.length > 0) {
458
- args.push(...argv.files);
459
- }
460
- const command = dlxCommand4(packageManager, oxfmt.name, { args });
461
- const result = yield* runCommand(command);
462
- return ok8(result);
463
- }).match(() => {
464
- process6.exit(0);
465
- }, (error) => {
466
- if (Fault8.isFault(error) && error.tag === "NO_PACKAGE_MANAGER") {
467
- log4.error(error.flatten());
468
- }
469
- process6.exit(1);
470
- })
471
- });
529
+ var files3 = Args3.file({ exists: "yes" }).pipe(Args3.withDescription("Specific files to format (optional)"), Args3.repeated, Args3.optional);
530
+ var check = Options3.boolean("check").pipe(Options3.withDescription("Check if files are formatted without writing"));
531
+ var format_default2 = Command4.make("format", { check, files: files3 }).pipe(Command4.withDescription("Format files using oxfmt"), Command4.withHandler(({ check: check2, files: files4 }) => Effect11.gen(function* () {
532
+ const pm = yield* PackageManager;
533
+ const [command, ...commandArgs] = pm.command;
534
+ const args = [];
535
+ if (check2) {
536
+ args.push("--check");
537
+ }
538
+ if (Option3.isSome(files4)) {
539
+ args.push(...files4.value);
540
+ }
541
+ return yield* ShellCommand5.make(command, ...commandArgs, oxfmt.name, ...args).pipe(ShellCommand5.stdout("inherit"), ShellCommand5.stderr("inherit"), ShellCommand5.exitCode);
542
+ })));
472
543
 
473
544
  // src/commands/init.ts
474
- import { writeFile as writeFile7 } from "node:fs/promises";
475
- import { join as join8 } from "node:path";
476
- import process8 from "node:process";
477
- import * as p from "@clack/prompts";
478
- import { Fault as Fault12 } from "faultier";
479
- import { err as err7, fromPromise as fromPromise8, fromSafePromise, ok as ok12, safeTry as safeTry12 } from "neverthrow";
545
+ import { isCancel } from "@clack/prompts";
546
+ import { Command as Command5 } from "@effect/cli";
547
+ import { FileSystem as FileSystem8, Path as Path8 } from "@effect/platform";
548
+ import { Effect as Effect15 } from "effect";
480
549
  import { addDevDependency } from "nypm";
481
550
 
482
551
  // src/helpers/ci/github.ts
483
- import { mkdir, writeFile as writeFile4 } from "node:fs/promises";
484
- import { join as join5 } from "node:path";
485
- import process7 from "node:process";
486
- import { Fault as Fault9 } from "faultier";
487
- import { fromPromise as fromPromise5, ok as ok9, safeTry as safeTry9 } from "neverthrow";
552
+ import { FileSystem as FileSystem5, Path as Path5 } from "@effect/platform";
553
+ import { Effect as Effect12 } from "effect";
488
554
  import { runScriptCommand } from "nypm";
489
555
  var setupSteps = {
490
556
  bun: ` - name: Setup Bun
@@ -621,36 +687,42 @@ var CI_COMPATIBLE_SCRIPTS = new Set([
621
687
  ]);
622
688
  var hasCICompatibleScripts = (scripts) => scripts.some((script) => CI_COMPATIBLE_SCRIPTS.has(script));
623
689
  var github = {
624
- create: (options) => safeTry9(async function* () {
625
- const workflowDir = join5(process7.cwd(), ".github", "workflows");
626
- yield* fromPromise5(mkdir(workflowDir, { recursive: true }), (error) => Fault9.wrap(error).withTag("FAILED_TO_CREATE_DIRECTORY").withDescription("Failed to create .github/workflows directory", "We're unable to create the .github/workflows directory in the current directory.").withContext({ path: workflowDir }));
690
+ create: (options) => Effect12.gen(function* () {
691
+ const fs = yield* FileSystem5.FileSystem;
692
+ const path = yield* Path5.Path;
693
+ const workflowDir = path.join(process.cwd(), ".github", "workflows");
694
+ yield* ensureDirectory(workflowDir);
627
695
  const workflowContent = generateWorkflow(options);
628
696
  if (!workflowContent) {
629
- return ok9();
697
+ return;
630
698
  }
631
- yield* fromPromise5(writeFile4(join5(workflowDir, "adamantite.yml"), workflowContent), (error) => Fault9.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write GitHub Actions workflow", "We're unable to write the GitHub Actions workflow file.").withContext({ path: join5(workflowDir, "adamantite.yml") }));
632
- return ok9();
699
+ const workflowPath = path.join(workflowDir, "adamantite.yml");
700
+ yield* fs.writeFileString(workflowPath, workflowContent).pipe(Effect12.mapError((cause) => new FailedToWriteFile({ cause, path: workflowPath })));
701
+ }),
702
+ exists: () => Effect12.gen(function* () {
703
+ const fs = yield* FileSystem5.FileSystem;
704
+ const path = yield* Path5.Path;
705
+ return yield* fs.exists(path.join(process.cwd(), ".github", "workflows", "adamantite.yml"));
633
706
  }),
634
- exists: () => checkIfExists(join5(process7.cwd(), ".github", "workflows", "adamantite.yml")),
635
- update: (options) => safeTry9(async function* () {
636
- const workflowPath = join5(process7.cwd(), ".github", "workflows", "adamantite.yml");
707
+ update: (options) => Effect12.gen(function* () {
708
+ const fs = yield* FileSystem5.FileSystem;
709
+ const path = yield* Path5.Path;
710
+ const workflowPath = path.join(process.cwd(), ".github", "workflows", "adamantite.yml");
637
711
  const workflowContent = generateWorkflow(options);
638
712
  if (!workflowContent) {
639
- return ok9();
713
+ return;
640
714
  }
641
- yield* fromPromise5(writeFile4(workflowPath, workflowContent), (error) => Fault9.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write GitHub Actions workflow", "We're unable to update the GitHub Actions workflow file.").withContext({ path: workflowPath }));
642
- return ok9();
715
+ yield* fs.writeFileString(workflowPath, workflowContent).pipe(Effect12.mapError((cause) => new FailedToWriteFile({ cause, path: workflowPath })));
643
716
  }),
644
717
  workflowPath: ".github/workflows/adamantite.yml"
645
718
  };
646
719
 
647
720
  // src/helpers/editors/vscode.ts
648
- import { mkdir as mkdir2, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
649
- import { join as join6 } from "node:path";
650
- import { Fault as Fault10 } from "faultier";
651
- import { err as err5, fromPromise as fromPromise6, ok as ok10, safeTry as safeTry10 } from "neverthrow";
721
+ import { FileSystem as FileSystem6, Path as Path6, Command as ShellCommand6 } from "@effect/platform";
722
+ import { Effect as Effect13 } from "effect";
723
+ var SETTINGS_FILE = "settings.json";
652
724
  var vscode = {
653
- cliExists: () => checkCliExists("code").mapErr((error) => Fault10.wrap(error).withTag("VSCODE_CLI_NOT_FOUND").withDescription("VS Code CLI not found", "The 'code' CLI command is not available. Please install the VS Code command-line tools by opening VS Code and running 'Shell Command: Install code command in PATH' from the command palette (Cmd+Shift+P).")),
725
+ cliExists: () => checkCliExists("code").pipe(Effect13.mapError((cause) => new VscodeCliNotFound({ cause }))),
654
726
  config: {
655
727
  "[css]": {
656
728
  "editor.defaultFormatter": "oxc.oxc-vscode"
@@ -685,36 +757,46 @@ var vscode = {
685
757
  "oxc.typeAware": true,
686
758
  "typescript.tsdk": "node_modules/typescript/lib"
687
759
  },
688
- create: () => safeTry10(async function* () {
689
- const vscodePath = join6(process.cwd(), ".vscode");
690
- yield* fromPromise6(mkdir2(vscodePath, { recursive: true }), (error) => Fault10.wrap(error).withTag("FAILED_TO_CREATE_DIRECTORY").withDescription("Failed to create .vscode directory", "We're unable to create the .vscode directory in the current directory.").withContext({ path: vscodePath }));
691
- yield* fromPromise6(writeFile5(join6(vscodePath, "settings.json"), JSON.stringify(vscode.config, null, 2)), (error) => Fault10.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write .vscode/settings.json", "We're unable to write the .vscode/settings.json file in the current directory."));
692
- return ok10();
760
+ create: () => Effect13.gen(function* () {
761
+ const fs = yield* FileSystem6.FileSystem;
762
+ const path = yield* Path6.Path;
763
+ const vscodePath = path.join(process.cwd(), ".vscode");
764
+ const settingsPath = path.join(vscodePath, SETTINGS_FILE);
765
+ yield* fs.makeDirectory(vscodePath, { recursive: true }).pipe(Effect13.mapError((cause) => new FailedToCreateDirectory({ cause, path: vscodePath })));
766
+ yield* fs.writeFileString(settingsPath, `${JSON.stringify(vscode.config, null, 2)}
767
+ `).pipe(Effect13.mapError((cause) => new FailedToWriteFile({ cause, path: settingsPath })));
768
+ }),
769
+ exists: () => Effect13.gen(function* () {
770
+ const fs = yield* FileSystem6.FileSystem;
771
+ const path = yield* Path6.Path;
772
+ return yield* fs.exists(path.join(process.cwd(), ".vscode", SETTINGS_FILE));
693
773
  }),
694
- exists: () => checkIfExists(join6(process.cwd(), ".vscode", "settings.json")),
695
- extension: (scripts = []) => safeTry10(function* () {
774
+ extension: (scripts = []) => Effect13.gen(function* () {
696
775
  yield* vscode.cliExists();
697
- if (scripts.includes("check") || scripts.includes("fix") || scripts.includes("format")) {
698
- yield* runCommand("code --install-extension oxc.oxc-vscode").mapErr((error) => Fault10.wrap(error).withTag("FAILED_TO_INSTALL_EXTENSION").withDescription("Failed to install VS Code extension", "An error occurred while installing the VS Code extension."));
776
+ const installExtension = (extension) => ShellCommand6.make("code", "--install-extension", extension).pipe(ShellCommand6.stdout("inherit"), ShellCommand6.stderr("inherit"), ShellCommand6.exitCode, Effect13.mapError((cause) => new FailedToInstallExtension({ cause, extension })));
777
+ const extensions = [
778
+ scripts.includes("check") || scripts.includes("fix") || scripts.includes("format") ? installExtension("oxc.oxc-vscode") : Effect13.void,
779
+ scripts.includes("analyze") ? installExtension("webpro.vscode-knip") : Effect13.void,
780
+ scripts.includes("typecheck") ? installExtension("TypeScriptTeam.native-preview") : Effect13.void
781
+ ];
782
+ const results = yield* Effect13.all(extensions, { mode: "either" });
783
+ const firstFailure = results.find((r) => r._tag === "Left");
784
+ if (firstFailure) {
785
+ yield* Effect13.fail(firstFailure.left);
699
786
  }
700
- if (scripts.includes("analyze")) {
701
- yield* runCommand("code --install-extension webpro.vscode-knip").mapErr((error) => Fault10.wrap(error).withTag("FAILED_TO_INSTALL_EXTENSION").withDescription("Failed to install VS Code extension", "An error occurred while installing the VS Code extension."));
702
- }
703
- if (scripts.includes("typecheck")) {
704
- yield* runCommand("code --install-extension TypeScriptTeam.native-preview").mapErr((error) => Fault10.wrap(error).withTag("FAILED_TO_INSTALL_EXTENSION").withDescription("Failed to install VS Code extension", "An error occurred while installing the VS Code extension."));
705
- }
706
- return ok10();
707
787
  }),
708
- update: () => safeTry10(async function* () {
709
- const vscodePath = join6(process.cwd(), ".vscode", "settings.json");
710
- const vscodeFile = yield* fromPromise6(readFile5(vscodePath, "utf8"), (error) => Fault10.wrap(error).withTag("FAILED_TO_READ_FILE").withDescription("Failed to read .vscode/settings.json", "We're unable to read the .vscode/settings.json file in the current directory.").withContext({ path: vscodePath }));
711
- const existingConfig = yield* parseJson(vscodeFile);
788
+ update: () => Effect13.gen(function* () {
789
+ const fs = yield* FileSystem6.FileSystem;
790
+ const path = yield* Path6.Path;
791
+ const vscodePath = path.join(process.cwd(), ".vscode", SETTINGS_FILE);
792
+ const vscodeFile = yield* fs.readFileString(vscodePath).pipe(Effect13.mapError((cause) => new FailedToReadFile({ cause, path: vscodePath })));
793
+ const existingConfig = yield* parseJson(vscodeFile, vscodePath);
712
794
  if (!isJsonObject(existingConfig)) {
713
- return err5(Fault10.create("INVALID_CONFIG_FORMAT").withDescription("Invalid .vscode/settings.json format", "The VS Code settings file must be a JSON object."));
795
+ return yield* Effect13.fail(new InvalidConfigFormat({ path: vscodePath }));
714
796
  }
715
797
  const newConfig = yield* mergeConfig(vscode.config, existingConfig);
716
- yield* fromPromise6(writeFile5(join6(process.cwd(), ".vscode", "settings.json"), JSON.stringify(newConfig, null, 2)), (error) => Fault10.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write .vscode/settings.json", "We're unable to write the .vscode/settings.json file in the current directory.").withContext({ path: vscodePath }));
717
- return ok10();
798
+ yield* fs.writeFileString(vscodePath, `${JSON.stringify(newConfig, null, 2)}
799
+ `).pipe(Effect13.mapError((cause) => new FailedToWriteFile({ cause, path: vscodePath })));
718
800
  })
719
801
  };
720
802
 
@@ -725,42 +807,61 @@ var sherif = {
725
807
  };
726
808
 
727
809
  // src/helpers/packages/typescript.ts
728
- import { readFile as readFile6, writeFile as writeFile6 } from "node:fs/promises";
729
- import { join as join7 } from "node:path";
730
- import { Fault as Fault11 } from "faultier";
731
- import { err as err6, fromPromise as fromPromise7, ok as ok11, safeTry as safeTry11 } from "neverthrow";
810
+ import { FileSystem as FileSystem7, Path as Path7 } from "@effect/platform";
811
+ import { Effect as Effect14 } from "effect";
812
+ var CONFIG_FILE2 = "tsconfig.json";
732
813
  var typescript = {
733
814
  command: "tsgo",
734
815
  config: { extends: "adamantite/typescript" },
735
- create: () => fromPromise7(writeFile6(join7(process.cwd(), "tsconfig.json"), JSON.stringify(typescript.config, null, 2)), (error) => Fault11.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write tsconfig.json", "We're unable to write the tsconfig.json file in the current directory.")),
736
- exists: () => checkIfExists(join7(process.cwd(), "tsconfig.json")),
816
+ create: () => Effect14.gen(function* () {
817
+ const fs = yield* FileSystem7.FileSystem;
818
+ const path = yield* Path7.Path;
819
+ const configPath = path.join(process.cwd(), CONFIG_FILE2);
820
+ const payload = JSON.stringify(typescript.config, null, 2);
821
+ yield* fs.writeFileString(configPath, `${payload}
822
+ `).pipe(Effect14.mapError((cause) => new FailedToWriteFile({ cause, path: configPath })));
823
+ }),
824
+ exists: () => Effect14.gen(function* () {
825
+ const fs = yield* FileSystem7.FileSystem;
826
+ const path = yield* Path7.Path;
827
+ return yield* fs.exists(path.join(process.cwd(), CONFIG_FILE2));
828
+ }),
737
829
  name: "@typescript/native-preview",
738
- update: () => safeTry11(async function* () {
739
- const tsconfigFile = yield* fromPromise7(readFile6(join7(process.cwd(), "tsconfig.json"), "utf8"), (error) => Fault11.wrap(error).withTag("FAILED_TO_READ_FILE").withDescription("Failed to read tsconfig.json", "We're unable to read the tsconfig.json file in the current directory."));
740
- const existingConfig = yield* parseJson(tsconfigFile);
830
+ update: () => Effect14.gen(function* () {
831
+ const fs = yield* FileSystem7.FileSystem;
832
+ const path = yield* Path7.Path;
833
+ const configPath = path.join(process.cwd(), CONFIG_FILE2);
834
+ const tsconfigFile = yield* fs.readFileString(configPath).pipe(Effect14.mapError((cause) => new FailedToReadFile({ cause, path: configPath })));
835
+ const existingConfig = yield* parseJson(tsconfigFile, configPath);
741
836
  if (!isJsonObject(existingConfig)) {
742
- return err6(Fault11.create("INVALID_CONFIG_FORMAT").withDescription("Invalid tsconfig.json format", "The tsconfig.json file must be a JSON object."));
837
+ return yield* Effect14.fail(new InvalidConfigFormat({ path: configPath }));
743
838
  }
744
839
  const newConfig = yield* mergeConfig(typescript.config, existingConfig);
745
- yield* fromPromise7(writeFile6(join7(process.cwd(), "tsconfig.json"), JSON.stringify(newConfig, null, 2)), (error) => Fault11.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write tsconfig.json", "We're unable to write the tsconfig.json file in the current directory."));
746
- return ok11();
840
+ yield* fs.writeFileString(configPath, `${JSON.stringify(newConfig, null, 2)}
841
+ `).pipe(Effect14.mapError((cause) => new FailedToWriteFile({ cause, path: configPath })));
747
842
  }),
748
843
  version: "7.0.0-dev.20260108.1"
749
844
  };
750
845
 
751
846
  // src/commands/init.ts
752
- var installDependencies = (packages) => safeTry12(async function* () {
753
- const s = p.spinner();
754
- s.start("Installing dependencies...");
847
+ var installDependencies = (packages) => Effect15.gen(function* () {
848
+ const prompter = yield* Prompter;
849
+ const spinner2 = prompter.spinner();
850
+ spinner2.start("Installing dependencies...");
755
851
  const isMonorepo = yield* checkIsMonorepo();
756
- yield* fromPromise8(addDevDependency(packages, { silent: true, workspace: isMonorepo }), (error) => Fault12.wrap(error).withTag("FAILED_TO_INSTALL_DEPENDENCY").withMessage(`Failed to install dependencies: ${packages.join(", ")}`));
757
- s.stop("Dependencies installed.");
758
- return ok12();
852
+ yield* Effect15.tryPromise({
853
+ catch: (cause) => new FailedToInstallDependency({ cause, packages }),
854
+ try: () => addDevDependency(packages, { silent: true, workspace: isMonorepo })
855
+ }).pipe(Effect15.tapError(() => Effect15.sync(() => {
856
+ spinner2.stop("Failed to install dependencies.");
857
+ })));
858
+ spinner2.stop("Dependencies installed.");
759
859
  });
760
- var setupOxlintConfig = (presets) => safeTry12(async function* () {
761
- const spinner2 = p.spinner();
860
+ var setupOxlintConfig = (presets) => Effect15.gen(function* () {
861
+ const prompter = yield* Prompter;
862
+ const spinner2 = prompter.spinner();
762
863
  spinner2.start("Setting up oxlint config...");
763
- const oxlintPath = await oxlint.exists();
864
+ const oxlintPath = yield* oxlint.exists();
764
865
  if (oxlintPath.path) {
765
866
  spinner2.message(`Found \`${oxlintPath.path}\`, updating...`);
766
867
  yield* oxlint.update(presets);
@@ -770,12 +871,12 @@ var setupOxlintConfig = (presets) => safeTry12(async function* () {
770
871
  yield* oxlint.create(presets);
771
872
  spinner2.stop("oxlint config created successfully.");
772
873
  }
773
- return ok12();
774
874
  });
775
- var setupOxfmtConfig = () => safeTry12(async function* () {
776
- const spinner2 = p.spinner();
875
+ var setupOxfmtConfig = () => Effect15.gen(function* () {
876
+ const prompter = yield* Prompter;
877
+ const spinner2 = prompter.spinner();
777
878
  spinner2.start("Setting up oxfmt config...");
778
- const oxfmtPath = await oxfmt.exists();
879
+ const oxfmtPath = yield* oxfmt.exists();
779
880
  if (oxfmtPath.path) {
780
881
  spinner2.message(`Found \`${oxfmtPath.path}\`, updating...`);
781
882
  yield* oxfmt.update();
@@ -785,12 +886,14 @@ var setupOxfmtConfig = () => safeTry12(async function* () {
785
886
  yield* oxfmt.create();
786
887
  spinner2.stop("oxfmt config created successfully.");
787
888
  }
788
- return ok12();
789
889
  });
790
- var addScripts = (scripts) => safeTry12(async function* () {
791
- const cwd = process8.cwd();
890
+ var addScripts = (scripts) => Effect15.gen(function* () {
891
+ const fs = yield* FileSystem8.FileSystem;
892
+ const path = yield* Path8.Path;
893
+ const cwd = yield* Cwd;
894
+ const prompter = yield* Prompter;
792
895
  const packageJson = yield* readPackageJson();
793
- const spinner2 = p.spinner();
896
+ const spinner2 = prompter.spinner();
794
897
  spinner2.start("Adding scripts to your `package.json`...");
795
898
  packageJson.scripts ??= {};
796
899
  for (const script of scripts) {
@@ -817,17 +920,20 @@ var addScripts = (scripts) => safeTry12(async function* () {
817
920
  packageJson.scripts.analyze = "adamantite analyze";
818
921
  break;
819
922
  default:
820
- return err7(Fault12.create("UNKNOWN_SCRIPT").withContext({ script }));
923
+ return yield* Effect15.fail(new UnknownScript({ script }));
821
924
  }
822
925
  }
823
- yield* fromPromise8(writeFile7(join8(cwd, "package.json"), JSON.stringify(packageJson, null, 2)), (error) => Fault12.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write package.json", "We're unable to update the package.json file.").withContext({ path: join8(cwd, "package.json") }));
926
+ const currentDir = yield* cwd.get;
927
+ const packagePath = path.join(currentDir, "package.json");
928
+ yield* fs.writeFileString(packagePath, `${JSON.stringify(packageJson, null, 2)}
929
+ `).pipe(Effect15.mapError((cause) => new FailedToWriteFile({ cause, path: packagePath })));
824
930
  spinner2.stop("Scripts added to your `package.json`");
825
- return ok12();
826
931
  });
827
- var setupKnipConfig = () => safeTry12(async function* () {
828
- const spinner2 = p.spinner();
932
+ var setupKnipConfig = () => Effect15.gen(function* () {
933
+ const prompter = yield* Prompter;
934
+ const spinner2 = prompter.spinner();
829
935
  spinner2.start("Setting up knip config...");
830
- const knipPath = await knip.exists();
936
+ const knipPath = yield* knip.exists();
831
937
  if (knipPath.path) {
832
938
  spinner2.message(`Found \`${knipPath.path}\`, updating...`);
833
939
  yield* knip.update();
@@ -837,12 +943,13 @@ var setupKnipConfig = () => safeTry12(async function* () {
837
943
  yield* knip.create();
838
944
  spinner2.stop("knip config created successfully.");
839
945
  }
840
- return ok12();
841
946
  });
842
- var setupTypescript = () => safeTry12(async function* () {
843
- const spinner2 = p.spinner();
947
+ var setupTypescript = () => Effect15.gen(function* () {
948
+ const prompter = yield* Prompter;
949
+ const spinner2 = prompter.spinner();
844
950
  spinner2.start("Setting up TypeScript config...");
845
- if (await typescript.exists()) {
951
+ const typescriptExists = yield* typescript.exists();
952
+ if (typescriptExists) {
846
953
  spinner2.message("`tsconfig.json` found, updating...");
847
954
  yield* typescript.update();
848
955
  spinner2.stop("`tsconfig.json` updated successfully");
@@ -851,13 +958,14 @@ var setupTypescript = () => safeTry12(async function* () {
851
958
  yield* typescript.create();
852
959
  spinner2.stop("`tsconfig.json` created successfully");
853
960
  }
854
- return ok12();
855
961
  });
856
- var setupEditors = (editors) => safeTry12(async function* () {
962
+ var setupEditors = (editors) => Effect15.gen(function* () {
963
+ const prompter = yield* Prompter;
857
964
  if (editors.includes("vscode")) {
858
- const spinner2 = p.spinner();
965
+ const spinner2 = prompter.spinner();
859
966
  spinner2.start("Checking for `.vscode/settings.json`...");
860
- if (await vscode.exists()) {
967
+ const hasVscodeSettings = yield* vscode.exists();
968
+ if (hasVscodeSettings) {
861
969
  spinner2.message("`.vscode/settings.json` found, updating...");
862
970
  yield* vscode.update();
863
971
  spinner2.stop("`.vscode/settings.json` updated with Adamantite preset.");
@@ -868,23 +976,45 @@ var setupEditors = (editors) => safeTry12(async function* () {
868
976
  }
869
977
  }
870
978
  if (editors.includes("zed")) {}
871
- return ok12();
872
979
  });
873
- var installEditorExtensions = (editors, scripts) => safeTry12(function* () {
874
- const spinner2 = p.spinner();
980
+ var installEditorExtensions = (editors, scripts) => Effect15.gen(function* () {
981
+ const prompter = yield* Prompter;
982
+ const spinner2 = prompter.spinner();
875
983
  spinner2.start("Installing editor extensions...");
876
- if (editors.includes("vscode")) {
877
- spinner2.message("Installing VS Code extension...");
878
- yield* vscode.extension(scripts);
984
+ const result = yield* Effect15.gen(function* () {
985
+ if (editors.includes("vscode")) {
986
+ spinner2.message("Installing VS Code extension...");
987
+ yield* vscode.extension(scripts);
988
+ }
989
+ if (editors.includes("zed")) {}
990
+ return true;
991
+ }).pipe(Effect15.tapError(() => Effect15.sync(() => {
992
+ spinner2.stop();
993
+ })), Effect15.catchTags({
994
+ FailedToInstallExtension: (error) => Effect15.gen(function* () {
995
+ yield* prompter.log.warning(`⚠️ Failed to install the \`${error.extension}\` extension.`);
996
+ yield* prompter.log.warning("Please install it manually after setup completes.");
997
+ return false;
998
+ }),
999
+ VscodeCliNotFound: () => Effect15.gen(function* () {
1000
+ yield* prompter.log.error("VSCode CLI ('code' command) not found.");
1001
+ yield* prompter.log.info("To install it:");
1002
+ yield* prompter.log.info(" 1. Open VS Code");
1003
+ yield* prompter.log.info(" 2. Press Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows/Linux)");
1004
+ yield* prompter.log.info(` 3. Run 'Shell Command: Install "code" command in PATH'`);
1005
+ return false;
1006
+ })
1007
+ }));
1008
+ if (result) {
1009
+ spinner2.stop("Editor extensions installed successfully.");
879
1010
  }
880
- if (editors.includes("zed")) {}
881
- spinner2.stop("Editor extensions installed successfully.");
882
- return ok12();
883
1011
  });
884
- var setupGitHubActions = (packageManager, scripts) => safeTry12(async function* () {
885
- const spinner2 = p.spinner();
1012
+ var setupGitHubActions = (packageManager, scripts) => Effect15.gen(function* () {
1013
+ const prompter = yield* Prompter;
1014
+ const spinner2 = prompter.spinner();
886
1015
  spinner2.start("Setting up GitHub Actions workflow...");
887
- if (await github.exists()) {
1016
+ const workflowExists = yield* github.exists();
1017
+ if (workflowExists) {
888
1018
  spinner2.message("`.github/workflows/adamantite.yml` found, updating...");
889
1019
  yield* github.update({ packageManager, scripts });
890
1020
  spinner2.stop("GitHub Actions workflow updated successfully.");
@@ -893,322 +1023,278 @@ var setupGitHubActions = (packageManager, scripts) => safeTry12(async function*
893
1023
  yield* github.create({ packageManager, scripts });
894
1024
  spinner2.stop("GitHub Actions workflow created successfully.");
895
1025
  }
896
- return ok12();
897
- });
898
- var init_default = defineCommand({
899
- builder: (yargs) => yargs,
900
- command: "init",
901
- describe: "Initialize Adamantite in the current directory",
902
- handler: () => safeTry12(async function* () {
903
- const packageManager = yield* getPackageManagerName();
904
- printTitle();
905
- p.intro("\uD83D\uDCA0 adamantite init");
906
- p.log.info(`Detected package manager: ${packageManager}`);
907
- const isMonorepo = yield* checkIsMonorepo();
908
- if (isMonorepo) {
909
- p.log.info("We've detected a monorepo setup in your project.");
910
- }
911
- const scripts = yield* fromSafePromise(p.multiselect({
912
- message: "Which scripts do you want to add to your `package.json`?",
913
- options: [
914
- {
915
- hint: "recommended",
916
- label: "check - find issues in code using oxlint",
917
- value: "check"
918
- },
919
- {
920
- hint: "recommended",
921
- label: "fix - fix code issues using oxlint",
922
- value: "fix"
923
- },
924
- {
925
- hint: "recommended",
926
- label: "format - code formatting using oxfmt",
927
- value: "format"
928
- },
929
- {
930
- hint: "extends the `adamantite/typescript` preset in your `tsconfig.json`",
931
- label: "typecheck - type-check your code using tsgo",
932
- value: "typecheck"
933
- },
934
- {
935
- disabled: !isMonorepo,
936
- hint: isMonorepo ? undefined : "available for monorepo projects",
937
- label: "check:monorepo - check for monorepo-specific issues using Sherif",
938
- value: "check:monorepo"
939
- },
940
- {
941
- disabled: !isMonorepo,
942
- hint: isMonorepo ? undefined : "available for monorepo projects",
943
- label: "fix:monorepo - fix monorepo-specific issues using Sherif",
944
- value: "fix:monorepo"
945
- },
946
- {
947
- label: "analyze - find unused dependencies, exports, and files using knip",
948
- value: "analyze"
949
- }
950
- ]
951
- }));
952
- if (p.isCancel(scripts)) {
953
- return err7(Fault12.create("OPERATION_CANCELLED"));
954
- }
955
- const hasOxlint = scripts.includes("check") || scripts.includes("fix");
956
- let presets = [];
957
- if (hasOxlint) {
958
- presets = yield* fromSafePromise(p.multiselect({
959
- message: "Which presets do you want to install? (core is always included)",
960
- options: [
961
- { label: "React", value: "react" },
962
- { label: "Next.js", value: "nextjs" },
963
- { label: "Vue", value: "vue" },
964
- { label: "Jest", value: "jest" },
965
- { label: "Vitest", value: "vitest" },
966
- { label: "Node", value: "node" }
967
- ],
968
- required: false
969
- }));
970
- if (p.isCancel(presets)) {
971
- return err7(Fault12.create("OPERATION_CANCELLED"));
1026
+ }).pipe(Effect15.option);
1027
+ var init_default = Command5.make("init").pipe(Command5.withDescription("Initialize Adamantite in the current directory"), Command5.withHandler(() => Effect15.gen(function* () {
1028
+ const pm = yield* PackageManager;
1029
+ const prompter = yield* Prompter;
1030
+ yield* printTitle();
1031
+ yield* prompter.intro("\uD83D\uDCA0 adamantite init");
1032
+ yield* prompter.log.info(`Detected package manager: ${pm.name}`);
1033
+ const isMonorepo = yield* checkIsMonorepo();
1034
+ if (isMonorepo) {
1035
+ yield* prompter.log.info("We've detected a monorepo setup in your project.");
1036
+ }
1037
+ const selectedScripts = yield* prompter.multiselect({
1038
+ message: "Which scripts do you want to add to your `package.json`?",
1039
+ options: [
1040
+ {
1041
+ hint: "recommended",
1042
+ label: "check - find issues in code using oxlint",
1043
+ value: "check"
1044
+ },
1045
+ {
1046
+ hint: "recommended",
1047
+ label: "fix - fix code issues using oxlint",
1048
+ value: "fix"
1049
+ },
1050
+ {
1051
+ hint: "recommended",
1052
+ label: "format - code formatting using oxfmt",
1053
+ value: "format"
1054
+ },
1055
+ {
1056
+ hint: "extends the `adamantite/typescript` preset in your `tsconfig.json`",
1057
+ label: "typecheck - type-check your code using tsgo",
1058
+ value: "typecheck"
1059
+ },
1060
+ {
1061
+ disabled: !isMonorepo,
1062
+ hint: isMonorepo ? undefined : "available for monorepo projects",
1063
+ label: "check:monorepo - check for monorepo-specific issues using Sherif",
1064
+ value: "check:monorepo"
1065
+ },
1066
+ {
1067
+ disabled: !isMonorepo,
1068
+ hint: isMonorepo ? undefined : "available for monorepo projects",
1069
+ label: "fix:monorepo - fix monorepo-specific issues using Sherif",
1070
+ value: "fix:monorepo"
1071
+ },
1072
+ {
1073
+ label: "analyze - find unused dependencies, exports, and files using knip",
1074
+ value: "analyze"
972
1075
  }
973
- }
974
- const editors = yield* fromSafePromise(p.multiselect({
975
- message: "Which editors do you want to configure? (optional)",
1076
+ ]
1077
+ });
1078
+ if (isCancel(selectedScripts)) {
1079
+ return yield* Effect15.fail(new OperationCancelled({ reason: "init-cancelled" }));
1080
+ }
1081
+ const hasOxlint = selectedScripts.includes("check") || selectedScripts.includes("fix");
1082
+ let presets = [];
1083
+ if (hasOxlint) {
1084
+ const selectedPresets = yield* prompter.multiselect({
1085
+ message: "Which presets do you want to install? (core is always included)",
976
1086
  options: [
977
- { label: "VSCode / Cursor / Windsurf", value: "vscode" },
978
- { disabled: true, hint: "coming soon", label: "Zed", value: "zed" }
1087
+ { label: "React", value: "react" },
1088
+ { label: "Next.js", value: "nextjs" },
1089
+ { label: "Vue", value: "vue" },
1090
+ { label: "Jest", value: "jest" },
1091
+ { label: "Vitest", value: "vitest" },
1092
+ { label: "Node", value: "node" }
979
1093
  ],
980
1094
  required: false
981
- }));
982
- if (p.isCancel(editors)) {
983
- return err7(Fault12.create("OPERATION_CANCELLED"));
984
- }
985
- let installExtensions = false;
986
- if (editors.length > 0) {
987
- const installExtensionsResponse = yield* fromSafePromise(p.confirm({
988
- initialValue: true,
989
- message: "Do you want to install the recommended editor extensions?"
990
- }));
991
- if (p.isCancel(installExtensionsResponse)) {
992
- return err7(Fault12.create("OPERATION_CANCELLED"));
993
- }
994
- installExtensions = installExtensionsResponse;
995
- }
996
- const hasCIScripts = hasCICompatibleScripts(scripts);
997
- let enableGitHubActions = false;
998
- if (hasCIScripts) {
999
- enableGitHubActions = yield* fromSafePromise(p.confirm({
1000
- message: "Do you want to add a GitHub Actions workflow to run checks in CI?"
1001
- }));
1002
- if (p.isCancel(enableGitHubActions)) {
1003
- return err7(Fault12.create("OPERATION_CANCELLED"));
1004
- }
1005
- }
1006
- const hasOxfmt = scripts.includes("format");
1007
- const hasSherif = scripts.includes("check:monorepo") || scripts.includes("fix:monorepo");
1008
- const hasTypecheck = scripts.includes("typecheck");
1009
- const hasKnip = scripts.includes("analyze");
1010
- const dependencies = ["adamantite"];
1011
- if (hasOxlint) {
1012
- dependencies.push(`${oxlint.name}@${oxlint.version}`);
1013
- dependencies.push(`${tsgolint.name}@${tsgolint.version}`);
1014
- }
1015
- if (hasOxfmt) {
1016
- dependencies.push(`${oxfmt.name}@${oxfmt.version}`);
1017
- }
1018
- if (hasSherif) {
1019
- dependencies.push(`${sherif.name}@${sherif.version}`);
1020
- }
1021
- if (hasTypecheck) {
1022
- dependencies.push(`${typescript.name}@${typescript.version}`);
1023
- }
1024
- if (hasKnip) {
1025
- dependencies.push(`${knip.name}@${knip.version}`);
1026
- }
1027
- yield* installDependencies(dependencies);
1028
- if (hasOxfmt) {
1029
- yield* setupOxfmtConfig();
1030
- }
1031
- if (hasOxlint) {
1032
- yield* setupOxlintConfig(presets);
1033
- }
1034
- if (hasKnip) {
1035
- yield* setupKnipConfig();
1036
- }
1037
- yield* addScripts(scripts);
1038
- if (hasTypecheck) {
1039
- yield* setupTypescript();
1040
- }
1041
- yield* setupEditors(editors);
1042
- if (installExtensions) {
1043
- yield* installEditorExtensions(editors, scripts);
1044
- }
1045
- if (enableGitHubActions) {
1046
- yield* setupGitHubActions(packageManager, scripts);
1095
+ });
1096
+ if (isCancel(selectedPresets)) {
1097
+ return yield* Effect15.fail(new OperationCancelled({ reason: "init-cancelled" }));
1047
1098
  }
1048
- return ok12();
1049
- }).match(() => {
1050
- p.outro("\uD83D\uDCA0 Adamantite initialized successfully!");
1051
- process8.exit(0);
1052
- }, (error) => {
1053
- if (Fault12.isFault(error) && error.tag === "OPERATION_CANCELLED") {
1054
- p.cancel("You've cancelled the initialization process.");
1055
- process8.exit(0);
1099
+ presets = selectedPresets;
1100
+ }
1101
+ const selectedEditors = yield* prompter.multiselect({
1102
+ message: "Which editors do you want to configure? (optional)",
1103
+ options: [
1104
+ { label: "VSCode / Cursor / Windsurf", value: "vscode" },
1105
+ { disabled: true, hint: "coming soon", label: "Zed", value: "zed" }
1106
+ ],
1107
+ required: false
1108
+ });
1109
+ if (isCancel(selectedEditors)) {
1110
+ return yield* Effect15.fail(new OperationCancelled({ reason: "init-cancelled" }));
1111
+ }
1112
+ let installExtensions = false;
1113
+ if (selectedEditors.length > 0) {
1114
+ const installExtensionsResponse = yield* prompter.confirm({
1115
+ initialValue: true,
1116
+ message: "Do you want to install the recommended editor extensions?"
1117
+ });
1118
+ if (isCancel(installExtensionsResponse)) {
1119
+ return yield* Effect15.fail(new OperationCancelled({ reason: "init-cancelled" }));
1056
1120
  }
1057
- if (!Fault12.isFault(error)) {
1058
- p.log.error(`An unexpected error occurred: ${String(error)}`);
1059
- p.cancel("Failed to initialize Adamantite");
1060
- process8.exit(1);
1121
+ installExtensions = installExtensionsResponse;
1122
+ }
1123
+ const hasCIScripts = hasCICompatibleScripts(selectedScripts);
1124
+ let enableGitHubActions = false;
1125
+ if (hasCIScripts) {
1126
+ const enableGitHubActionsResponse = yield* prompter.confirm({
1127
+ message: "Do you want to add a GitHub Actions workflow to run checks in CI?"
1128
+ });
1129
+ if (isCancel(enableGitHubActionsResponse)) {
1130
+ return yield* Effect15.fail(new OperationCancelled({ reason: "init-cancelled" }));
1061
1131
  }
1062
- p.log.error(error.flatten());
1063
- p.cancel("Failed to initialize Adamantite");
1064
- process8.exit(1);
1132
+ enableGitHubActions = enableGitHubActionsResponse;
1133
+ }
1134
+ const hasOxfmt = selectedScripts.includes("format");
1135
+ const hasSherif = selectedScripts.includes("check:monorepo") || selectedScripts.includes("fix:monorepo");
1136
+ const hasTypecheck = selectedScripts.includes("typecheck");
1137
+ const hasKnip = selectedScripts.includes("analyze");
1138
+ const dependencies = ["adamantite"];
1139
+ if (hasOxlint) {
1140
+ dependencies.push(`${oxlint.name}@${oxlint.version}`);
1141
+ dependencies.push(`${tsgolint.name}@${tsgolint.version}`);
1142
+ }
1143
+ if (hasOxfmt) {
1144
+ dependencies.push(`${oxfmt.name}@${oxfmt.version}`);
1145
+ }
1146
+ if (hasSherif) {
1147
+ dependencies.push(`${sherif.name}@${sherif.version}`);
1148
+ }
1149
+ if (hasTypecheck) {
1150
+ dependencies.push(`${typescript.name}@${typescript.version}`);
1151
+ }
1152
+ if (hasKnip) {
1153
+ dependencies.push(`${knip.name}@${knip.version}`);
1154
+ }
1155
+ yield* installDependencies(dependencies);
1156
+ if (hasOxfmt) {
1157
+ yield* setupOxfmtConfig();
1158
+ }
1159
+ if (hasOxlint) {
1160
+ yield* setupOxlintConfig(presets);
1161
+ }
1162
+ if (hasKnip) {
1163
+ yield* setupKnipConfig();
1164
+ }
1165
+ yield* addScripts(selectedScripts);
1166
+ if (hasTypecheck) {
1167
+ yield* setupTypescript();
1168
+ }
1169
+ yield* setupEditors(selectedEditors);
1170
+ if (installExtensions) {
1171
+ yield* installEditorExtensions(selectedEditors, selectedScripts);
1172
+ }
1173
+ if (enableGitHubActions) {
1174
+ yield* setupGitHubActions(pm.name, selectedScripts);
1175
+ }
1176
+ yield* prompter.log.success("Your project is now configured");
1177
+ yield* prompter.outro("\uD83D\uDCA0 Adamantite initialized successfully!");
1178
+ }).pipe(Effect15.catchTags({
1179
+ OperationCancelled: () => Effect15.gen(function* () {
1180
+ const prompter = yield* Prompter;
1181
+ yield* prompter.cancel("You've cancelled the initialization process.");
1065
1182
  })
1066
- });
1183
+ }))));
1067
1184
 
1068
1185
  // src/commands/monorepo.ts
1069
- import process9 from "node:process";
1070
- import { log as log6 } from "@clack/prompts";
1071
- import { Fault as Fault13 } from "faultier";
1072
- import { ok as ok13, safeTry as safeTry13 } from "neverthrow";
1073
- import { dlxCommand as dlxCommand5 } from "nypm";
1074
- var monorepo_default = defineCommand({
1075
- builder: (yargs) => yargs.option("fix", {
1076
- description: "Automatically fix issues",
1077
- type: "boolean"
1078
- }),
1079
- command: "monorepo",
1080
- describe: "Find and fix monorepo-specific issues using Sherif",
1081
- handler: (argv) => safeTry13(async function* () {
1082
- const packageManager = yield* getPackageManagerName();
1083
- const args = [];
1084
- if (argv.fix) {
1085
- args.push("--fix");
1086
- }
1087
- const command = dlxCommand5(packageManager, sherif.name, { args });
1088
- yield* runCommand(command);
1089
- return ok13();
1090
- }).match(() => {
1091
- process9.exit(0);
1092
- }, (error) => {
1093
- if (Fault13.isFault(error) && error.tag === "NO_PACKAGE_MANAGER") {
1094
- log6.error(error.flatten());
1095
- }
1096
- process9.exit(1);
1097
- })
1098
- });
1186
+ import { Command as Command6, Options as Options4 } from "@effect/cli";
1187
+ import { Command as ShellCommand7 } from "@effect/platform";
1188
+ import { Effect as Effect16 } from "effect";
1189
+ var fix2 = Options4.boolean("fix").pipe(Options4.withDescription("Automatically fix issues"));
1190
+ var monorepo_default = Command6.make("monorepo", { fix: fix2 }).pipe(Command6.withDescription("Find and fix monorepo-specific issues using Sherif"), Command6.withHandler(({ fix: fix3 }) => Effect16.gen(function* () {
1191
+ const pm = yield* PackageManager;
1192
+ const [command, ...commandArgs] = pm.command;
1193
+ const args = [];
1194
+ if (fix3) {
1195
+ args.push("--fix");
1196
+ }
1197
+ return yield* ShellCommand7.make(command, ...commandArgs, sherif.name, ...args).pipe(ShellCommand7.stdout("inherit"), ShellCommand7.stderr("inherit"), ShellCommand7.exitCode);
1198
+ })));
1099
1199
 
1100
1200
  // src/commands/typecheck.ts
1101
- import process10 from "node:process";
1102
- import { log as log7 } from "@clack/prompts";
1103
- import { Fault as Fault14 } from "faultier";
1104
- import { ok as ok14, safeTry as safeTry14 } from "neverthrow";
1105
- import { dlxCommand as dlxCommand6 } from "nypm";
1106
- var typecheck_default = defineCommand({
1107
- builder: (yargs) => yargs.option("project", {
1108
- alias: "p",
1109
- description: "Path to tsconfig.json file",
1110
- type: "string"
1111
- }).option("watch", {
1112
- alias: "w",
1113
- description: "Run in watch mode",
1114
- type: "boolean"
1115
- }),
1116
- command: "typecheck",
1117
- describe: "Run TypeScript type checking",
1118
- handler: (argv) => safeTry14(async function* () {
1119
- const packageManager = yield* getPackageManagerName();
1120
- const args = ["--noEmit"];
1121
- if (argv.project) {
1122
- args.push("--project", argv.project);
1123
- }
1124
- if (argv.watch) {
1125
- args.push("--watch");
1126
- }
1127
- const command = dlxCommand6(packageManager, typescript.command, { args });
1128
- const result = yield* runCommand(command);
1129
- return ok14(result);
1130
- }).match(() => {
1131
- process10.exit(0);
1132
- }, (error) => {
1133
- if (Fault14.isFault(error) && error.tag === "NO_PACKAGE_MANAGER") {
1134
- log7.error(error.flatten());
1135
- }
1136
- process10.exit(1);
1137
- })
1138
- });
1201
+ import { Command as Command7, Options as Options5 } from "@effect/cli";
1202
+ import { Command as ShellCommand8 } from "@effect/platform";
1203
+ import { Effect as Effect17, Option as Option4 } from "effect";
1204
+ var project = Options5.text("project").pipe(Options5.withAlias("p"), Options5.optional, Options5.withDescription("Path to tsconfig.json file"));
1205
+ var watch = Options5.boolean("watch").pipe(Options5.withAlias("w"), Options5.withDescription("Run in watch mode"));
1206
+ var typecheck_default = Command7.make("typecheck", { project, watch }).pipe(Command7.withDescription("Run TypeScript type checking"), Command7.withHandler(({ project: project2, watch: watch2 }) => Effect17.gen(function* () {
1207
+ const pm = yield* PackageManager;
1208
+ const [command, ...commandArgs] = pm.command;
1209
+ const args = ["--noEmit"];
1210
+ if (Option4.isSome(project2)) {
1211
+ args.push("--project", project2.value);
1212
+ }
1213
+ if (watch2) {
1214
+ args.push("--watch");
1215
+ }
1216
+ return yield* ShellCommand8.make(command, ...commandArgs, typescript.command, ...args).pipe(ShellCommand8.stdout("inherit"), ShellCommand8.stderr("inherit"), ShellCommand8.exitCode);
1217
+ })));
1139
1218
 
1140
1219
  // src/commands/update.ts
1141
- import process11 from "node:process";
1142
- import { cancel as cancel2, confirm as confirm2, intro as intro2, isCancel as isCancel2, log as log8, outro as outro2, spinner as spinner2 } from "@clack/prompts";
1143
- import { Fault as Fault15 } from "faultier";
1144
- import { err as err8, fromPromise as fromPromise9, fromSafePromise as fromSafePromise2, ok as ok15, safeTry as safeTry15 } from "neverthrow";
1220
+ import { isCancel as isCancel2 } from "@clack/prompts";
1221
+ import { Command as Command8 } from "@effect/cli";
1222
+ import { Effect as Effect18 } from "effect";
1145
1223
  import { addDevDependency as addDevDependency2 } from "nypm";
1146
- var update_default = defineCommand({
1147
- builder: (yargs) => yargs,
1148
- command: "update",
1149
- describe: "Update adamantite dependencies to latest compatible versions",
1150
- handler: () => safeTry15(async function* () {
1151
- const packageJson = yield* readPackageJson();
1152
- printTitle();
1153
- intro2("\uD83D\uDCA0 adamantite update");
1154
- const updates = [];
1155
- for (const pkg of [oxlint, oxfmt, sherif]) {
1156
- const dependency = packageJson.devDependencies?.[pkg.name];
1157
- if (dependency && normalizeDependencyVersion(dependency) !== pkg.version) {
1158
- updates.push({
1159
- currentVersion: dependency,
1160
- isDevDependency: true,
1161
- name: pkg.name,
1162
- targetVersion: pkg.version
1163
- });
1164
- }
1165
- }
1166
- if (updates.length === 0) {
1167
- log8.success("All adamantite dependencies are already up to date!");
1168
- return ok15("no-updates");
1169
- }
1170
- log8.message("The following dependencies will be updated:");
1171
- for (const dep of updates) {
1172
- log8.message(` ${dep.name}: ${dep.currentVersion} → ${dep.targetVersion}`);
1173
- }
1174
- const shouldUpdate = yield* fromSafePromise2(confirm2({
1175
- message: "Do you want to proceed with these updates?"
1176
- }));
1177
- if (isCancel2(shouldUpdate)) {
1178
- return err8(Fault15.create("OPERATION_CANCELLED"));
1179
- }
1180
- if (!shouldUpdate) {
1181
- return ok15("cancelled");
1182
- }
1183
- const s = spinner2();
1184
- s.start("Updating dependencies...");
1185
- yield* fromPromise9(addDevDependency2(updates.map((dep) => `${dep.name}@${dep.targetVersion}`), { silent: true }), (error) => Fault15.wrap(error).withTag("FAILED_TO_INSTALL_DEPENDENCY").withMessage(`Failed to update dependencies: ${updates.map((dep) => dep.name).join(", ")}`));
1186
- s.stop("Dependencies updated successfully");
1187
- return ok15("updated");
1188
- }).match((value) => {
1189
- if (value === "no-updates") {
1190
- outro2("✅ No updates needed");
1191
- } else if (value === "cancelled") {
1192
- outro2("⚠️ Update cancelled");
1193
- } else if (value === "updated") {
1194
- outro2("✅ Dependencies updated successfully!");
1195
- }
1196
- process11.exit(0);
1197
- }, (error) => {
1198
- if (Fault15.isFault(error) && error.tag === "OPERATION_CANCELLED") {
1199
- cancel2("You've cancelled the update process.");
1200
- process11.exit(0);
1201
- }
1202
- if (Fault15.isFault(error)) {
1203
- log8.error(error.flatten());
1204
- } else {
1205
- log8.error(String(error));
1224
+ var update_default = Command8.make("update").pipe(Command8.withDescription("Update adamantite dependencies to latest compatible versions"), Command8.withHandler(() => Effect18.gen(function* () {
1225
+ const prompter = yield* Prompter;
1226
+ const packageJson = yield* readPackageJson();
1227
+ yield* printTitle();
1228
+ yield* prompter.intro("\uD83D\uDCA0 adamantite update");
1229
+ const updates = [];
1230
+ for (const pkg of [oxlint, oxfmt, sherif]) {
1231
+ const dependency = packageJson.devDependencies?.[pkg.name];
1232
+ if (dependency && normalizeDependencyVersion(dependency) !== pkg.version) {
1233
+ updates.push({
1234
+ currentVersion: dependency,
1235
+ isDevDependency: true,
1236
+ name: pkg.name,
1237
+ targetVersion: pkg.version
1238
+ });
1206
1239
  }
1207
- cancel2("Failed to update dependencies");
1208
- process11.exit(1);
1240
+ }
1241
+ if (updates.length === 0) {
1242
+ yield* prompter.log.success("All adamantite dependencies are already up to date!");
1243
+ return "no-updates";
1244
+ }
1245
+ yield* prompter.log.info("The following dependencies will be updated:");
1246
+ for (const dep of updates) {
1247
+ yield* prompter.log.info(` ${dep.name}: ${dep.currentVersion} → ${dep.targetVersion}`);
1248
+ }
1249
+ const shouldUpdate = yield* prompter.confirm({
1250
+ message: "Do you want to proceed with these updates?"
1251
+ });
1252
+ if (isCancel2(shouldUpdate)) {
1253
+ return yield* Effect18.fail(new OperationCancelled({ reason: "update-cancelled" }));
1254
+ }
1255
+ if (!shouldUpdate) {
1256
+ return "cancelled";
1257
+ }
1258
+ const spinner2 = prompter.spinner();
1259
+ spinner2.start("Updating dependencies...");
1260
+ yield* Effect18.tryPromise({
1261
+ catch: (cause) => new FailedToInstallDependency({
1262
+ cause,
1263
+ packages: updates.map((dep) => dep.name)
1264
+ }),
1265
+ try: () => addDevDependency2(updates.map((dep) => `${dep.name}@${dep.targetVersion}`), { silent: true })
1266
+ }).pipe(Effect18.tapError(() => Effect18.sync(() => {
1267
+ spinner2.stop("Failed to update dependencies");
1268
+ })));
1269
+ spinner2.stop("Dependencies updated successfully");
1270
+ return "updated";
1271
+ }).pipe(Effect18.tap((value) => Effect18.gen(function* () {
1272
+ const prompter = yield* Prompter;
1273
+ switch (value) {
1274
+ case "no-updates":
1275
+ yield* prompter.outro("✅ No updates needed");
1276
+ break;
1277
+ case "cancelled":
1278
+ yield* prompter.outro("⚠️ Update cancelled");
1279
+ break;
1280
+ case "updated":
1281
+ yield* prompter.outro("✅ Dependencies updated successfully!");
1282
+ break;
1283
+ default:
1284
+ break;
1285
+ }
1286
+ })), Effect18.catchTags({
1287
+ OperationCancelled: () => Effect18.gen(function* () {
1288
+ const prompter = yield* Prompter;
1289
+ yield* prompter.cancel("You've cancelled the update process.");
1209
1290
  })
1210
- });
1291
+ }))));
1211
1292
 
1212
1293
  // src/index.ts
1213
- var version = await "0.25.0";
1214
- yargs(hideBin(process.argv)).scriptName("adamantite").version(version).command(analyze_default).command(check_default).command(fix_default).command(format_default2).command(init_default).command(monorepo_default).command(typecheck_default).command(update_default).demandCommand(1).strict().help().parse();
1294
+ var main = Command9.make("adamantite").pipe(Command9.withDescription("Opinionated preset package for modern TypeScript applications"), Command9.withSubcommands([analyze_default, check_default, fix_default, format_default2, init_default, monorepo_default, typecheck_default, update_default]));
1295
+ var program = Effect19.gen(function* () {
1296
+ const version = yield* getPackageVersion();
1297
+ const cli = Command9.run(main, { name: "adamantite", version });
1298
+ yield* cli(process5.argv);
1299
+ });
1300
+ program.pipe(Effect19.provide(Layer4.mergeAll(NodeContext.layer, PackageManagerLive, PrompterLive, CwdLive)), NodeRuntime.runMain);