adamantite 0.13.2 → 0.14.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/README.md +1 -1
- package/bin/adamantite +1 -1
- package/dist/index.mjs +248 -325
- package/package.json +9 -7
- package/{src/presets → presets}/biome.jsonc +4 -4
- /package/{src/presets → presets}/tsconfig.json +0 -0
package/README.md
CHANGED
|
@@ -165,7 +165,7 @@ Adamantite's Biome preset includes:
|
|
|
165
165
|
- React/JSX patterns
|
|
166
166
|
- **File Patterns**: Pre-configured for TypeScript, JavaScript, JSON, and more
|
|
167
167
|
|
|
168
|
-
### TypeScript Configuration ([presets/tsconfig.json](./
|
|
168
|
+
### TypeScript Configuration ([presets/tsconfig.json](./presets/tsconfig.json))
|
|
169
169
|
|
|
170
170
|
The TypeScript preset includes strict settings for maximum type safety:
|
|
171
171
|
|
package/bin/adamantite
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import yargs from "yargs";
|
|
2
2
|
import { hideBin } from "yargs/helpers";
|
|
3
|
-
import
|
|
3
|
+
import process$1 from "process";
|
|
4
|
+
import { err, fromPromise, fromSafePromise, fromThrowable, ok, safeTry } from "neverthrow";
|
|
4
5
|
import { addDevDependency, detectPackageManager, dlxCommand } from "nypm";
|
|
5
6
|
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
6
7
|
import { join } from "path";
|
|
8
|
+
import { Fault } from "faultier";
|
|
9
|
+
import { execSync } from "child_process";
|
|
7
10
|
import defu from "defu";
|
|
8
11
|
import { parse } from "jsonc-parser";
|
|
9
|
-
import process$1 from "process";
|
|
10
12
|
import { cancel, confirm, intro, isCancel, log, multiselect, outro, spinner } from "@clack/prompts";
|
|
11
13
|
import { readFileSync } from "fs";
|
|
12
14
|
|
|
@@ -14,51 +16,20 @@ import { readFileSync } from "fs";
|
|
|
14
16
|
function defineCommand(input) {
|
|
15
17
|
return input;
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (!result)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
await access(path);
|
|
33
|
-
return true;
|
|
34
|
-
} catch {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Reads and parses package.json with proper typing
|
|
40
|
-
*/
|
|
41
|
-
async function readPackageJson(cwd = process$1.cwd()) {
|
|
42
|
-
const currentPath = join(cwd, "package.json");
|
|
43
|
-
if (!await checkIfExists(currentPath)) throw new Error("package.json not found in the current directory");
|
|
44
|
-
try {
|
|
45
|
-
const content = await readFile(currentPath, "utf-8");
|
|
46
|
-
return JSON.parse(content);
|
|
47
|
-
} catch (error) {
|
|
48
|
-
throw new Error(`Failed to parse package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Writes package.json with proper formatting
|
|
53
|
-
*/
|
|
54
|
-
async function writePackageJson(packageJson, cwd = process$1.cwd()) {
|
|
55
|
-
const currentPath = join(cwd, "package.json");
|
|
56
|
-
try {
|
|
57
|
-
await writeFile(currentPath, JSON.stringify(packageJson, null, 2));
|
|
58
|
-
} catch (error) {
|
|
59
|
-
throw new Error(`Failed to write package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
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));
|
|
62
33
|
function getTitle() {
|
|
63
34
|
if ((process$1.stdout.columns || 80) >= 120) return `
|
|
64
35
|
█████ █████ ███ █████
|
|
@@ -78,96 +49,68 @@ function getTitle() {
|
|
|
78
49
|
}
|
|
79
50
|
|
|
80
51
|
//#endregion
|
|
81
|
-
//#region src/
|
|
82
|
-
const tsconfig = {
|
|
83
|
-
name: "tsconfig",
|
|
84
|
-
config: { extends: "adamantite/tsconfig" },
|
|
85
|
-
async exists() {
|
|
86
|
-
return await checkIfExists(join(process.cwd(), "tsconfig.json"));
|
|
87
|
-
},
|
|
88
|
-
async create() {
|
|
89
|
-
await writeFile(join(process.cwd(), "tsconfig.json"), JSON.stringify(this.config, null, 2));
|
|
90
|
-
},
|
|
91
|
-
async update() {
|
|
92
|
-
const existingConfig = parse(await readFile(join(process.cwd(), "tsconfig.json"), "utf-8"));
|
|
93
|
-
const newConfig = defu(this.config, existingConfig);
|
|
94
|
-
await writeFile(join(process.cwd(), "tsconfig.json"), JSON.stringify(newConfig, null, 2));
|
|
95
|
-
}
|
|
96
|
-
};
|
|
52
|
+
//#region src/helpers/packages/biome.ts
|
|
97
53
|
const biome = {
|
|
98
54
|
name: "@biomejs/biome",
|
|
99
55
|
version: "2.3.10",
|
|
100
56
|
config: { $schema: "./node_modules/@biomejs/biome/configuration_schema.json" },
|
|
101
|
-
async
|
|
102
|
-
|
|
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 };
|
|
103
61
|
},
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
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 };
|
|
112
72
|
if (!Array.isArray(newConfig.extends)) newConfig.extends = newConfig.extends ? [newConfig.extends] : [];
|
|
113
73
|
if (!newConfig.extends.includes("adamantite")) newConfig.extends.push("adamantite");
|
|
114
|
-
const mergedConfig =
|
|
115
|
-
|
|
116
|
-
|
|
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
|
+
})
|
|
117
79
|
};
|
|
118
|
-
const vscode = {
|
|
119
|
-
name: ".vscode",
|
|
120
|
-
config: {
|
|
121
|
-
"typescript.tsdk": "node_modules/typescript/lib",
|
|
122
|
-
"editor.formatOnSave": true,
|
|
123
|
-
"editor.formatOnPaste": true,
|
|
124
|
-
"editor.codeActionsOnSave": {
|
|
125
|
-
"source.organizeImports.biome": "explicit",
|
|
126
|
-
"source.fixAll.biome": "explicit"
|
|
127
|
-
},
|
|
128
|
-
"[javascript][typescript][javascriptreact][typescriptreact][json][jsonc][css][graphql]": { "editor.defaultFormatter": "biomejs.biome" }
|
|
129
|
-
},
|
|
130
|
-
async exists() {
|
|
131
|
-
return await checkIfExists(join(process.cwd(), ".vscode", "settings.json"));
|
|
132
|
-
},
|
|
133
|
-
async create() {
|
|
134
|
-
const vscodePath = join(process.cwd(), ".vscode");
|
|
135
|
-
await mkdir(vscodePath, { recursive: true });
|
|
136
|
-
await writeFile(join(vscodePath, "settings.json"), JSON.stringify(this.config, null, 2));
|
|
137
|
-
},
|
|
138
|
-
async update() {
|
|
139
|
-
const existingConfig = parse(await readFile(join(process.cwd(), ".vscode", "settings.json"), "utf-8"));
|
|
140
|
-
const newConfig = defu(this.config, existingConfig);
|
|
141
|
-
await writeFile(join(process.cwd(), ".vscode", "settings.json"), JSON.stringify(newConfig, null, 2));
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
const sherif = { version: "1.9.0" };
|
|
145
80
|
|
|
146
81
|
//#endregion
|
|
147
82
|
//#region src/commands/check.ts
|
|
148
83
|
var check_default = defineCommand({
|
|
149
|
-
command: "check",
|
|
84
|
+
command: "check [files..]",
|
|
150
85
|
describe: "Run Biome linter and check files for issues",
|
|
151
86
|
builder: (yargs$1) => yargs$1.positional("files", {
|
|
152
87
|
describe: "Specific files to lint (optional)",
|
|
153
|
-
type: "string"
|
|
88
|
+
type: "string",
|
|
89
|
+
array: true
|
|
154
90
|
}).option("summary", {
|
|
155
91
|
type: "boolean",
|
|
156
92
|
description: "Show summary of lint results"
|
|
157
93
|
}),
|
|
158
94
|
handler: async (argv) => {
|
|
159
|
-
|
|
160
|
-
const packageManager =
|
|
95
|
+
if ((await safeTry(async function* () {
|
|
96
|
+
const packageManager = yield* getPackageManagerName();
|
|
161
97
|
const args = ["check"];
|
|
162
98
|
if (argv.summary) args.push("--reporter", "summary");
|
|
163
99
|
if (argv.files && argv.files.length > 0) args.push(...argv.files);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
100
|
+
yield* runCommand(dlxCommand(packageManager, biome.name, { args }), { stdio: "inherit" });
|
|
101
|
+
return ok(void 0);
|
|
102
|
+
})).isOk()) return;
|
|
103
|
+
process$1.exit(1);
|
|
168
104
|
}
|
|
169
105
|
});
|
|
170
106
|
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/helpers/packages/sherif.ts
|
|
109
|
+
const sherif = {
|
|
110
|
+
name: "sherif",
|
|
111
|
+
version: "1.9.0"
|
|
112
|
+
};
|
|
113
|
+
|
|
171
114
|
//#endregion
|
|
172
115
|
//#region src/commands/ci.ts
|
|
173
116
|
var ci_default = defineCommand({
|
|
@@ -181,174 +124,192 @@ var ci_default = defineCommand({
|
|
|
181
124
|
description: "Use GitHub reporter"
|
|
182
125
|
}),
|
|
183
126
|
handler: async (argv) => {
|
|
184
|
-
|
|
185
|
-
const packageManager =
|
|
127
|
+
if ((await safeTry(async function* () {
|
|
128
|
+
const packageManager = yield* getPackageManagerName();
|
|
186
129
|
const tools = [{
|
|
187
|
-
package:
|
|
130
|
+
package: biome.name,
|
|
188
131
|
args: ["ci", ...argv.github ? ["--reporter", "github"] : []]
|
|
189
|
-
}
|
|
190
|
-
|
|
132
|
+
}];
|
|
133
|
+
if (argv.monorepo) tools.push({
|
|
134
|
+
package: sherif.name,
|
|
191
135
|
args: []
|
|
192
|
-
}
|
|
193
|
-
for (const tool of tools)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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);
|
|
197
141
|
}
|
|
198
142
|
});
|
|
199
143
|
|
|
200
144
|
//#endregion
|
|
201
145
|
//#region src/commands/fix.ts
|
|
202
146
|
var fix_default = defineCommand({
|
|
203
|
-
command: "fix",
|
|
147
|
+
command: "fix [files..]",
|
|
204
148
|
describe: "Run Biome linter and fix issues in files",
|
|
205
149
|
builder: (yargs$1) => yargs$1.positional("files", {
|
|
206
150
|
describe: "Specific files to fix (optional)",
|
|
207
|
-
type: "string"
|
|
151
|
+
type: "string",
|
|
152
|
+
array: true
|
|
208
153
|
}).option("unsafe", {
|
|
209
154
|
type: "boolean",
|
|
210
155
|
description: "Apply unsafe fixes"
|
|
211
156
|
}),
|
|
212
157
|
handler: async (argv) => {
|
|
213
|
-
|
|
214
|
-
const packageManager =
|
|
158
|
+
if ((await safeTry(async function* () {
|
|
159
|
+
const packageManager = yield* getPackageManagerName();
|
|
215
160
|
const args = ["check", "--write"];
|
|
216
161
|
if (argv.unsafe) args.push("--unsafe");
|
|
217
162
|
if (argv.files && argv.files.length > 0) args.push(...argv.files);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
163
|
+
yield* runCommand(dlxCommand(packageManager, biome.name, { args }), { stdio: "inherit" });
|
|
164
|
+
return ok(void 0);
|
|
165
|
+
})).isOk()) return;
|
|
166
|
+
process$1.exit(1);
|
|
222
167
|
}
|
|
223
168
|
});
|
|
224
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
|
+
|
|
225
213
|
//#endregion
|
|
226
214
|
//#region src/commands/init.ts
|
|
227
|
-
async function checkIsMonorepo() {
|
|
228
|
-
if (await checkIfExists(join(process$1.cwd(), "pnpm-workspace.yaml"))) return true;
|
|
229
|
-
try {
|
|
230
|
-
return (await readPackageJson()).workspaces !== void 0;
|
|
231
|
-
} catch {
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
async function setupBiomeConfig() {
|
|
236
|
-
const s = spinner();
|
|
237
|
-
if (await biome.exists()) {
|
|
238
|
-
s.start("Biome config found, updating...");
|
|
239
|
-
await biome.update();
|
|
240
|
-
s.stop("Biome config updated with Adamantite preset");
|
|
241
|
-
} else {
|
|
242
|
-
s.start("Biome config not found, creating...");
|
|
243
|
-
await biome.create();
|
|
244
|
-
s.stop("Biome config created with Adamantite preset");
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
async function setupScripts({ check, fix, monorepo }) {
|
|
248
|
-
const s = spinner();
|
|
249
|
-
s.start("Adding scripts to your `package.json`...");
|
|
250
|
-
try {
|
|
251
|
-
const packageJson = await readPackageJson();
|
|
252
|
-
if (!packageJson.scripts) packageJson.scripts = {};
|
|
253
|
-
if (check) packageJson.scripts["check"] = "adamantite check";
|
|
254
|
-
if (fix) packageJson.scripts["fix"] = "adamantite fix";
|
|
255
|
-
if (monorepo) packageJson.scripts["lint:monorepo"] = "adamantite monorepo";
|
|
256
|
-
await writePackageJson(packageJson);
|
|
257
|
-
s.stop("Scripts added to your `package.json`");
|
|
258
|
-
} catch (error) {
|
|
259
|
-
s.stop("Failed to add scripts");
|
|
260
|
-
throw new Error(`Failed to modify package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
async function setupTsConfig() {
|
|
264
|
-
const s = spinner();
|
|
265
|
-
if (await tsconfig.exists()) {
|
|
266
|
-
s.start("`tsconfig.json` found, updating...");
|
|
267
|
-
await tsconfig.update();
|
|
268
|
-
s.stop("Updated `tsconfig.json` with preset");
|
|
269
|
-
} else {
|
|
270
|
-
s.start("`tsconfig.json` not found, creating...");
|
|
271
|
-
await tsconfig.create();
|
|
272
|
-
s.stop("Created `tsconfig.json` with preset");
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
async function selectEditorConfig() {
|
|
276
|
-
const selected = await multiselect({
|
|
277
|
-
message: "Which editors do you want to configure (recommended)?",
|
|
278
|
-
options: [{
|
|
279
|
-
label: "VSCode / Cursor / Windsurf",
|
|
280
|
-
value: "vscode"
|
|
281
|
-
}, {
|
|
282
|
-
label: "Zed (coming soon)",
|
|
283
|
-
value: "zed"
|
|
284
|
-
}],
|
|
285
|
-
required: false
|
|
286
|
-
});
|
|
287
|
-
if (isCancel(selected)) throw new Error("Operation cancelled");
|
|
288
|
-
return selected;
|
|
289
|
-
}
|
|
290
|
-
async function setupEditorConfig(selectedEditors) {
|
|
291
|
-
if (!selectedEditors || selectedEditors.length === 0) return;
|
|
292
|
-
const s = spinner();
|
|
293
|
-
if (selectedEditors.includes("vscode")) if (await vscode.exists()) {
|
|
294
|
-
s.start("VSCode settings found, updating...");
|
|
295
|
-
await vscode.update();
|
|
296
|
-
s.stop("VSCode settings updated with Adamantite preset");
|
|
297
|
-
} else {
|
|
298
|
-
s.start("VSCode settings not found, creating...");
|
|
299
|
-
await vscode.create();
|
|
300
|
-
s.stop("VSCode settings created with Adamantite preset");
|
|
301
|
-
}
|
|
302
|
-
if (selectedEditors.includes("zed")) {
|
|
303
|
-
s.start("Zed configuration coming soon...");
|
|
304
|
-
s.stop("Zed configuration coming soon...");
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
async function confirmAction(message) {
|
|
308
|
-
const result = await confirm({ message });
|
|
309
|
-
if (isCancel(result)) throw new Error("Operation cancelled");
|
|
310
|
-
return result;
|
|
311
|
-
}
|
|
312
|
-
async function installDependencies(options) {
|
|
313
|
-
const s = spinner();
|
|
314
|
-
s.start("Installing dependencies...");
|
|
315
|
-
try {
|
|
316
|
-
await addDevDependency("adamantite");
|
|
317
|
-
const biomeVersion = biome.version;
|
|
318
|
-
await addDevDependency(`@biomejs/biome@${biomeVersion}`);
|
|
319
|
-
if (options?.monorepo) await addDevDependency(`sherif@${sherif.version}`);
|
|
320
|
-
s.stop("Dependencies installed successfully");
|
|
321
|
-
} catch (error) {
|
|
322
|
-
s.stop("Failed to install dependencies");
|
|
323
|
-
throw new Error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
215
|
var init_default = defineCommand({
|
|
327
216
|
command: "init",
|
|
328
217
|
describe: "Initialize Adamantite in the current directory",
|
|
329
218
|
builder: (yargs$1) => yargs$1,
|
|
330
219
|
handler: async () => {
|
|
331
220
|
intro(getTitle());
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
const
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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()) {
|
|
347
303
|
outro("💠 Adamantite initialized successfully!");
|
|
348
|
-
|
|
349
|
-
log.error(`${error instanceof Error ? error.message : "Unknown error"}`);
|
|
350
|
-
cancel("Failed to initialize Adamantite");
|
|
304
|
+
return;
|
|
351
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);
|
|
352
313
|
}
|
|
353
314
|
});
|
|
354
315
|
|
|
@@ -359,100 +320,62 @@ var monorepo_default = defineCommand({
|
|
|
359
320
|
describe: "Lint and automatically fix monorepo-specific issues using Sherif",
|
|
360
321
|
builder: (yargs$1) => yargs$1,
|
|
361
322
|
handler: async () => {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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);
|
|
367
328
|
}
|
|
368
329
|
});
|
|
369
330
|
|
|
370
331
|
//#endregion
|
|
371
332
|
//#region src/commands/update.ts
|
|
372
|
-
async function detectUpdatesNeeded() {
|
|
373
|
-
const updates = [];
|
|
374
|
-
try {
|
|
375
|
-
const packageJson = await readPackageJson();
|
|
376
|
-
const biomeDep = packageJson.devDependencies?.["@biomejs/biome"];
|
|
377
|
-
if (biomeDep && biomeDep !== biome.version) updates.push({
|
|
378
|
-
name: "@biomejs/biome",
|
|
379
|
-
currentVersion: biomeDep,
|
|
380
|
-
targetVersion: biome.version,
|
|
381
|
-
isDevDependency: true
|
|
382
|
-
});
|
|
383
|
-
const sherifDep = packageJson.devDependencies?.sherif;
|
|
384
|
-
if (sherifDep && sherifDep !== sherif.version) updates.push({
|
|
385
|
-
name: "sherif",
|
|
386
|
-
currentVersion: sherifDep,
|
|
387
|
-
targetVersion: sherif.version,
|
|
388
|
-
isDevDependency: true
|
|
389
|
-
});
|
|
390
|
-
return updates;
|
|
391
|
-
} catch (error) {
|
|
392
|
-
throw new Error(`Failed to read package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
async function updateDependencies(updates) {
|
|
396
|
-
const s = spinner();
|
|
397
|
-
s.start("Updating dependencies...");
|
|
398
|
-
try {
|
|
399
|
-
const tasks = updates.map((dep) => addDevDependency(`${dep.name}@${dep.targetVersion}`));
|
|
400
|
-
const results = await Promise.allSettled(tasks);
|
|
401
|
-
const failures = [];
|
|
402
|
-
const successes = [];
|
|
403
|
-
for (const [index, result] of results.entries()) {
|
|
404
|
-
const dep = updates[index];
|
|
405
|
-
if (!dep) continue;
|
|
406
|
-
const depName = dep.name;
|
|
407
|
-
if (result.status === "fulfilled") successes.push(depName);
|
|
408
|
-
else failures.push(`${depName}: ${result.reason?.message || "Unknown error"}`);
|
|
409
|
-
}
|
|
410
|
-
if (failures.length === 0) s.stop("Dependencies updated successfully");
|
|
411
|
-
else if (successes.length === 0) {
|
|
412
|
-
s.stop("Failed to update dependencies");
|
|
413
|
-
throw new Error(`All dependency updates failed:\n${failures.join("\n")}`);
|
|
414
|
-
} else {
|
|
415
|
-
s.stop("Partial update completed");
|
|
416
|
-
log.warn("Some dependencies failed to update:");
|
|
417
|
-
for (const failure of failures) log.warn(` ${failure}`);
|
|
418
|
-
log.success(`Successfully updated: ${successes.join(", ")}`);
|
|
419
|
-
}
|
|
420
|
-
} catch (error) {
|
|
421
|
-
s.stop("Failed to update dependencies");
|
|
422
|
-
throw error;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
async function confirmUpdate(updates) {
|
|
426
|
-
log.message("The following dependencies will be updated:");
|
|
427
|
-
log.message("");
|
|
428
|
-
for (const dep of updates) log.message(` ${dep.name}: ${dep.currentVersion} → ${dep.targetVersion}`);
|
|
429
|
-
log.message("");
|
|
430
|
-
const result = await confirm({ message: "Do you want to proceed with these updates?" });
|
|
431
|
-
if (isCancel(result)) throw new Error("Operation cancelled");
|
|
432
|
-
return result;
|
|
433
|
-
}
|
|
434
333
|
var update_default = defineCommand({
|
|
435
334
|
command: "update",
|
|
436
335
|
describe: "Update adamantite dependencies to latest compatible versions",
|
|
437
336
|
builder: (yargs$1) => yargs$1,
|
|
438
337
|
handler: async () => {
|
|
439
338
|
intro(getTitle());
|
|
440
|
-
|
|
441
|
-
const
|
|
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
|
+
}
|
|
442
351
|
if (updates.length === 0) {
|
|
443
352
|
log.success("All adamantite dependencies are already up to date!");
|
|
444
|
-
|
|
445
|
-
return;
|
|
353
|
+
return ok("no-updates");
|
|
446
354
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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;
|
|
455
375
|
}
|
|
376
|
+
log.error(result.error.message);
|
|
377
|
+
cancel("Failed to update dependencies");
|
|
378
|
+
process$1.exit(1);
|
|
456
379
|
}
|
|
457
380
|
});
|
|
458
381
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adamantite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "An strict and opinionated set of presets for modern TypeScript applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adamantite",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "Adel Rodriguez <hello@adelrodriguez.com>",
|
|
23
23
|
"type": "module",
|
|
24
|
-
"main": "
|
|
24
|
+
"main": "presets/biome.jsonc",
|
|
25
25
|
"bin": {
|
|
26
26
|
"adamantite": "bin/adamantite"
|
|
27
27
|
},
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
"#*": "./src/*"
|
|
30
30
|
},
|
|
31
31
|
"exports": {
|
|
32
|
-
".": "./
|
|
33
|
-
"./biome": "./
|
|
34
|
-
"./tsconfig": "./
|
|
35
|
-
"./presets/*": "./
|
|
32
|
+
".": "./presets/biome.jsonc",
|
|
33
|
+
"./biome": "./presets/biome.jsonc",
|
|
34
|
+
"./tsconfig": "./presets/tsconfig.json",
|
|
35
|
+
"./presets/*": "./presets/*"
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"bin",
|
|
39
39
|
"dist",
|
|
40
|
-
"
|
|
40
|
+
"presets"
|
|
41
41
|
],
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "tsdown",
|
|
@@ -54,7 +54,9 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@clack/prompts": "0.11.0",
|
|
56
56
|
"defu": "6.1.4",
|
|
57
|
+
"faultier": "^1.0.3",
|
|
57
58
|
"jsonc-parser": "3.3.1",
|
|
59
|
+
"neverthrow": "8.2.0",
|
|
58
60
|
"nypm": "0.6.2",
|
|
59
61
|
"yargs": "18.0.0"
|
|
60
62
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
2
|
+
"$schema": "../node_modules/@biomejs/biome/configuration_schema.json",
|
|
3
3
|
"root": false,
|
|
4
4
|
// ---------------------------- FORMATTER -----------------------------
|
|
5
5
|
// These are the generic settings that apply to all files in the project.
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// Use the system line ending.
|
|
16
16
|
"lineEnding": "auto",
|
|
17
17
|
// The expected line width for most editors.
|
|
18
|
-
"lineWidth":
|
|
18
|
+
"lineWidth": 100,
|
|
19
19
|
// Don't force attributes to be on the same line as the element.
|
|
20
20
|
"attributePosition": "auto",
|
|
21
21
|
"bracketSpacing": true
|
|
@@ -103,9 +103,9 @@
|
|
|
103
103
|
"noEmptyTypeParameters": "error",
|
|
104
104
|
"noExtraBooleanCast": "error",
|
|
105
105
|
"noExcessiveCognitiveComplexity": {
|
|
106
|
-
"level": "
|
|
106
|
+
"level": "warn",
|
|
107
107
|
"options": {
|
|
108
|
-
"maxAllowedComplexity":
|
|
108
|
+
"maxAllowedComplexity": 40
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
111
|
"noExcessiveNestedTestSuites": "error",
|
|
File without changes
|