adamantite 0.14.0 → 0.15.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.
package/dist/index.mjs DELETED
@@ -1,395 +0,0 @@
1
- import yargs from "yargs";
2
- import { hideBin } from "yargs/helpers";
3
- import process$1 from "process";
4
- import { err, fromPromise, fromSafePromise, fromThrowable, ok, safeTry } from "neverthrow";
5
- import { addDevDependency, detectPackageManager, dlxCommand } from "nypm";
6
- import { access, mkdir, readFile, writeFile } from "fs/promises";
7
- import { join } from "path";
8
- import { Fault } from "faultier";
9
- import { execSync } from "child_process";
10
- import defu from "defu";
11
- import { parse } from "jsonc-parser";
12
- import { cancel, confirm, intro, isCancel, log, multiselect, outro, spinner } from "@clack/prompts";
13
- import { readFileSync } from "fs";
14
-
15
- //#region src/utils.ts
16
- function defineCommand(input) {
17
- return input;
18
- }
19
- const runCommand = fromThrowable(execSync, (error) => Fault.wrap(error).withTag("FAILED_TO_RUN_COMMAND"));
20
- const getPackageManagerName = () => fromPromise(detectPackageManager(process$1.cwd()), () => Fault.create("NO_PACKAGE_MANAGER").withDescription("Error while detecting the package manager.", "We're unable to detect the package manager used in this project.")).andThen((result) => {
21
- if (!result) return err(Fault.create("NO_PACKAGE_MANAGER").withDescription("No package manager detected.", "We're unable to detect the package manager used in this project."));
22
- return ok(result.name);
23
- });
24
- const checkIfExists = (path) => fromPromise(access(path), () => /* @__PURE__ */ new Error("File not found")).match(() => true, () => false);
25
- const parseJson = (content) => {
26
- const errors = [];
27
- const parsed = parse(content, errors);
28
- if (errors.length > 0) return err(Fault.create("FAILED_TO_PARSE_FILE").withDescription("Failed to parse JSON", "We're unable to parse the provided JSON file.").withContext({ errors }));
29
- return ok(parsed);
30
- };
31
- const 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."));
32
- const readPackageJson = (cwd = process$1.cwd()) => fromPromise(readFile(join(cwd, "package.json"), "utf-8"), (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));
33
- function getTitle() {
34
- if ((process$1.stdout.columns || 80) >= 120) return `
35
- █████ █████ ███ █████
36
- ░░███ ░░███ ░░░ ░░███
37
- ██████ ███████ ██████ █████████████ ██████ ████████ ███████ ████ ███████ ██████
38
- ░░░░░███ ███░░███ ░░░░░███ ░░███░░███░░███ ░░░░░███ ░░███░░███ ░░░███░ ░░███ ░░░███░ ███░░███
39
- ███████ ░███ ░███ ███████ ░███ ░███ ░███ ███████ ░███ ░███ ░███ ░███ ░███ ░███████
40
- ███░░███ ░███ ░███ ███░░███ ░███ ░███ ░███ ███░░███ ░███ ░███ ░███ ███ ░███ ░███ ███░███░░░
41
- ░░████████░░████████░░████████ █████░███ █████░░████████ ████ █████ ░░█████ █████ ░░█████ ░░██████
42
- ░░░░░░░░ ░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░ ░░░░░ ░░░░░░░░ ░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░
43
- `;
44
- return `
45
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
46
- ┃ ADAMANTITE ┃
47
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
48
- `;
49
- }
50
-
51
- //#endregion
52
- //#region src/helpers/packages/biome.ts
53
- const biome = {
54
- name: "@biomejs/biome",
55
- version: "2.3.10",
56
- config: { $schema: "./node_modules/@biomejs/biome/configuration_schema.json" },
57
- exists: async () => {
58
- if (await checkIfExists(join(process.cwd(), "biome.jsonc"))) return { path: join(process.cwd(), "biome.jsonc") };
59
- if (await checkIfExists(join(process.cwd(), "biome.json"))) return { path: join(process.cwd(), "biome.json") };
60
- return { path: null };
61
- },
62
- create: () => fromPromise(writeFile(join(process.cwd(), "biome.jsonc"), JSON.stringify({
63
- ...biome.config,
64
- extends: ["adamantite"]
65
- }, null, 2)), (error) => Fault.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write Biome configuration", "We're unable to write the Biome configuration to the current directory.")),
66
- update: () => safeTry(async function* () {
67
- const exists = await biome.exists();
68
- if (!exists.path) return err(Fault.create("FILE_NOT_FOUND").withDescription("No `biome.jsonc` or `biome.json` found", "We're unable to find a Biome configuration in the current directory."));
69
- const existingConfig = yield* parseJson(yield* fromPromise(readFile(exists.path, "utf-8"), (error) => Fault.wrap(error).withTag("FAILED_TO_READ_FILE").withDescription("Failed to read Biome configuration", "We're unable to read the Biome configuration from the current directory.")));
70
- if (!existingConfig || Object.keys(existingConfig).length === 0) return err(Fault.create("INVALID_BIOME_CONFIG").withDescription("Invalid Biome configuration", "The Biome configuration file is empty or invalid.").withContext({ path: exists.path }));
71
- const newConfig = { ...existingConfig };
72
- if (!Array.isArray(newConfig.extends)) newConfig.extends = newConfig.extends ? [newConfig.extends] : [];
73
- if (!newConfig.extends.includes("adamantite")) newConfig.extends.push("adamantite");
74
- const mergedConfig = yield* mergeConfig(newConfig, biome.config);
75
- mergedConfig.$schema = biome.config.$schema;
76
- yield* fromPromise(writeFile(exists.path, JSON.stringify(mergedConfig, null, 2)), (error) => Fault.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write Biome configuration", "We're unable to write the Biome configuration to the current directory.").withContext({ path: exists.path }));
77
- return ok();
78
- })
79
- };
80
-
81
- //#endregion
82
- //#region src/commands/check.ts
83
- var check_default = defineCommand({
84
- command: "check [files..]",
85
- describe: "Run Biome linter and check files for issues",
86
- builder: (yargs$1) => yargs$1.positional("files", {
87
- describe: "Specific files to lint (optional)",
88
- type: "string",
89
- array: true
90
- }).option("summary", {
91
- type: "boolean",
92
- description: "Show summary of lint results"
93
- }),
94
- handler: async (argv) => {
95
- if ((await safeTry(async function* () {
96
- const packageManager = yield* getPackageManagerName();
97
- const args = ["check"];
98
- if (argv.summary) args.push("--reporter", "summary");
99
- if (argv.files && argv.files.length > 0) args.push(...argv.files);
100
- yield* runCommand(dlxCommand(packageManager, biome.name, { args }), { stdio: "inherit" });
101
- return ok(void 0);
102
- })).isOk()) return;
103
- process$1.exit(1);
104
- }
105
- });
106
-
107
- //#endregion
108
- //#region src/helpers/packages/sherif.ts
109
- const sherif = {
110
- name: "sherif",
111
- version: "1.9.0"
112
- };
113
-
114
- //#endregion
115
- //#region src/commands/ci.ts
116
- var ci_default = defineCommand({
117
- command: "ci",
118
- describe: "Run Adamantite in a CI environment",
119
- builder: (yargs$1) => yargs$1.option("monorepo", {
120
- type: "boolean",
121
- description: "Run additional monorepo-specific checks"
122
- }).option("github", {
123
- type: "boolean",
124
- description: "Use GitHub reporter"
125
- }),
126
- handler: async (argv) => {
127
- if ((await safeTry(async function* () {
128
- const packageManager = yield* getPackageManagerName();
129
- const tools = [{
130
- package: biome.name,
131
- args: ["ci", ...argv.github ? ["--reporter", "github"] : []]
132
- }];
133
- if (argv.monorepo) tools.push({
134
- package: sherif.name,
135
- args: []
136
- });
137
- for (const tool of tools) yield* runCommand(dlxCommand(packageManager, tool.package, { args: tool.args }), { stdio: "inherit" });
138
- return ok(void 0);
139
- })).isOk()) return;
140
- process$1.exit(1);
141
- }
142
- });
143
-
144
- //#endregion
145
- //#region src/commands/fix.ts
146
- var fix_default = defineCommand({
147
- command: "fix [files..]",
148
- describe: "Run Biome linter and fix issues in files",
149
- builder: (yargs$1) => yargs$1.positional("files", {
150
- describe: "Specific files to fix (optional)",
151
- type: "string",
152
- array: true
153
- }).option("unsafe", {
154
- type: "boolean",
155
- description: "Apply unsafe fixes"
156
- }),
157
- handler: async (argv) => {
158
- if ((await safeTry(async function* () {
159
- const packageManager = yield* getPackageManagerName();
160
- const args = ["check", "--write"];
161
- if (argv.unsafe) args.push("--unsafe");
162
- if (argv.files && argv.files.length > 0) args.push(...argv.files);
163
- yield* runCommand(dlxCommand(packageManager, biome.name, { args }), { stdio: "inherit" });
164
- return ok(void 0);
165
- })).isOk()) return;
166
- process$1.exit(1);
167
- }
168
- });
169
-
170
- //#endregion
171
- //#region src/helpers/editors/vscode.ts
172
- const vscode = {
173
- config: {
174
- "typescript.tsdk": "node_modules/typescript/lib",
175
- "editor.formatOnSave": true,
176
- "editor.formatOnPaste": true,
177
- "editor.codeActionsOnSave": {
178
- "source.organizeImports.biome": "explicit",
179
- "source.fixAll.biome": "explicit"
180
- },
181
- "[javascript][typescript][javascriptreact][typescriptreact][json][jsonc][css][graphql]": { "editor.defaultFormatter": "biomejs.biome" }
182
- },
183
- exists: () => checkIfExists(join(process.cwd(), ".vscode", "settings.json")),
184
- create: () => safeTry(async function* () {
185
- const vscodePath = join(process.cwd(), ".vscode");
186
- yield* fromPromise(mkdir(vscodePath, { recursive: true }), (error) => Fault.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 }));
187
- yield* fromPromise(writeFile(join(vscodePath, "settings.json"), JSON.stringify(vscode.config, null, 2)), (error) => Fault.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."));
188
- return ok();
189
- }),
190
- update: () => safeTry(async function* () {
191
- const vscodePath = join(process.cwd(), ".vscode", "settings.json");
192
- const existingConfig = yield* parseJson(yield* fromPromise(readFile(vscodePath, "utf-8"), (error) => Fault.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 })));
193
- const newConfig = yield* mergeConfig(vscode.config, existingConfig);
194
- yield* fromPromise(writeFile(join(process.cwd(), ".vscode", "settings.json"), JSON.stringify(newConfig, null, 2)), (error) => Fault.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 }));
195
- return ok();
196
- })
197
- };
198
-
199
- //#endregion
200
- //#region src/helpers/tsconfig.ts
201
- const tsconfig = {
202
- config: { extends: "adamantite/tsconfig" },
203
- exists: () => checkIfExists(join(process.cwd(), "tsconfig.json")),
204
- create: () => fromPromise(writeFile(join(process.cwd(), "tsconfig.json"), JSON.stringify(tsconfig.config, null, 2)), (error) => Fault.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.")),
205
- update: () => safeTry(async function* () {
206
- const existingConfig = yield* parseJson(yield* fromPromise(readFile(join(process.cwd(), "tsconfig.json"), "utf-8"), (error) => Fault.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.")));
207
- const newConfig = yield* mergeConfig(tsconfig.config, existingConfig);
208
- yield* fromPromise(writeFile(join(process.cwd(), "tsconfig.json"), JSON.stringify(newConfig, null, 2)), (error) => Fault.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."));
209
- return ok();
210
- })
211
- };
212
-
213
- //#endregion
214
- //#region src/commands/init.ts
215
- var init_default = defineCommand({
216
- command: "init",
217
- describe: "Initialize Adamantite in the current directory",
218
- builder: (yargs$1) => yargs$1,
219
- handler: async () => {
220
- intro(getTitle());
221
- const cwd = process$1.cwd();
222
- const result = await safeTry(async function* () {
223
- let packageJson = yield* readPackageJson();
224
- const hasPnpmWorkspace = await checkIfExists(join(process$1.cwd(), "pnpm-workspace.yaml"));
225
- const isMonorepo = packageJson.workspaces !== void 0 || hasPnpmWorkspace;
226
- const shouldInstallScripts = yield* fromSafePromise(confirm({ message: "Do you want to add the `check` and `fix` scripts to your `package.json`?" })).andThen((r) => isCancel(r) ? err(Fault.create("OPERATION_CANCELLED")) : ok(r));
227
- const shouldInstallMonorepoScripts = isMonorepo ? yield* fromSafePromise(confirm({ message: "We've detected a monorepo setup in your project. Would you like to install monorepo linting scripts?" })).andThen((r) => isCancel(r) ? err(Fault.create("OPERATION_CANCELLED")) : ok(r)) : false;
228
- const shouldInstallTypeScriptPreset = yield* fromSafePromise(confirm({ message: "Adamantite provides a TypeScript preset to enforce strict type-safety. Would you like to install it?" })).andThen((r) => isCancel(r) ? err(Fault.create("OPERATION_CANCELLED")) : ok(r));
229
- const selectedEditors = yield* fromSafePromise(multiselect({
230
- message: "Which editors do you want to configure (recommended)?",
231
- options: [{
232
- label: "VSCode / Cursor / Windsurf",
233
- value: "vscode"
234
- }, {
235
- label: "Zed (coming soon)",
236
- value: "zed"
237
- }],
238
- required: false
239
- })).andThen((r) => isCancel(r) ? err(Fault.create("OPERATION_CANCELLED")) : ok(r));
240
- const installingDependencies = spinner();
241
- installingDependencies.start("Installing dependencies...");
242
- yield* fromPromise(addDevDependency("adamantite"), (error) => Fault.wrap(error).withTag("FAILED_TO_INSTALL_DEPENDENCY").withMessage("Failed to install Adamantite"));
243
- yield* fromPromise(addDevDependency(`${biome.name}@${biome.version}`), (error) => Fault.wrap(error).withTag("FAILED_TO_INSTALL_DEPENDENCY").withMessage("Failed to install Biome"));
244
- if (shouldInstallMonorepoScripts) yield* fromPromise(addDevDependency(`${sherif.name}@${sherif.version}`), (error) => Fault.wrap(error).withTag("FAILED_TO_INSTALL_DEPENDENCY").withMessage("Failed to install Sherif"));
245
- installingDependencies.stop("Dependencies installed successfully");
246
- const settingUpBiomeConfig = spinner();
247
- settingUpBiomeConfig.start("Setting up Biome config...");
248
- if ((await biome.exists()).path) {
249
- settingUpBiomeConfig.message("Biome config found, updating...");
250
- yield* biome.update();
251
- settingUpBiomeConfig.stop("Biome config updated successfully");
252
- } else {
253
- settingUpBiomeConfig.message("Biome config not found, creating...");
254
- yield* biome.create();
255
- settingUpBiomeConfig.stop("Biome config created successfully");
256
- }
257
- if (shouldInstallScripts) {
258
- const addingScripts = spinner();
259
- packageJson = yield* readPackageJson();
260
- addingScripts.start("Adding scripts to your `package.json`...");
261
- if (!packageJson.scripts) packageJson.scripts = {};
262
- packageJson.scripts.check = "adamantite check";
263
- packageJson.scripts.fix = "adamantite fix";
264
- if (shouldInstallMonorepoScripts) packageJson.scripts["lint:monorepo"] = "adamantite monorepo";
265
- yield* fromPromise(writeFile(join(cwd, "package.json"), JSON.stringify(packageJson, null, 2)), (error) => Fault.wrap(error).withTag("FAILED_TO_WRITE_FILE").withDescription("Failed to write package.json", "We're unable to update the package.json file.").withContext({ path: join(cwd, "package.json") }));
266
- addingScripts.stop("Scripts added to your `package.json`");
267
- }
268
- if (shouldInstallTypeScriptPreset) {
269
- const settingUpTypeScriptConfig = spinner();
270
- settingUpTypeScriptConfig.start("Setting up TypeScript config...");
271
- if (await tsconfig.exists()) {
272
- settingUpTypeScriptConfig.message("`tsconfig.json` found, updating...");
273
- yield* tsconfig.update();
274
- settingUpTypeScriptConfig.stop("`tsconfig.json` updated successfully");
275
- } else {
276
- settingUpTypeScriptConfig.message("`tsconfig.json` not found, creating...");
277
- yield* tsconfig.create();
278
- settingUpTypeScriptConfig.stop("`tsconfig.json` created successfully");
279
- }
280
- }
281
- if (selectedEditors.length > 0) {
282
- const settingUpEditorConfig = spinner();
283
- settingUpEditorConfig.start("Setting up editor config...");
284
- if (selectedEditors.includes("vscode")) {
285
- const settingUpVSCodeConfig = spinner();
286
- settingUpVSCodeConfig.start("Setting up VSCode config...");
287
- if (await vscode.exists()) {
288
- settingUpVSCodeConfig.message("VSCode settings found, updating...");
289
- yield* vscode.update();
290
- settingUpVSCodeConfig.stop("VSCode settings updated with Adamantite preset");
291
- } else {
292
- settingUpVSCodeConfig.message("VSCode settings not found, creating...");
293
- yield* vscode.create();
294
- settingUpVSCodeConfig.stop("VSCode settings created with Adamantite preset");
295
- }
296
- }
297
- if (selectedEditors.includes("zed")) log.warning("Zed configuration coming soon...");
298
- settingUpEditorConfig.stop("Editor config set up successfully");
299
- }
300
- return ok();
301
- });
302
- if (result.isOk()) {
303
- outro("💠 Adamantite initialized successfully!");
304
- return;
305
- }
306
- if (result.error.tag === "OPERATION_CANCELLED") {
307
- cancel("You've cancelled the initialization process.");
308
- return;
309
- }
310
- log.error(result.error.message);
311
- cancel("Failed to initialize Adamantite");
312
- process$1.exit(1);
313
- }
314
- });
315
-
316
- //#endregion
317
- //#region src/commands/monorepo.ts
318
- var monorepo_default = defineCommand({
319
- command: "monorepo",
320
- describe: "Lint and automatically fix monorepo-specific issues using Sherif",
321
- builder: (yargs$1) => yargs$1,
322
- handler: async () => {
323
- if ((await safeTry(async function* () {
324
- yield* runCommand(dlxCommand(yield* getPackageManagerName(), sherif.name, { args: ["--fix"] }), { stdio: "inherit" });
325
- return ok(void 0);
326
- })).isOk()) return;
327
- process$1.exit(1);
328
- }
329
- });
330
-
331
- //#endregion
332
- //#region src/commands/update.ts
333
- var update_default = defineCommand({
334
- command: "update",
335
- describe: "Update adamantite dependencies to latest compatible versions",
336
- builder: (yargs$1) => yargs$1,
337
- handler: async () => {
338
- intro(getTitle());
339
- const result = await safeTry(async function* () {
340
- const packageJson = yield* readPackageJson();
341
- const updates = [];
342
- for (const pkg of [biome, sherif]) {
343
- const dependency = packageJson.devDependencies?.[pkg.name];
344
- if (dependency && dependency !== pkg.version) updates.push({
345
- name: pkg.name,
346
- currentVersion: dependency,
347
- targetVersion: pkg.version,
348
- isDevDependency: true
349
- });
350
- }
351
- if (updates.length === 0) {
352
- log.success("All adamantite dependencies are already up to date!");
353
- return ok("no-updates");
354
- }
355
- log.message("The following dependencies will be updated:");
356
- log.message("");
357
- for (const dep of updates) log.message(` ${dep.name}: ${dep.currentVersion} → ${dep.targetVersion}`);
358
- log.message("");
359
- if (!(yield* fromSafePromise(confirm({ message: "Do you want to proceed with these updates?" })).andThen((r) => isCancel(r) ? err(Fault.create("OPERATION_CANCELLED")) : ok(r)))) return ok("cancelled");
360
- const s = spinner();
361
- s.start("Updating dependencies...");
362
- for (const dep of updates) yield* fromPromise(addDevDependency(`${dep.name}@${dep.targetVersion}`), (error) => Fault.wrap(error).withTag("FAILED_TO_INSTALL_DEPENDENCY").withMessage(`Failed to update ${dep.name}`));
363
- s.stop("Dependencies updated successfully");
364
- return ok("updated");
365
- });
366
- if (result.isOk()) {
367
- if (result.value === "no-updates") outro("💠 No updates needed");
368
- else if (result.value === "cancelled") outro("💠 Update cancelled");
369
- else if (result.value === "updated") outro("💠 Dependencies updated successfully!");
370
- return;
371
- }
372
- if (result.error.tag === "OPERATION_CANCELLED") {
373
- cancel("You've cancelled the update process.");
374
- return;
375
- }
376
- log.error(result.error.message);
377
- cancel("Failed to update dependencies");
378
- process$1.exit(1);
379
- }
380
- });
381
-
382
- //#endregion
383
- //#region src/version.ts
384
- function getPackageVersion() {
385
- return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version;
386
- }
387
- const version = getPackageVersion();
388
- var version_default = version;
389
-
390
- //#endregion
391
- //#region src/index.ts
392
- yargs(hideBin(process.argv)).scriptName("adamantite").version(version_default).command(check_default).command(ci_default).command(fix_default).command(init_default).command(monorepo_default).command(update_default).demandCommand(1).strict().help().parse();
393
-
394
- //#endregion
395
- export { };