adamantite 0.13.1 → 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 +395 -0
- package/package.json +15 -9
- package/{src/presets → presets}/biome.jsonc +4 -4
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -16
- /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
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
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 { };
|
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,20 +21,23 @@
|
|
|
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
|
},
|
|
28
|
+
"imports": {
|
|
29
|
+
"#*": "./src/*"
|
|
30
|
+
},
|
|
28
31
|
"exports": {
|
|
29
|
-
".": "./
|
|
30
|
-
"./biome": "./
|
|
31
|
-
"./tsconfig": "./
|
|
32
|
-
"./presets/*": "./
|
|
32
|
+
".": "./presets/biome.jsonc",
|
|
33
|
+
"./biome": "./presets/biome.jsonc",
|
|
34
|
+
"./tsconfig": "./presets/tsconfig.json",
|
|
35
|
+
"./presets/*": "./presets/*"
|
|
33
36
|
},
|
|
34
37
|
"files": [
|
|
35
38
|
"bin",
|
|
36
39
|
"dist",
|
|
37
|
-
"
|
|
40
|
+
"presets"
|
|
38
41
|
],
|
|
39
42
|
"scripts": {
|
|
40
43
|
"build": "tsdown",
|
|
@@ -50,15 +53,18 @@
|
|
|
50
53
|
},
|
|
51
54
|
"dependencies": {
|
|
52
55
|
"@clack/prompts": "0.11.0",
|
|
53
|
-
"citty": "0.1.6",
|
|
54
56
|
"defu": "6.1.4",
|
|
57
|
+
"faultier": "^1.0.3",
|
|
55
58
|
"jsonc-parser": "3.3.1",
|
|
56
|
-
"
|
|
59
|
+
"neverthrow": "8.2.0",
|
|
60
|
+
"nypm": "0.6.2",
|
|
61
|
+
"yargs": "18.0.0"
|
|
57
62
|
},
|
|
58
63
|
"devDependencies": {
|
|
59
64
|
"@biomejs/biome": "2.3.10",
|
|
60
65
|
"@changesets/cli": "2.29.8",
|
|
61
66
|
"@types/bun": "1.3.5",
|
|
67
|
+
"@types/yargs": "17.0.35",
|
|
62
68
|
"sherif": "1.9.0",
|
|
63
69
|
"tsdown": "0.18.1",
|
|
64
70
|
"type-fest": "5.3.1",
|
|
@@ -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",
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|
package/dist/index.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import{defineCommand as e,runMain as t}from"citty";import{execSync as n}from"child_process";import{addDevDependency as r,detectPackageManager as i,dlxCommand as a}from"nypm";import{access as o,mkdir as s,readFile as c,writeFile as l}from"fs/promises";import{join as u}from"path";import d from"process";import{cancel as f,confirm as p,intro as m,isCancel as h,log as g,multiselect as _,outro as v,spinner as y}from"@clack/prompts";import b from"defu";import{parse as x}from"jsonc-parser";import{readFileSync as S}from"fs";async function C(){let e=await i(d.cwd());if(!e)throw Error(`No package manager found`);let{warnings:t,...n}=e;return t&&t.length>0&&console.warn(t.join(`
|
|
2
|
-
`)),n.name}function w(e){let t=e instanceof Error?e.message:`An unknown error occurred`;console.error(t),f(`Failed to run Adamantite`),d.exit(1)}async function T(e){try{return await o(e),!0}catch{return!1}}async function E(e=d.cwd()){let t=u(e,`package.json`);if(!await T(t))throw Error(`package.json not found in the current directory`);try{let e=await c(t,`utf-8`);return JSON.parse(e)}catch(e){throw Error(`Failed to parse package.json: ${e instanceof Error?e.message:`Unknown error`}`)}}async function D(e,t=d.cwd()){let n=u(t,`package.json`);try{await l(n,JSON.stringify(e,null,2))}catch(e){throw Error(`Failed to write package.json: ${e instanceof Error?e.message:`Unknown error`}`)}}function O(){return(d.stdout.columns||80)>=120?`
|
|
3
|
-
█████ █████ ███ █████
|
|
4
|
-
░░███ ░░███ ░░░ ░░███
|
|
5
|
-
██████ ███████ ██████ █████████████ ██████ ████████ ███████ ████ ███████ ██████
|
|
6
|
-
░░░░░███ ███░░███ ░░░░░███ ░░███░░███░░███ ░░░░░███ ░░███░░███ ░░░███░ ░░███ ░░░███░ ███░░███
|
|
7
|
-
███████ ░███ ░███ ███████ ░███ ░███ ░███ ███████ ░███ ░███ ░███ ░███ ░███ ░███████
|
|
8
|
-
███░░███ ░███ ░███ ███░░███ ░███ ░███ ░███ ███░░███ ░███ ░███ ░███ ███ ░███ ░███ ███░███░░░
|
|
9
|
-
░░████████░░████████░░████████ █████░███ █████░░████████ ████ █████ ░░█████ █████ ░░█████ ░░██████
|
|
10
|
-
░░░░░░░░ ░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░ ░░░░░ ░░░░░░░░ ░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░
|
|
11
|
-
`:`
|
|
12
|
-
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
13
|
-
┃ ADAMANTITE ┃
|
|
14
|
-
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
15
|
-
`}var k=e({meta:{name:`check`,description:`Run Biome linter and check files for issues`},args:{files:{description:`Specific files to lint (optional)`,type:`positional`,required:!1},summary:{description:`Show summary of lint results`,type:`boolean`}},run:async({args:e})=>{try{let t=await C(),r=[`check`];e.summary&&r.push(`--reporter`,`summary`);let i=e._;i.length>0&&r.push(...i),n(a(t,`@biomejs/biome`,{args:r}),{stdio:`inherit`})}catch(e){w(e)}}}),A=e({meta:{name:`ci`,description:`Run Adamantite in a CI environment`},args:{monorepo:{description:`Run additional monorepo-specific checks`,type:`boolean`},github:{description:`Use GitHub reporter`,type:`boolean`}},run:async({args:e})=>{try{let t=await C(),r=[{package:`@biomejs/biome`,args:[`ci`,...e.github?[`--reporter`,`github`]:[]]},...e.monorepo?[{package:`sherif`,args:[]}]:[]];for(let e of r)n(a(t,e.package,{args:e.args}),{stdio:`inherit`})}catch(e){w(e)}}}),j=e({meta:{name:`fix`,description:`Run Biome linter and fix issues in files`},args:{files:{description:`Specific files to fix (optional)`,type:`positional`,required:!1},unsafe:{description:`Apply unsafe fixes`,type:`boolean`}},run:async({args:e})=>{try{let t=await C(),r=[`check`,`--write`];e.unsafe&&r.push(`--unsafe`);let i=e._;i.length>0&&r.push(...i),n(a(t,`@biomejs/biome`,{args:r}),{stdio:`inherit`})}catch(e){w(e)}}});const M={config:{extends:`adamantite/tsconfig`},async exists(){return await T(u(process.cwd(),`tsconfig.json`))},async create(){await l(u(process.cwd(),`tsconfig.json`),JSON.stringify(this.config,null,2))},async update(){let e=x(await c(u(process.cwd(),`tsconfig.json`),`utf-8`)),t=b(this.config,e);await l(u(process.cwd(),`tsconfig.json`),JSON.stringify(t,null,2))}},N={version:`2.3.10`,config:{$schema:`./node_modules/@biomejs/biome/configuration_schema.json`},async exists(){return await T(u(process.cwd(),`biome.jsonc`))},async create(){await l(u(process.cwd(),`biome.jsonc`),JSON.stringify({...this.config,extends:[`adamantite`]},null,2))},async update(){let e={...x(await c(await T(u(process.cwd(),`biome.jsonc`))?u(process.cwd(),`biome.jsonc`):u(process.cwd(),`biome.json`),`utf-8`))};Array.isArray(e.extends)||(e.extends=e.extends?[e.extends]:[]),e.extends.includes(`adamantite`)||e.extends.push(`adamantite`);let t=b(this.config,e);await l(u(process.cwd(),`biome.jsonc`),JSON.stringify(t,null,2))}},P={config:{"typescript.tsdk":`node_modules/typescript/lib`,"editor.formatOnSave":!0,"editor.formatOnPaste":!0,"editor.codeActionsOnSave":{"source.organizeImports.biome":`explicit`,"source.fixAll.biome":`explicit`},"[javascript][typescript][javascriptreact][typescriptreact][json][jsonc][css][graphql]":{"editor.defaultFormatter":`biomejs.biome`}},async exists(){return await T(u(process.cwd(),`.vscode`,`settings.json`))},async create(){let e=u(process.cwd(),`.vscode`);await s(e,{recursive:!0}),await l(u(e,`settings.json`),JSON.stringify(this.config,null,2))},async update(){let e=x(await c(u(process.cwd(),`.vscode`,`settings.json`),`utf-8`)),t=b(this.config,e);await l(u(process.cwd(),`.vscode`,`settings.json`),JSON.stringify(t,null,2))}},F={version:`1.9.0`};async function I(){if(await T(u(d.cwd(),`pnpm-workspace.yaml`)))return!0;try{return(await E()).workspaces!==void 0}catch{return!1}}async function L(){let e=y();await N.exists()?(e.start(`Biome config found, updating...`),await N.update(),e.stop(`Biome config updated with Adamantite preset`)):(e.start(`Biome config not found, creating...`),await N.create(),e.stop(`Biome config created with Adamantite preset`))}async function R({check:e,fix:t,monorepo:n}){let r=y();r.start("Adding scripts to your `package.json`...");try{let i=await E();i.scripts||={},e&&(i.scripts.check=`adamantite check`),t&&(i.scripts.fix=`adamantite fix`),n&&(i.scripts[`lint:monorepo`]=`adamantite monorepo`),await D(i),r.stop("Scripts added to your `package.json`")}catch(e){throw r.stop(`Failed to add scripts`),Error(`Failed to modify package.json: ${e instanceof Error?e.message:`Unknown error`}`)}}async function z(){let e=y();await M.exists()?(e.start("`tsconfig.json` found, updating..."),await M.update(),e.stop("Updated `tsconfig.json` with preset")):(e.start("`tsconfig.json` not found, creating..."),await M.create(),e.stop("Created `tsconfig.json` with preset"))}async function B(){let e=await _({message:`Which editors do you want to configure (recommended)?`,options:[{label:`VSCode / Cursor / Windsurf`,value:`vscode`},{label:`Zed (coming soon)`,value:`zed`}],required:!1});if(h(e))throw Error(`Operation cancelled`);return e}async function V(e){if(!e||e.length===0)return;let t=y();e.includes(`vscode`)&&(await P.exists()?(t.start(`VSCode settings found, updating...`),await P.update(),t.stop(`VSCode settings updated with Adamantite preset`)):(t.start(`VSCode settings not found, creating...`),await P.create(),t.stop(`VSCode settings created with Adamantite preset`))),e.includes(`zed`)&&(t.start(`Zed configuration coming soon...`),t.stop(`Zed configuration coming soon...`))}async function H(e){let t=await p({message:e});if(h(t))throw Error(`Operation cancelled`);return t}async function U(e){let t=y();t.start(`Installing dependencies...`);try{await r(`adamantite`);let n=N.version;await r(`@biomejs/biome@${n}`),e?.monorepo&&await r(`sherif@${F.version}`),t.stop(`Dependencies installed successfully`)}catch(e){throw t.stop(`Failed to install dependencies`),Error(`Failed to install dependencies: ${e instanceof Error?e.message:`Unknown error`}`)}}var W=e({meta:{name:`init`,description:`Initialize Adamantite in the current directory`},run:async()=>{m(O());try{let e=await I(),t=await H("Do you want to add the `check` and `fix` scripts to your `package.json`?"),n=e?await H(`We've detected a monorepo setup in your project. Would you like to install monorepo linting scripts?`):!1,r=await H(`Adamantite provides a TypeScript preset to enforce strict type-safety. Would you like to install it?`),i=await B();await U({monorepo:n}),await L(),(t||n)&&await R({check:t,fix:t,monorepo:n}),r&&await z(),await V(i),v(`💠 Adamantite initialized successfully!`)}catch(e){g.error(`${e instanceof Error?e.message:`Unknown error`}`),f(`Failed to initialize Adamantite`)}}}),G=e({meta:{name:`monorepo`,description:`Lint and automatically fix monorepo-specific issues using Sherif`},run:async()=>{try{n(a(await C(),`sherif`,{args:[`--fix`]}),{stdio:`inherit`})}catch(e){w(e)}}});async function K(){let e=[];try{let t=await E(),n=t.devDependencies?.[`@biomejs/biome`];n&&n!==N.version&&e.push({name:`@biomejs/biome`,currentVersion:n,targetVersion:N.version,isDevDependency:!0});let r=t.devDependencies?.sherif;return r&&r!==F.version&&e.push({name:`sherif`,currentVersion:r,targetVersion:F.version,isDevDependency:!0}),e}catch(e){throw Error(`Failed to read package.json: ${e instanceof Error?e.message:`Unknown error`}`)}}async function q(e){let t=y();t.start(`Updating dependencies...`);try{let n=e.map(e=>r(`${e.name}@${e.targetVersion}`)),i=await Promise.allSettled(n),a=[],o=[];for(let[t,n]of i.entries()){let r=e[t];if(!r)continue;let i=r.name;n.status===`fulfilled`?o.push(i):a.push(`${i}: ${n.reason?.message||`Unknown error`}`)}if(a.length===0)t.stop(`Dependencies updated successfully`);else if(o.length===0)throw t.stop(`Failed to update dependencies`),Error(`All dependency updates failed:\n${a.join(`
|
|
16
|
-
`)}`);else{t.stop(`Partial update completed`),g.warn(`Some dependencies failed to update:`);for(let e of a)g.warn(` ${e}`);g.success(`Successfully updated: ${o.join(`, `)}`)}}catch(e){throw t.stop(`Failed to update dependencies`),e}}async function J(e){g.message(`The following dependencies will be updated:`),g.message(``);for(let t of e)g.message(` ${t.name}: ${t.currentVersion} → ${t.targetVersion}`);g.message(``);let t=await p({message:`Do you want to proceed with these updates?`});if(h(t))throw Error(`Operation cancelled`);return t}var Y=e({meta:{name:`update`,description:`Update adamantite dependencies to latest compatible versions`},run:async()=>{m(O());try{let e=await K();if(e.length===0){g.success(`All adamantite dependencies are already up to date!`),v(`💠 No updates needed`);return}if(!await J(e)){v(`💠 Update cancelled`);return}await q(e),v(`💠 Dependencies updated successfully!`)}catch(e){w(e)}}});function X(){return JSON.parse(S(u(process.cwd(),`package.json`),`utf-8`)).version}t(e({meta:{name:`adamantite`,description:`An opinionated set of presets for modern TypeScript applications`,version:X()},subCommands:{check:k,ci:A,fix:j,init:W,monorepo:G,update:Y}}));
|
|
File without changes
|