@mochi-css/tsuki 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +10 -0
  2. package/dist/index.js +584 -0
  3. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # 🧁 Mochi-CSS/tsuki
2
+
3
+ This package is part of the [Mochi-CSS project](https://github.com/Niikelion/mochi-css).
4
+ It provides installer for Mochi-CSS that adds it to your project.
5
+
6
+ You can run it with:
7
+
8
+ ```bash
9
+ npx @mochi-css/tsuki
10
+ ```
package/dist/index.js ADDED
@@ -0,0 +1,584 @@
1
+ #!/usr/bin/env node
2
+ //#region rolldown:runtime
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+
24
+ //#endregion
25
+ let commander = require("commander");
26
+ commander = __toESM(commander);
27
+ let __clack_prompts = require("@clack/prompts");
28
+ __clack_prompts = __toESM(__clack_prompts);
29
+ let picocolors = require("picocolors");
30
+ picocolors = __toESM(picocolors);
31
+ let node_readline = require("node:readline");
32
+ node_readline = __toESM(node_readline);
33
+ let node_stream = require("node:stream");
34
+ node_stream = __toESM(node_stream);
35
+ let package_manager_detector = require("package-manager-detector");
36
+ package_manager_detector = __toESM(package_manager_detector);
37
+ let cross_spawn = require("cross-spawn");
38
+ cross_spawn = __toESM(cross_spawn);
39
+ let fs_extra = require("fs-extra");
40
+ fs_extra = __toESM(fs_extra);
41
+ let fs_promises = require("fs/promises");
42
+ fs_promises = __toESM(fs_promises);
43
+ let path = require("path");
44
+ path = __toESM(path);
45
+ let magicast = require("magicast");
46
+ magicast = __toESM(magicast);
47
+
48
+ //#region src/install.ts
49
+ function onceEvent(emitter, event) {
50
+ return new Promise((resolve) => {
51
+ emitter.once(event, (...args) => {
52
+ resolve(args);
53
+ });
54
+ });
55
+ }
56
+ function spawnProcess(command, args, options) {
57
+ return new Promise((resolve, reject) => {
58
+ const child = (0, cross_spawn.default)(command, args, options);
59
+ const onSpawn = () => {
60
+ child.off("error", onError);
61
+ resolve(child);
62
+ };
63
+ const onError = (err) => {
64
+ child.off("spawn", onSpawn);
65
+ reject(err);
66
+ };
67
+ child.once("spawn", onSpawn);
68
+ child.once("error", onError);
69
+ });
70
+ }
71
+ async function runInstall(title, command, args, packages) {
72
+ const log = __clack_prompts.taskLog({ title });
73
+ log.message(`${command} ${args.join(" ")}`);
74
+ try {
75
+ const child = await spawnProcess(command, args, { stdio: [
76
+ "inherit",
77
+ "pipe",
78
+ "pipe"
79
+ ] });
80
+ const merged = new node_stream.PassThrough();
81
+ let openStreams = 0;
82
+ for (const stream of [child.stdout, child.stderr]) {
83
+ if (!stream) continue;
84
+ openStreams++;
85
+ stream.pipe(merged, { end: false });
86
+ stream.on("end", () => {
87
+ if (--openStreams === 0) merged.end();
88
+ });
89
+ }
90
+ const rl = (0, node_readline.createInterface)({
91
+ input: merged,
92
+ crlfDelay: Infinity
93
+ });
94
+ const drain = (async () => {
95
+ for await (const line of rl) log.message(line);
96
+ })();
97
+ const [code] = await onceEvent(child, "close");
98
+ await drain;
99
+ if (code !== 0) throw new Error(`Failed to install packages: ${packages.join(", ")}`);
100
+ log.success(`${packages.join(", ")} has been installed installed!`);
101
+ } catch (err) {
102
+ log.error(err instanceof Error ? err.message : String(err));
103
+ throw err;
104
+ }
105
+ }
106
+ async function installPackages(packages) {
107
+ if (packages.length === 0) return;
108
+ const packageManager = await (0, package_manager_detector.detect)({ strategies: [
109
+ "packageManager-field",
110
+ "devEngines-field",
111
+ "lockfile",
112
+ "install-metadata"
113
+ ] });
114
+ if (packageManager === null) throw new Error("Could not determine package manager of the project");
115
+ const agent = packageManager.agent;
116
+ const devFlag = agent === "deno" ? "--dev" : "-D";
117
+ const devPackages = packages.filter((pkg) => pkg.dev !== false).map((pkg) => pkg.name);
118
+ const prodPackages = packages.filter((pkg) => pkg.dev === false).map((pkg) => pkg.name);
119
+ const packageList = [...devPackages.map((name) => `${name} (dev)`), ...prodPackages.map((name) => name)].join(", ");
120
+ const confirmed = await __clack_prompts.confirm({ message: `Install the following packages: ${packageList}?` });
121
+ if (__clack_prompts.isCancel(confirmed) || !confirmed) {
122
+ __clack_prompts.log.info("Skipping package installation");
123
+ return;
124
+ }
125
+ if (devPackages.length > 0) {
126
+ const cmd = (0, package_manager_detector.resolveCommand)(agent, "add", [devFlag, ...devPackages]);
127
+ if (cmd === null) throw new Error("Could not prepare install command");
128
+ await runInstall(`Installing dev dependencies: ${devPackages.join(", ")}`, cmd.command, cmd.args, devPackages);
129
+ }
130
+ if (prodPackages.length > 0) {
131
+ const cmd = (0, package_manager_detector.resolveCommand)(agent, "add", prodPackages);
132
+ if (cmd === null) throw new Error("Could not prepare install command");
133
+ await runInstall(`Installing dependencies: ${prodPackages.join(", ")}`, cmd.command, cmd.args, prodPackages);
134
+ }
135
+ }
136
+
137
+ //#endregion
138
+ //#region src/runner.ts
139
+ var ModuleRunner = class {
140
+ packages = [];
141
+ modules = [];
142
+ register(module$1) {
143
+ this.modules.push(module$1);
144
+ return this;
145
+ }
146
+ async run() {
147
+ const ctx = {
148
+ requirePackage: (name, dev = true) => {
149
+ this.packages.push({
150
+ name,
151
+ dev
152
+ });
153
+ },
154
+ requirePackages: (packages) => {
155
+ for (const pkg of packages) this.packages.push({
156
+ name: pkg.name,
157
+ dev: pkg.dev ?? true
158
+ });
159
+ }
160
+ };
161
+ for (const module$1 of this.modules) await module$1.run(ctx);
162
+ if (this.packages.length > 0) await installPackages(this.packages);
163
+ }
164
+ };
165
+
166
+ //#endregion
167
+ //#region src/modules/ast.ts
168
+ function getPropKeyName(prop) {
169
+ const key = prop["key"];
170
+ if (typeof key["name"] === "string") return key["name"];
171
+ if (typeof key["value"] === "string") return key["value"];
172
+ }
173
+ function optionsToAstProperties(options) {
174
+ return Object.entries(options).map(([key, value]) => ({
175
+ type: "ObjectProperty",
176
+ key: {
177
+ type: "Identifier",
178
+ name: key
179
+ },
180
+ value: typeof value === "string" ? {
181
+ type: "StringLiteral",
182
+ value
183
+ } : typeof value === "number" ? {
184
+ type: "NumericLiteral",
185
+ value
186
+ } : {
187
+ type: "BooleanLiteral",
188
+ value
189
+ },
190
+ computed: false,
191
+ shorthand: false
192
+ }));
193
+ }
194
+
195
+ //#endregion
196
+ //#region src/modules/postcss.ts
197
+ const postcssConfigNames = [
198
+ "postcss.config.mts",
199
+ "postcss.config.ts",
200
+ "postcss.config.mjs",
201
+ "postcss.config.js",
202
+ "postcss.config.cjs",
203
+ ".postcssrc.mts",
204
+ ".postcssrc.ts",
205
+ ".postcssrc.mjs",
206
+ ".postcssrc.js",
207
+ ".postcssrc.cjs",
208
+ ".postcssrc.json",
209
+ ".postcssrc.yml",
210
+ ".postcssrc.yaml",
211
+ ".postcssrc"
212
+ ];
213
+ function findPostcssConfig() {
214
+ return postcssConfigNames.find((name) => fs_extra.default.existsSync(name));
215
+ }
216
+ function defaultPostcssConfig(pluginOptions = {}) {
217
+ const entries = Object.entries(pluginOptions);
218
+ return `export default {\n plugins: {\n "@mochi-css/postcss": ${entries.length === 0 ? "{}" : `{\n${entries.map(([k, v]) => ` ${k}: ${JSON.stringify(v)}`).join(",\n")}\n }`}\n }\n}\n`;
219
+ }
220
+ async function askForPath() {
221
+ const defaultConfig = findPostcssConfig() ?? "postcss.config.js";
222
+ const configPath = await __clack_prompts.text({
223
+ message: "Path to PostCSS config",
224
+ placeholder: defaultConfig,
225
+ defaultValue: defaultConfig
226
+ });
227
+ if (__clack_prompts.isCancel(configPath)) return false;
228
+ return configPath;
229
+ }
230
+ function isProxy(v) {
231
+ return v !== null && typeof v === "object" && typeof v["$ast"] === "object";
232
+ }
233
+ function isObject(v) {
234
+ return v !== null && typeof v === "object";
235
+ }
236
+ function addPluginToNamedVar(mod, varName, pluginName, pluginOptions, configPath) {
237
+ const body = mod.$ast.body;
238
+ for (const stmt of body) {
239
+ if (stmt.type !== "VariableDeclaration") continue;
240
+ for (const decl of stmt.declarations) {
241
+ if (decl.id.type !== "Identifier" || decl.id.name !== varName) continue;
242
+ const init = decl.init;
243
+ if (!init) throw new Error(`Failed to add postcss plugin to ${configPath}`);
244
+ const pluginsProp = init.properties.find((prop) => getPropKeyName(prop) === "plugins");
245
+ if (!pluginsProp) throw new Error(`Failed to find plugins object in ${configPath}`);
246
+ pluginsProp.value.properties.push({
247
+ type: "ObjectProperty",
248
+ key: {
249
+ type: "StringLiteral",
250
+ value: pluginName
251
+ },
252
+ value: {
253
+ type: "ObjectExpression",
254
+ properties: optionsToAstProperties(pluginOptions)
255
+ },
256
+ computed: false,
257
+ shorthand: false
258
+ });
259
+ return;
260
+ }
261
+ }
262
+ throw new Error(`Failed to add postcss plugin to ${configPath}`);
263
+ }
264
+ async function addPostcssPlugin(configPath, pluginName, pluginOptions = {}) {
265
+ const mod = (0, magicast.parseModule)(await fs_promises.default.readFile(configPath, "utf-8"));
266
+ const defaultExport = mod.exports["default"];
267
+ if (isProxy(defaultExport) && defaultExport.$type === "identifier") {
268
+ addPluginToNamedVar(mod, defaultExport.$name, pluginName, pluginOptions, configPath);
269
+ const { code: code$1 } = (0, magicast.generateCode)(mod);
270
+ await fs_promises.default.writeFile(configPath, code$1);
271
+ return;
272
+ }
273
+ const config = isProxy(defaultExport) && defaultExport.$type === "function-call" ? defaultExport.$args[0] : defaultExport;
274
+ if (!isProxy(config) || config.$type !== "object" || !isObject(config)) throw new Error(`Failed to add postcss plugin to ${configPath}`);
275
+ if ("plugins" in config && config["plugins"] !== void 0 && !isObject(config["plugins"])) throw new Error(`Unrecognized plugins config type in ${configPath}`);
276
+ config["plugins"] ??= {};
277
+ config["plugins"][pluginName] = pluginOptions;
278
+ const { code } = (0, magicast.generateCode)(mod);
279
+ await fs_promises.default.writeFile(configPath, code);
280
+ }
281
+ async function addToConfig(configPath, pluginOptions = {}) {
282
+ if (!fs_extra.default.existsSync(configPath)) {
283
+ await fs_extra.default.writeFile("postcss.config.mts", defaultPostcssConfig(pluginOptions));
284
+ return;
285
+ }
286
+ const ext = configPath.split(".").pop();
287
+ if (ext === "json" || path.default.basename(configPath) === ".postcssrc") {
288
+ const config = await fs_extra.default.readJson(configPath);
289
+ if (!isObject(config)) throw new Error("Unrecognized config type in ${configPath}`)");
290
+ config["plugins"] ??= {};
291
+ if (!isObject(config["plugins"])) throw new Error("Unrecognized config type in ${configPath}`)");
292
+ config["plugins"]["@mochi-css/postcss"] = pluginOptions;
293
+ await fs_extra.default.writeJson(configPath, config, { spaces: 2 });
294
+ return;
295
+ }
296
+ if (ext === "yml" || ext === "yaml") throw new Error("YAML PostCSS config is not supported yet");
297
+ await addPostcssPlugin(configPath, "@mochi-css/postcss", pluginOptions);
298
+ }
299
+ function createPostcssModule(options = {}) {
300
+ const pluginOptions = {};
301
+ if (options.outDir !== void 0) pluginOptions["outDir"] = options.outDir;
302
+ return {
303
+ id: "postcss",
304
+ name: "PostCSS",
305
+ async run(ctx) {
306
+ let configPath;
307
+ if (options.auto) configPath = findPostcssConfig() ?? "postcss.config.mts";
308
+ else {
309
+ const usePostcss = await __clack_prompts.confirm({ message: "Do you use PostCSS?" });
310
+ if (__clack_prompts.isCancel(usePostcss) || !usePostcss) return;
311
+ const selected = await askForPath();
312
+ if (selected === false) return;
313
+ configPath = selected;
314
+ }
315
+ await addToConfig(configPath, pluginOptions);
316
+ __clack_prompts.log.step("Added mochi plugin to the postcss config");
317
+ ctx.requirePackage("@mochi-css/postcss");
318
+ }
319
+ };
320
+ }
321
+ const postcssModule = createPostcssModule();
322
+
323
+ //#endregion
324
+ //#region src/presets/lib.ts
325
+ const libPreset = {
326
+ id: "lib",
327
+ name: "Library",
328
+ setup(runner) {
329
+ runner.register(createPostcssModule());
330
+ }
331
+ };
332
+
333
+ //#endregion
334
+ //#region src/modules/vite.ts
335
+ const viteConfigNames = [
336
+ "vite.config.ts",
337
+ "vite.config.mts",
338
+ "vite.config.js",
339
+ "vite.config.mjs"
340
+ ];
341
+ function findViteConfig() {
342
+ return viteConfigNames.find((name) => fs_extra.default.existsSync(name));
343
+ }
344
+ const defaultViteConfig = `import { defineConfig } from "vite"
345
+ import { mochiCss } from "@mochi-css/vite"
346
+
347
+ export default defineConfig({
348
+ plugins: [mochiCss()],
349
+ })
350
+ `;
351
+ function getPluginsElements(obj, configPath) {
352
+ const existing = obj.properties.find((prop) => getPropKeyName(prop) === "plugins");
353
+ if (existing) {
354
+ const value = existing["value"];
355
+ if (value["type"] !== "ArrayExpression") throw new Error(`Unrecognized plugins config type in ${configPath}`);
356
+ return value["elements"];
357
+ }
358
+ const elements = [];
359
+ obj.properties.push({
360
+ type: "ObjectProperty",
361
+ key: {
362
+ type: "Identifier",
363
+ name: "plugins"
364
+ },
365
+ value: {
366
+ type: "ArrayExpression",
367
+ elements
368
+ },
369
+ computed: false,
370
+ shorthand: false
371
+ });
372
+ return elements;
373
+ }
374
+ function addPluginCallToObj(obj, configPath) {
375
+ getPluginsElements(obj, configPath).push({
376
+ type: "CallExpression",
377
+ callee: {
378
+ type: "Identifier",
379
+ name: "mochiCss"
380
+ },
381
+ arguments: []
382
+ });
383
+ }
384
+ function addToVitePlugins(mod, configPath) {
385
+ const body = mod.$ast.body;
386
+ const exportDefault = body.find((s) => s.type === "ExportDefaultDeclaration");
387
+ if (!exportDefault) throw new Error(`No default export found in ${configPath}`);
388
+ const decl = exportDefault.declaration;
389
+ if (decl["type"] === "ObjectExpression") {
390
+ addPluginCallToObj(decl, configPath);
391
+ return;
392
+ }
393
+ if (decl["type"] === "CallExpression") {
394
+ const firstArg = decl["arguments"][0];
395
+ if (firstArg?.["type"] === "ObjectExpression") {
396
+ addPluginCallToObj(firstArg, configPath);
397
+ return;
398
+ }
399
+ }
400
+ if (decl["type"] === "Identifier") {
401
+ const varName = decl["name"];
402
+ for (const stmt of body) {
403
+ if (stmt.type !== "VariableDeclaration") continue;
404
+ for (const d of stmt.declarations) {
405
+ if (d.id.type !== "Identifier" || d.id.name !== varName) continue;
406
+ if (d.init?.["type"] !== "ObjectExpression") throw new Error(`Failed to add vite plugin to ${configPath}`);
407
+ addPluginCallToObj(d.init, configPath);
408
+ return;
409
+ }
410
+ }
411
+ }
412
+ throw new Error(`Failed to add vite plugin to ${configPath}`);
413
+ }
414
+ async function addMochiToViteConfig(configPath) {
415
+ const mod = (0, magicast.parseModule)(await fs_promises.default.readFile(configPath, "utf-8"));
416
+ mod.imports.$prepend({
417
+ from: "@mochi-css/vite",
418
+ imported: "mochiCss",
419
+ local: "mochiCss"
420
+ });
421
+ addToVitePlugins(mod, configPath);
422
+ const { code } = (0, magicast.generateCode)(mod);
423
+ await fs_promises.default.writeFile(configPath, code);
424
+ }
425
+ const viteModule = {
426
+ id: "vite",
427
+ name: "Vite",
428
+ async run(ctx) {
429
+ const existingConfig = findViteConfig();
430
+ let configPath;
431
+ if (!existingConfig) {
432
+ const selected = await __clack_prompts.text({
433
+ message: "Path to Vite config",
434
+ placeholder: "vite.config.ts",
435
+ defaultValue: "vite.config.ts"
436
+ });
437
+ if (__clack_prompts.isCancel(selected)) return;
438
+ configPath = selected;
439
+ } else configPath = existingConfig;
440
+ if (!fs_extra.default.existsSync(configPath)) {
441
+ await fs_promises.default.writeFile(configPath, defaultViteConfig);
442
+ __clack_prompts.log.step("Created vite config with mochi plugin");
443
+ } else {
444
+ await addMochiToViteConfig(configPath);
445
+ __clack_prompts.log.step("Added mochiCss() to vite config");
446
+ }
447
+ ctx.requirePackage("@mochi-css/vite");
448
+ }
449
+ };
450
+
451
+ //#endregion
452
+ //#region src/presets/vite.ts
453
+ const vitePreset = {
454
+ id: "vite",
455
+ name: "Vite",
456
+ setup(runner) {
457
+ runner.register(createPostcssModule({ outDir: ".mochi" }));
458
+ runner.register(viteModule);
459
+ }
460
+ };
461
+
462
+ //#endregion
463
+ //#region src/modules/next.ts
464
+ const nextConfigNames = [
465
+ "next.config.ts",
466
+ "next.config.mts",
467
+ "next.config.js",
468
+ "next.config.mjs"
469
+ ];
470
+ function findNextConfig() {
471
+ return nextConfigNames.find((name) => fs_extra.default.existsSync(name));
472
+ }
473
+ const defaultNextConfig = `import { withMochi } from "@mochi-css/next"
474
+
475
+ export default withMochi({})
476
+ `;
477
+ function wrapExportDefault(mod, configPath) {
478
+ const exportDefault = mod.$ast.body.find((s) => s.type === "ExportDefaultDeclaration");
479
+ if (!exportDefault) throw new Error(`No default export found in ${configPath}`);
480
+ exportDefault["declaration"] = {
481
+ type: "CallExpression",
482
+ callee: {
483
+ type: "Identifier",
484
+ name: "withMochi"
485
+ },
486
+ arguments: [exportDefault.declaration]
487
+ };
488
+ }
489
+ async function addMochiToNextConfig(configPath) {
490
+ const mod = (0, magicast.parseModule)(await fs_promises.default.readFile(configPath, "utf-8"));
491
+ mod.imports.$prepend({
492
+ from: "@mochi-css/next",
493
+ imported: "withMochi",
494
+ local: "withMochi"
495
+ });
496
+ wrapExportDefault(mod, configPath);
497
+ const { code } = (0, magicast.generateCode)(mod);
498
+ await fs_promises.default.writeFile(configPath, code);
499
+ }
500
+ const nextModule = {
501
+ id: "next",
502
+ name: "Next.js",
503
+ async run(ctx) {
504
+ const existingConfig = findNextConfig();
505
+ let configPath;
506
+ if (!existingConfig) {
507
+ const selected = await __clack_prompts.text({
508
+ message: "Path to Next.js config",
509
+ placeholder: "next.config.ts",
510
+ defaultValue: "next.config.ts"
511
+ });
512
+ if (__clack_prompts.isCancel(selected)) return;
513
+ configPath = selected;
514
+ } else configPath = existingConfig;
515
+ if (!fs_extra.default.existsSync(configPath)) {
516
+ await fs_promises.default.writeFile(configPath, defaultNextConfig);
517
+ __clack_prompts.log.step("Created next config with mochi");
518
+ } else {
519
+ await addMochiToNextConfig(configPath);
520
+ __clack_prompts.log.step("Added withMochi() to next config");
521
+ }
522
+ ctx.requirePackage("@mochi-css/next");
523
+ }
524
+ };
525
+
526
+ //#endregion
527
+ //#region src/presets/nextjs.ts
528
+ const nextjsPreset = {
529
+ id: "nextjs",
530
+ name: "Next.js",
531
+ setup(runner) {
532
+ runner.register(createPostcssModule({
533
+ outDir: ".mochi",
534
+ auto: true
535
+ }));
536
+ runner.register(nextModule);
537
+ }
538
+ };
539
+
540
+ //#endregion
541
+ //#region src/presets/index.ts
542
+ const presets = {
543
+ lib: libPreset,
544
+ vite: vitePreset,
545
+ nextjs: nextjsPreset
546
+ };
547
+
548
+ //#endregion
549
+ //#region src/index.ts
550
+ commander.program.name("tsuki").description("Add mochi-css to your project").version("1.1.0").addOption(new commander.Option("-p, --preset <preset>", "Preset to use").choices([
551
+ "vite",
552
+ "nextjs",
553
+ "lib"
554
+ ])).action(async (options) => {
555
+ __clack_prompts.intro(picocolors.default.cyan("Installing Mochi-CSS..."));
556
+ try {
557
+ const runner = new ModuleRunner();
558
+ let presetId = options.preset;
559
+ if (presetId === void 0) {
560
+ const selected = await __clack_prompts.select({
561
+ message: "Which framework are you using?",
562
+ options: Object.values(presets).map((preset$1) => ({
563
+ value: preset$1.id,
564
+ label: preset$1.name
565
+ }))
566
+ });
567
+ if (__clack_prompts.isCancel(selected)) {
568
+ __clack_prompts.outro(picocolors.default.red("Cancelled"));
569
+ return;
570
+ }
571
+ presetId = selected;
572
+ }
573
+ const preset = presets[presetId];
574
+ if (!preset) throw new Error(`Unknown preset: ${presetId}`);
575
+ preset.setup(runner);
576
+ await runner.run();
577
+ __clack_prompts.outro(picocolors.default.green("Done!"));
578
+ } catch (e) {
579
+ if (e instanceof Error) __clack_prompts.outro(picocolors.default.red(e.message));
580
+ }
581
+ });
582
+ commander.program.parse();
583
+
584
+ //#endregion
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@mochi-css/tsuki",
3
+ "repository": "git@github.com:Niikelion/mochi-css.git",
4
+ "version": "1.1.0",
5
+ "license": "MIT",
6
+ "bin": "./dist/index.js",
7
+ "files": [
8
+ "/dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc --noEmit && tsdown",
12
+ "test": "vitest",
13
+ "coverage": "vitest run --coverage",
14
+ "smoke": "jiti scripts/smoke.ts",
15
+ "manual": "jiti scripts/manual.ts",
16
+ "lint": "eslint src",
17
+ "lint:fix": "eslint src --fix",
18
+ "format": "prettier --write"
19
+ },
20
+ "devDependencies": {
21
+ "@eslint/js": "^9.18.0",
22
+ "@gamedev-sensei/ts-config": "^2.1.0",
23
+ "@types/cross-spawn": "^6.0.6",
24
+ "@types/fs-extra": "^11.0.4",
25
+ "@types/node": "^24.8.1",
26
+ "@vitest/coverage-v8": "^4.0.15",
27
+ "eslint": "^9.39.2",
28
+ "eslint-config-prettier": "^10.1.8",
29
+ "eslint-plugin-prettier": "^5.5.5",
30
+ "jiti": "^2.6.1",
31
+ "prettier": "^3.8.1",
32
+ "tsdown": "^0.15.7",
33
+ "typescript": "^5.9.3",
34
+ "typescript-eslint": "^8.21.0",
35
+ "vite-tsconfig-paths": "^5.1.4",
36
+ "vitest": "^4.0.15"
37
+ },
38
+ "dependencies": {
39
+ "@clack/prompts": "^1.0.1",
40
+ "commander": "^13.1.0",
41
+ "cross-spawn": "^7.0.6",
42
+ "fs-extra": "^11.3.0",
43
+ "magicast": "^0.5.1",
44
+ "package-manager-detector": "^1.6.0",
45
+ "picocolors": "^1.1.1"
46
+ }
47
+ }