@collie-lang/cli 1.1.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,42 +1,64 @@
1
1
  #!/usr/bin/env node
2
+ "use strict";
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") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
2
25
 
3
26
  // src/index.ts
4
- import { spawn as spawn2 } from "child_process";
5
- import fs9 from "fs/promises";
6
- import { existsSync as existsSync4, readFileSync } from "fs";
7
- import path9 from "path";
8
- import { fileURLToPath as fileURLToPath2 } from "url";
9
- import ts from "typescript";
10
- import fg4 from "fast-glob";
11
- import { diffLines } from "diff";
12
- import pc8 from "picocolors";
13
- import prompts2 from "prompts";
27
+ var import_node_child_process2 = require("child_process");
28
+ var import_promises8 = __toESM(require("fs/promises"));
29
+ var import_node_fs3 = require("fs");
30
+ var import_node_path8 = __toESM(require("path"));
31
+ var import_typescript = __toESM(require("typescript"));
32
+ var import_fast_glob4 = __toESM(require("fast-glob"));
33
+ var import_diff = require("diff");
34
+ var import_picocolors7 = __toESM(require("picocolors"));
35
+ var import_prompts2 = __toESM(require("prompts"));
14
36
 
15
37
  // src/formatter.ts
16
- import fs from "fs/promises";
17
- import { formatCollie } from "@collie-lang/compiler";
38
+ var import_promises = __toESM(require("fs/promises"));
39
+ var import_compiler = require("@collie-lang/compiler");
18
40
  function formatSource(source, options = {}) {
19
- return formatCollie(source, options);
41
+ return (0, import_compiler.formatCollie)(source, options);
20
42
  }
21
43
 
22
44
  // src/watcher.ts
23
- import chokidar from "chokidar";
24
- import { compileToTsx } from "@collie-lang/compiler";
25
- import fs2 from "fs/promises";
26
- import path2 from "path";
27
- import pc from "picocolors";
45
+ var import_chokidar = __toESM(require("chokidar"));
46
+ var import_compiler2 = require("@collie-lang/compiler");
47
+ var import_promises2 = __toESM(require("fs/promises"));
48
+ var import_node_path2 = __toESM(require("path"));
49
+ var import_picocolors = __toESM(require("picocolors"));
28
50
 
29
51
  // src/fs-utils.ts
30
- import path from "path";
52
+ var import_node_path = __toESM(require("path"));
31
53
  function resolveOutputPath(filepath, baseDir, outDir) {
32
54
  const outputBase = outDir ?? baseDir;
33
- const relative = path.relative(baseDir, filepath);
34
- const ext = path.extname(relative);
55
+ const relative = import_node_path.default.relative(baseDir, filepath);
56
+ const ext = import_node_path.default.extname(relative);
35
57
  const withoutExt = ext ? relative.slice(0, -ext.length) : relative;
36
- return path.join(outputBase, `${withoutExt}.tsx`);
58
+ return import_node_path.default.join(outputBase, `${withoutExt}.tsx`);
37
59
  }
38
60
  function toDisplayPath(target) {
39
- const relative = path.relative(process.cwd(), target);
61
+ const relative = import_node_path.default.relative(process.cwd(), target);
40
62
  if (!relative || relative.startsWith("..") || relative.startsWith("..\\")) {
41
63
  return target;
42
64
  }
@@ -45,21 +67,21 @@ function toDisplayPath(target) {
45
67
 
46
68
  // src/watcher.ts
47
69
  async function watch(inputPath, options = {}) {
48
- const resolvedInput = path2.resolve(process.cwd(), inputPath);
70
+ const resolvedInput = import_node_path2.default.resolve(process.cwd(), inputPath);
49
71
  let stats;
50
72
  try {
51
- stats = await fs2.stat(resolvedInput);
73
+ stats = await import_promises2.default.stat(resolvedInput);
52
74
  } catch {
53
75
  throw new Error(`Input path does not exist: ${inputPath}`);
54
76
  }
55
77
  const isDirectory = stats.isDirectory();
56
78
  const ext = normalizeExtension(options.ext);
57
- const baseDir = isDirectory ? resolvedInput : path2.dirname(resolvedInput);
58
- const outDir = options.outDir ? path2.resolve(process.cwd(), options.outDir) : void 0;
59
- const pattern = isDirectory ? path2.join(resolvedInput, `**/*${ext}`) : resolvedInput;
60
- console.log(pc.cyan(`Watching ${toDisplayPath(resolvedInput)} for changes...
79
+ const baseDir = isDirectory ? resolvedInput : import_node_path2.default.dirname(resolvedInput);
80
+ const outDir = options.outDir ? import_node_path2.default.resolve(process.cwd(), options.outDir) : void 0;
81
+ const pattern = isDirectory ? import_node_path2.default.join(resolvedInput, `**/*${ext}`) : resolvedInput;
82
+ console.log(import_picocolors.default.cyan(`Watching ${toDisplayPath(resolvedInput)} for changes...
61
83
  `));
62
- const watcher = chokidar.watch(pattern, {
84
+ const watcher = import_chokidar.default.watch(pattern, {
63
85
  ignored: /node_modules/,
64
86
  persistent: true,
65
87
  ignoreInitial: false
@@ -69,7 +91,7 @@ async function watch(inputPath, options = {}) {
69
91
  });
70
92
  watcher.on("change", (file) => {
71
93
  if (options.verbose) {
72
- console.log(pc.gray(`[${getTimestamp()}] Changed: ${toDisplayPath(file)}`));
94
+ console.log(import_picocolors.default.gray(`[${getTimestamp()}] Changed: ${toDisplayPath(file)}`));
73
95
  }
74
96
  void compileFile(file, baseDir, outDir, options);
75
97
  });
@@ -77,20 +99,20 @@ async function watch(inputPath, options = {}) {
77
99
  void deleteCompiledFile(file, baseDir, outDir, options);
78
100
  });
79
101
  watcher.on("ready", () => {
80
- console.log(pc.green("\nWatching for file changes...\n"));
102
+ console.log(import_picocolors.default.green("\nWatching for file changes...\n"));
81
103
  });
82
104
  await new Promise((resolve, reject) => {
83
105
  watcher.on("close", resolve);
84
106
  watcher.on("error", (error) => {
85
107
  const err = error instanceof Error ? error : new Error(String(error));
86
- console.error(pc.red(`[collie] Watcher error: ${err.message}`));
108
+ console.error(import_picocolors.default.red(`[collie] Watcher error: ${err.message}`));
87
109
  reject(err);
88
110
  });
89
111
  process.once("SIGINT", () => {
90
- console.log(pc.yellow("\nStopping watch mode..."));
112
+ console.log(import_picocolors.default.yellow("\nStopping watch mode..."));
91
113
  watcher.close().catch((error) => {
92
114
  const err = error instanceof Error ? error : new Error(String(error));
93
- console.error(pc.red(`[collie] Failed to stop watcher: ${err.message}`));
115
+ console.error(import_picocolors.default.red(`[collie] Failed to stop watcher: ${err.message}`));
94
116
  reject(err);
95
117
  });
96
118
  });
@@ -98,44 +120,44 @@ async function watch(inputPath, options = {}) {
98
120
  }
99
121
  async function compileFile(filepath, baseDir, outDir, options) {
100
122
  try {
101
- const source = await fs2.readFile(filepath, "utf8");
102
- const componentName = path2.basename(filepath, path2.extname(filepath));
123
+ const source = await import_promises2.default.readFile(filepath, "utf8");
124
+ const componentName = import_node_path2.default.basename(filepath, import_node_path2.default.extname(filepath));
103
125
  const compileOptions = {
104
126
  filename: filepath,
105
127
  componentNameHint: componentName,
106
128
  jsxRuntime: options.jsxRuntime ?? "automatic"
107
129
  };
108
- const result = compileToTsx(source, compileOptions);
130
+ const result = (0, import_compiler2.compileToTsx)(source, compileOptions);
109
131
  const errors = result.diagnostics.filter((d) => d.severity === "error");
110
132
  if (errors.length) {
111
133
  logDiagnostics(filepath, errors);
112
134
  return;
113
135
  }
114
136
  const outputPath = resolveOutputPath(filepath, baseDir, outDir);
115
- await fs2.mkdir(path2.dirname(outputPath), { recursive: true });
116
- await fs2.writeFile(outputPath, result.code, "utf8");
137
+ await import_promises2.default.mkdir(import_node_path2.default.dirname(outputPath), { recursive: true });
138
+ await import_promises2.default.writeFile(outputPath, result.code, "utf8");
117
139
  if (options.sourcemap && result.map) {
118
- await fs2.writeFile(`${outputPath}.map`, JSON.stringify(result.map), "utf8");
140
+ await import_promises2.default.writeFile(`${outputPath}.map`, JSON.stringify(result.map), "utf8");
119
141
  }
120
- console.log(pc.green(`[${getTimestamp()}] Compiled ${toDisplayPath(filepath)} \u2192 ${toDisplayPath(outputPath)}`));
142
+ console.log(import_picocolors.default.green(`[${getTimestamp()}] Compiled ${toDisplayPath(filepath)} \u2192 ${toDisplayPath(outputPath)}`));
121
143
  const warnings = result.diagnostics.filter((d) => d.severity === "warning");
122
144
  if (warnings.length) {
123
145
  logDiagnostics(filepath, warnings);
124
146
  }
125
147
  } catch (error) {
126
148
  const message = error instanceof Error ? error.message : String(error);
127
- console.error(pc.red(`[collie] Failed to compile ${toDisplayPath(filepath)}: ${message}`));
149
+ console.error(import_picocolors.default.red(`[collie] Failed to compile ${toDisplayPath(filepath)}: ${message}`));
128
150
  }
129
151
  }
130
152
  async function deleteCompiledFile(filepath, baseDir, outDir, options) {
131
153
  try {
132
154
  const outputPath = resolveOutputPath(filepath, baseDir, outDir);
133
- await fs2.unlink(outputPath);
155
+ await import_promises2.default.unlink(outputPath);
134
156
  if (options.sourcemap) {
135
- await fs2.unlink(`${outputPath}.map`).catch(() => {
157
+ await import_promises2.default.unlink(`${outputPath}.map`).catch(() => {
136
158
  });
137
159
  }
138
- console.log(pc.yellow(`[${getTimestamp()}] Deleted ${toDisplayPath(outputPath)}`));
160
+ console.log(import_picocolors.default.yellow(`[${getTimestamp()}] Deleted ${toDisplayPath(outputPath)}`));
139
161
  } catch {
140
162
  }
141
163
  }
@@ -146,7 +168,7 @@ function logDiagnostics(file, diagnostics) {
146
168
  const location = range ? `${range.start.line}:${range.start.col}` : "";
147
169
  const prefix = location ? `${toDisplayPath(fileLabel)}:${location}` : toDisplayPath(fileLabel);
148
170
  const code = diag.code ? ` (${diag.code})` : "";
149
- const writer = diag.severity === "warning" ? pc.yellow : pc.red;
171
+ const writer = diag.severity === "warning" ? import_picocolors.default.yellow : import_picocolors.default.red;
150
172
  console[diag.severity === "warning" ? "warn" : "error"](
151
173
  writer(`${prefix ? `${prefix}: ` : ""}${diag.severity}${code}: ${diag.message}`)
152
174
  );
@@ -163,27 +185,27 @@ function getTimestamp() {
163
185
  }
164
186
 
165
187
  // src/builder.ts
166
- import fg from "fast-glob";
167
- import { compileToTsx as compileToTsx2 } from "@collie-lang/compiler";
168
- import fs3 from "fs/promises";
169
- import path3 from "path";
170
- import pc3 from "picocolors";
188
+ var import_fast_glob = __toESM(require("fast-glob"));
189
+ var import_compiler3 = require("@collie-lang/compiler");
190
+ var import_promises3 = __toESM(require("fs/promises"));
191
+ var import_node_path3 = __toESM(require("path"));
192
+ var import_picocolors3 = __toESM(require("picocolors"));
171
193
 
172
194
  // src/output.ts
173
- import pc2 from "picocolors";
195
+ var import_picocolors2 = __toESM(require("picocolors"));
174
196
  var SUMMARY_STYLES = {
175
- success: { icon: "\u2714", color: pc2.green },
176
- warning: { icon: "\u26A0", color: pc2.yellow },
177
- error: { icon: "\u2716", color: pc2.red }
197
+ success: { icon: "\u2714", color: import_picocolors2.default.green },
198
+ warning: { icon: "\u26A0", color: import_picocolors2.default.yellow },
199
+ error: { icon: "\u2716", color: import_picocolors2.default.red }
178
200
  };
179
201
  function printSummary(kind, message, detail, nextStep) {
180
202
  const style = SUMMARY_STYLES[kind];
181
203
  console.log(style.color(`${style.icon} ${message}`));
182
204
  if (detail) {
183
- console.log(pc2.dim(`Changed: ${detail}`));
205
+ console.log(import_picocolors2.default.dim(`Changed: ${detail}`));
184
206
  }
185
207
  if (nextStep) {
186
- console.log(pc2.dim(`Next: ${nextStep}`));
208
+ console.log(import_picocolors2.default.dim(`Next: ${nextStep}`));
187
209
  }
188
210
  }
189
211
  function formatDiagnosticLine(diag, fallbackFile) {
@@ -196,17 +218,17 @@ function formatDiagnosticLine(diag, fallbackFile) {
196
218
 
197
219
  // src/builder.ts
198
220
  async function build(input, options = {}) {
199
- const resolvedInput = path3.resolve(process.cwd(), input);
221
+ const resolvedInput = import_node_path3.default.resolve(process.cwd(), input);
200
222
  let stats;
201
223
  try {
202
- stats = await fs3.stat(resolvedInput);
224
+ stats = await import_promises3.default.stat(resolvedInput);
203
225
  } catch {
204
226
  throw new Error(`Input path does not exist: ${input}`);
205
227
  }
206
228
  const isDirectory = stats.isDirectory();
207
- const baseDir = isDirectory ? resolvedInput : path3.dirname(resolvedInput);
208
- const outDir = options.outDir ? path3.resolve(process.cwd(), options.outDir) : void 0;
209
- const files = isDirectory ? (await fg("**/*.collie", { cwd: resolvedInput, absolute: true })).sort() : [resolvedInput];
229
+ const baseDir = isDirectory ? resolvedInput : import_node_path3.default.dirname(resolvedInput);
230
+ const outDir = options.outDir ? import_node_path3.default.resolve(process.cwd(), options.outDir) : void 0;
231
+ const files = isDirectory ? (await (0, import_fast_glob.default)("**/*.collie", { cwd: resolvedInput, absolute: true })).sort() : [resolvedInput];
210
232
  if (!files.length) {
211
233
  if (!options.quiet) {
212
234
  printSummary(
@@ -219,7 +241,7 @@ async function build(input, options = {}) {
219
241
  return { totalFiles: 0, successfulFiles: 0, errors: [] };
220
242
  }
221
243
  if (!options.quiet) {
222
- console.log(pc3.cyan(`Compiling ${toDisplayPath(resolvedInput)}...`));
244
+ console.log(import_picocolors3.default.cyan(`Compiling ${toDisplayPath(resolvedInput)}...`));
223
245
  console.log("");
224
246
  }
225
247
  const result = {
@@ -232,7 +254,7 @@ async function build(input, options = {}) {
232
254
  if (compileResult.success) {
233
255
  result.successfulFiles++;
234
256
  if (!options.quiet) {
235
- console.log(pc3.green(`\u2714 ${toDisplayPath(file)} \u2192 ${toDisplayPath(compileResult.outputPath)}`));
257
+ console.log(import_picocolors3.default.green(`\u2714 ${toDisplayPath(file)} \u2192 ${toDisplayPath(compileResult.outputPath)}`));
236
258
  }
237
259
  if (options.verbose) {
238
260
  logDiagnostics2(file, compileResult.diagnostics.filter((d) => d.severity === "warning"));
@@ -266,23 +288,23 @@ async function build(input, options = {}) {
266
288
  }
267
289
  async function compileSingleFile(filepath, baseDir, outDir, options) {
268
290
  try {
269
- const source = await fs3.readFile(filepath, "utf8");
270
- const componentName = path3.basename(filepath, path3.extname(filepath));
291
+ const source = await import_promises3.default.readFile(filepath, "utf8");
292
+ const componentName = import_node_path3.default.basename(filepath, import_node_path3.default.extname(filepath));
271
293
  const compileOptions = {
272
294
  filename: filepath,
273
295
  componentNameHint: componentName,
274
296
  jsxRuntime: options.jsxRuntime ?? "automatic"
275
297
  };
276
- const result = compileToTsx2(source, compileOptions);
298
+ const result = (0, import_compiler3.compileToTsx)(source, compileOptions);
277
299
  const errors = result.diagnostics.filter((d) => d.severity === "error");
278
300
  if (errors.length) {
279
301
  return { success: false, diagnostics: errors };
280
302
  }
281
303
  const outputPath = resolveOutputPath(filepath, baseDir, outDir);
282
- await fs3.mkdir(path3.dirname(outputPath), { recursive: true });
283
- await fs3.writeFile(outputPath, result.code, "utf8");
304
+ await import_promises3.default.mkdir(import_node_path3.default.dirname(outputPath), { recursive: true });
305
+ await import_promises3.default.writeFile(outputPath, result.code, "utf8");
284
306
  if (options.sourcemap && result.map) {
285
- await fs3.writeFile(`${outputPath}.map`, JSON.stringify(result.map), "utf8");
307
+ await import_promises3.default.writeFile(`${outputPath}.map`, JSON.stringify(result.map), "utf8");
286
308
  }
287
309
  return { success: true, outputPath, diagnostics: result.diagnostics };
288
310
  } catch (error) {
@@ -309,19 +331,19 @@ function logDiagnostics2(file, diagnostics, force = false) {
309
331
  }
310
332
  const displayFile = diag.file ? toDisplayPath(diag.file) : toDisplayPath(file);
311
333
  const message = formatDiagnosticLine({ ...diag, file: displayFile }, toDisplayPath(file));
312
- const writer = diag.severity === "warning" ? pc3.yellow : pc3.red;
334
+ const writer = diag.severity === "warning" ? import_picocolors3.default.yellow : import_picocolors3.default.red;
313
335
  console[diag.severity === "warning" ? "warn" : "error"](writer(message));
314
336
  }
315
337
  }
316
338
 
317
339
  // src/checker.ts
318
- import fg2 from "fast-glob";
319
- import { parseCollie } from "@collie-lang/compiler";
320
- import fs4 from "fs/promises";
321
- import path4 from "path";
322
- import pc4 from "picocolors";
340
+ var import_fast_glob2 = __toESM(require("fast-glob"));
341
+ var import_compiler4 = require("@collie-lang/compiler");
342
+ var import_promises4 = __toESM(require("fs/promises"));
343
+ var import_node_path4 = __toESM(require("path"));
344
+ var import_picocolors4 = __toESM(require("picocolors"));
323
345
  async function scanTemplates(patterns) {
324
- const files = await fg2(patterns, {
346
+ const files = await (0, import_fast_glob2.default)(patterns, {
325
347
  absolute: true,
326
348
  onlyFiles: true,
327
349
  dot: false,
@@ -336,16 +358,16 @@ async function scanTemplates(patterns) {
336
358
  for (const file of files) {
337
359
  const displayPath = toDisplayPath(file);
338
360
  try {
339
- const source = await fs4.readFile(file, "utf8");
361
+ const source = await import_promises4.default.readFile(file, "utf8");
340
362
  lineCache.set(displayPath, source.split(/\r?\n/));
341
- const parseResult = parseCollie(source, { filename: file });
363
+ const parseResult = (0, import_compiler4.parseCollie)(source, { filename: file });
342
364
  for (const diag of parseResult.diagnostics) {
343
365
  const range = diag.range ?? diag.span;
344
366
  const normalized = {
345
367
  ...diag,
346
- file: diag.file ? toDisplayPath(path4.isAbsolute(diag.file) ? diag.file : path4.resolve(path4.dirname(file), diag.file)) : displayPath,
368
+ file: diag.file ? toDisplayPath(import_node_path4.default.isAbsolute(diag.file) ? diag.file : import_node_path4.default.resolve(import_node_path4.default.dirname(file), diag.file)) : displayPath,
347
369
  filePath: diag.filePath ? toDisplayPath(
348
- path4.isAbsolute(diag.filePath) ? diag.filePath : path4.resolve(path4.dirname(file), diag.filePath)
370
+ import_node_path4.default.isAbsolute(diag.filePath) ? diag.filePath : import_node_path4.default.resolve(import_node_path4.default.dirname(file), diag.filePath)
349
371
  ) : displayPath,
350
372
  range
351
373
  };
@@ -451,7 +473,7 @@ async function check(patterns, options = {}) {
451
473
  if ((options.format ?? "text") === "json") {
452
474
  console.log(JSON.stringify(result, null, 2));
453
475
  } else {
454
- console.log(pc4.cyan(`Checking ${scan.files.length} file${scan.files.length === 1 ? "" : "s"}...
476
+ console.log(import_picocolors4.default.cyan(`Checking ${scan.files.length} file${scan.files.length === 1 ? "" : "s"}...
455
477
  `));
456
478
  printTextDiagnostics(result, options, scan.lineCache);
457
479
  }
@@ -462,7 +484,7 @@ function printTextDiagnostics(result, options, lineCache) {
462
484
  if (hasDiagnostics) {
463
485
  for (const diag of result.diagnostics) {
464
486
  const message = formatDiagnosticLine(diag);
465
- const writer = diag.severity === "warning" ? pc4.yellow : pc4.red;
487
+ const writer = diag.severity === "warning" ? import_picocolors4.default.yellow : import_picocolors4.default.red;
466
488
  console.log(writer(message));
467
489
  const range = diag.range ?? diag.span;
468
490
  const fileLabel = diag.filePath ?? diag.file;
@@ -474,8 +496,8 @@ function printTextDiagnostics(result, options, lineCache) {
474
496
  const markerStart = Math.max(0, range.start.col - 1);
475
497
  const width = Math.max(1, range.end.col - range.start.col);
476
498
  const indicator = `${" ".repeat(markerStart)}${"^".repeat(width)}`;
477
- console.log(pc4.dim(` ${text}`));
478
- console.log(pc4.dim(` ${indicator}`));
499
+ console.log(import_picocolors4.default.dim(` ${text}`));
500
+ console.log(import_picocolors4.default.dim(` ${indicator}`));
479
501
  }
480
502
  }
481
503
  if (options.verbose) {
@@ -508,13 +530,12 @@ function printTextDiagnostics(result, options, lineCache) {
508
530
  }
509
531
 
510
532
  // src/creator.ts
511
- import prompts from "prompts";
512
- import fs5 from "fs/promises";
513
- import { existsSync } from "fs";
514
- import path5 from "path";
515
- import { spawn } from "child_process";
516
- import { fileURLToPath } from "url";
517
- import pc5 from "picocolors";
533
+ var import_prompts = __toESM(require("prompts"));
534
+ var import_promises5 = __toESM(require("fs/promises"));
535
+ var import_node_fs = require("fs");
536
+ var import_node_path5 = __toESM(require("path"));
537
+ var import_node_child_process = require("child_process");
538
+ var import_picocolors5 = __toESM(require("picocolors"));
518
539
  var TEMPLATE_MAP = {
519
540
  vite: {
520
541
  label: "Vite + React",
@@ -523,21 +544,9 @@ var TEMPLATE_MAP = {
523
544
  ts: "vite-react-ts",
524
545
  js: "vite-react-js"
525
546
  }
526
- },
527
- "nextjs-app-router": {
528
- label: "Next.js App Router",
529
- description: "Next.js 14 App Router starter wired with @collie-lang/next",
530
- variants: {
531
- ts: "nextjs-app-router-ts",
532
- js: "nextjs-app-router-js"
533
- }
534
547
  }
535
548
  };
536
- var TEMPLATE_ALIASES = {
537
- next: { template: "nextjs-app-router" },
538
- nextjs: { template: "nextjs-app-router", forcedTypescript: true },
539
- "nextjs-app": { template: "nextjs-app-router", forcedTypescript: true }
540
- };
549
+ var TEMPLATE_ALIASES = {};
541
550
  function formatTemplateList() {
542
551
  return Object.entries(TEMPLATE_MAP).map(([key, meta]) => {
543
552
  const variantInfo = [
@@ -553,38 +562,38 @@ function formatTemplateList() {
553
562
  }
554
563
  async function create(options = {}) {
555
564
  const resolved = await promptForOptions(options);
556
- const targetDir = path5.resolve(process.cwd(), resolved.projectName);
557
- if (existsSync(targetDir)) {
565
+ const targetDir = import_node_path5.default.resolve(process.cwd(), resolved.projectName);
566
+ if ((0, import_node_fs.existsSync)(targetDir)) {
558
567
  const overwrite = await confirmOverwrite(resolved.projectName);
559
568
  if (!overwrite) {
560
- console.log(pc5.yellow("Cancelled"));
569
+ console.log(import_picocolors5.default.yellow("Cancelled"));
561
570
  return;
562
571
  }
563
- await fs5.rm(targetDir, { recursive: true, force: true });
572
+ await import_promises5.default.rm(targetDir, { recursive: true, force: true });
564
573
  }
565
- console.log(pc5.cyan(`
574
+ console.log(import_picocolors5.default.cyan(`
566
575
  Creating project in ${targetDir}...
567
576
  `));
568
577
  const templateDir = getTemplateDir(resolved.template, resolved.typescript);
569
578
  await copyTemplate(templateDir, targetDir, resolved.projectName);
570
- console.log(pc5.green("\u2714 Copied template files"));
579
+ console.log(import_picocolors5.default.green("\u2714 Copied template files"));
571
580
  if (!resolved.noGit) {
572
581
  try {
573
582
  await runCommand("git", ["init"], targetDir);
574
- console.log(pc5.green("\u2714 Initialized git repository"));
583
+ console.log(import_picocolors5.default.green("\u2714 Initialized git repository"));
575
584
  } catch (error) {
576
585
  const message = error instanceof Error ? error.message : String(error);
577
- console.log(pc5.yellow(`\u26A0 Failed to initialize git: ${message}`));
586
+ console.log(import_picocolors5.default.yellow(`\u26A0 Failed to initialize git: ${message}`));
578
587
  }
579
588
  }
580
589
  if (!resolved.noInstall) {
581
- console.log(pc5.cyan(`\u2714 Installing dependencies with ${resolved.packageManager}...`));
590
+ console.log(import_picocolors5.default.cyan(`\u2714 Installing dependencies with ${resolved.packageManager}...`));
582
591
  try {
583
592
  await installDependencies(resolved.packageManager, targetDir);
584
593
  } catch (error) {
585
594
  const message = error instanceof Error ? error.message : String(error);
586
- console.log(pc5.yellow(`\u26A0 Failed to install dependencies: ${message}`));
587
- console.log(pc5.yellow(" Run the install command manually once you're ready."));
595
+ console.log(import_picocolors5.default.yellow(`\u26A0 Failed to install dependencies: ${message}`));
596
+ console.log(import_picocolors5.default.yellow(" Run the install command manually once you're ready."));
588
597
  }
589
598
  }
590
599
  printSuccessMessage(resolved);
@@ -639,9 +648,9 @@ async function promptForOptions(options) {
639
648
  initial: detected === "pnpm" ? 0 : detected === "npm" ? 1 : 2
640
649
  });
641
650
  }
642
- const answers = questions.length > 0 ? await prompts(questions, {
651
+ const answers = questions.length > 0 ? await (0, import_prompts.default)(questions, {
643
652
  onCancel: () => {
644
- console.log(pc5.yellow("\nCancelled"));
653
+ console.log(import_picocolors5.default.yellow("\nCancelled"));
645
654
  process.exit(0);
646
655
  }
647
656
  }) : {};
@@ -692,7 +701,7 @@ Usage: collie create <project-name> --template <template>`
692
701
  );
693
702
  }
694
703
  async function confirmOverwrite(projectName) {
695
- const { overwrite } = await prompts({
704
+ const { overwrite } = await (0, import_prompts.default)({
696
705
  type: "confirm",
697
706
  name: "overwrite",
698
707
  message: `Directory ${projectName} already exists. Overwrite?`,
@@ -703,8 +712,8 @@ async function confirmOverwrite(projectName) {
703
712
  function getTemplateDir(template, typescript) {
704
713
  const meta = TEMPLATE_MAP[template];
705
714
  const variant = typescript ? meta.variants.ts : meta.variants.js;
706
- const dir = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "..", "templates", variant);
707
- if (!existsSync(dir)) {
715
+ const dir = import_node_path5.default.resolve(__dirname, "..", "templates", variant);
716
+ if (!(0, import_node_fs.existsSync)(dir)) {
708
717
  throw new Error(
709
718
  `Template '${template}' with ${typescript ? "TypeScript" : "JavaScript"} is not available.`
710
719
  );
@@ -712,25 +721,25 @@ function getTemplateDir(template, typescript) {
712
721
  return dir;
713
722
  }
714
723
  async function copyTemplate(templateDir, targetDir, projectName) {
715
- await fs5.mkdir(targetDir, { recursive: true });
724
+ await import_promises5.default.mkdir(targetDir, { recursive: true });
716
725
  await copyDirectory(templateDir, targetDir, { projectName });
717
726
  }
718
727
  async function copyDirectory(source, target, context) {
719
- const entries = await fs5.readdir(source, { withFileTypes: true });
728
+ const entries = await import_promises5.default.readdir(source, { withFileTypes: true });
720
729
  for (const entry of entries) {
721
- const srcPath = path5.join(source, entry.name);
730
+ const srcPath = import_node_path5.default.join(source, entry.name);
722
731
  const destName = entry.name.endsWith(".template") ? entry.name.replace(/\.template$/, "") : entry.name;
723
- const destPath = path5.join(target, destName);
732
+ const destPath = import_node_path5.default.join(target, destName);
724
733
  if (entry.isDirectory()) {
725
- await fs5.mkdir(destPath, { recursive: true });
734
+ await import_promises5.default.mkdir(destPath, { recursive: true });
726
735
  await copyDirectory(srcPath, destPath, context);
727
736
  } else {
728
- const buffer = await fs5.readFile(srcPath);
737
+ const buffer = await import_promises5.default.readFile(srcPath);
729
738
  if (entry.name.endsWith(".template")) {
730
739
  const content = buffer.toString("utf8").replace(/__PROJECT_NAME__/g, context.projectName);
731
- await fs5.writeFile(destPath, content, "utf8");
740
+ await import_promises5.default.writeFile(destPath, content, "utf8");
732
741
  } else {
733
- await fs5.writeFile(destPath, buffer);
742
+ await import_promises5.default.writeFile(destPath, buffer);
734
743
  }
735
744
  }
736
745
  }
@@ -741,7 +750,7 @@ async function installDependencies(packageManager, cwd) {
741
750
  }
742
751
  function runCommand(command, args, cwd) {
743
752
  return new Promise((resolve, reject) => {
744
- const child = spawn(command, args, { cwd, stdio: "inherit" });
753
+ const child = (0, import_node_child_process.spawn)(command, args, { cwd, stdio: "inherit" });
745
754
  child.on("error", reject);
746
755
  child.on("close", (code) => {
747
756
  if (code === 0) resolve();
@@ -760,35 +769,25 @@ function printSuccessMessage(config) {
760
769
  const cdCommand = `cd ${config.projectName}`;
761
770
  const installCommand = config.packageManager === "npm" ? "npm install" : `${config.packageManager} install`;
762
771
  const devCommand = config.packageManager === "npm" ? "npm run dev" : `${config.packageManager} dev`;
763
- console.log(pc5.green(`
772
+ console.log(import_picocolors5.default.green(`
764
773
  \u{1F389} Success! Created ${config.projectName}
765
774
  `));
766
775
  console.log("Next steps:");
767
- console.log(pc5.cyan(` ${cdCommand}`));
776
+ console.log(import_picocolors5.default.cyan(` ${cdCommand}`));
768
777
  if (config.noInstall) {
769
- console.log(pc5.cyan(` ${installCommand}`));
778
+ console.log(import_picocolors5.default.cyan(` ${installCommand}`));
770
779
  }
771
- console.log(pc5.cyan(` ${devCommand}`));
772
- console.log(pc5.gray("\nHappy coding with Collie! \u{1F415}\n"));
773
- }
774
-
775
- // src/nextjs-setup.ts
776
- import fs6 from "fs/promises";
777
- import { existsSync as existsSync2 } from "fs";
778
- import path6 from "path";
779
- import pc6 from "picocolors";
780
- import { detectNextDirectory } from "@collie-lang/next";
781
- function hasNextDependency(pkg) {
782
- return Boolean(pkg?.dependencies?.next || pkg?.devDependencies?.next);
780
+ console.log(import_picocolors5.default.cyan(` ${devCommand}`));
781
+ console.log(import_picocolors5.default.gray("\nHappy coding with Collie! \u{1F415}\n"));
783
782
  }
784
783
 
785
784
  // src/converter.ts
786
- import fs7 from "fs/promises";
787
- import path7 from "path";
788
- import { convertTsxToCollie } from "@collie-lang/compiler";
785
+ var import_promises6 = __toESM(require("fs/promises"));
786
+ var import_node_path6 = __toESM(require("path"));
787
+ var import_compiler5 = require("@collie-lang/compiler");
789
788
  async function convertFile(filepath, options = {}) {
790
- const source = await fs7.readFile(filepath, "utf8");
791
- const result = convertTsxToCollie(source, { filename: filepath });
789
+ const source = await import_promises6.default.readFile(filepath, "utf8");
790
+ const result = (0, import_compiler5.convertTsxToCollie)(source, { filename: filepath });
792
791
  const { collie, warnings } = result;
793
792
  let outputPath;
794
793
  if (options.write) {
@@ -796,13 +795,13 @@ async function convertFile(filepath, options = {}) {
796
795
  if (!options.overwrite) {
797
796
  const exists = await fileExists(outputPath);
798
797
  if (exists) {
799
- throw new Error(`${path7.relative(process.cwd(), outputPath)} already exists. Use --overwrite to replace.`);
798
+ throw new Error(`${import_node_path6.default.relative(process.cwd(), outputPath)} already exists. Use --overwrite to replace.`);
800
799
  }
801
800
  }
802
- await fs7.mkdir(path7.dirname(outputPath), { recursive: true });
803
- await fs7.writeFile(outputPath, collie, "utf8");
801
+ await import_promises6.default.mkdir(import_node_path6.default.dirname(outputPath), { recursive: true });
802
+ await import_promises6.default.writeFile(outputPath, collie, "utf8");
804
803
  if (options.removeOriginal) {
805
- await fs7.unlink(filepath);
804
+ await import_promises6.default.unlink(filepath);
806
805
  }
807
806
  }
808
807
  return { collie, warnings, outputPath };
@@ -812,7 +811,7 @@ function resolveOutputPath2(filepath) {
812
811
  }
813
812
  async function fileExists(filepath) {
814
813
  try {
815
- await fs7.access(filepath);
814
+ await import_promises6.default.access(filepath);
816
815
  return true;
817
816
  } catch {
818
817
  return false;
@@ -820,14 +819,13 @@ async function fileExists(filepath) {
820
819
  }
821
820
 
822
821
  // src/doctor.ts
823
- import { compileToJsx } from "@collie-lang/compiler";
824
- import fg3 from "fast-glob";
825
- import fs8 from "fs/promises";
826
- import { existsSync as existsSync3 } from "fs";
827
- import path8 from "path";
828
- import pc7 from "picocolors";
822
+ var import_compiler6 = require("@collie-lang/compiler");
823
+ var import_fast_glob3 = __toESM(require("fast-glob"));
824
+ var import_promises7 = __toESM(require("fs/promises"));
825
+ var import_node_fs2 = require("fs");
826
+ var import_node_path7 = __toESM(require("path"));
827
+ var import_picocolors6 = __toESM(require("picocolors"));
829
828
  var VITE_CONFIG_FILES = ["vite.config.ts", "vite.config.js", "vite.config.mts", "vite.config.mjs"];
830
- var NEXT_CONFIG_FILES = ["next.config.ts", "next.config.mjs", "next.config.js"];
831
829
  var DECLARATION_CANDIDATES = ["src/collie.d.ts", "app/collie.d.ts", "collie.d.ts"];
832
830
  async function runDoctor(options = {}) {
833
831
  const cwd = options.cwd ?? process.cwd();
@@ -847,12 +845,6 @@ async function runDoctor(options = {}) {
847
845
  results.push(viteDependency);
848
846
  }
849
847
  results.push(await checkViteConfig(context));
850
- } else if (buildInfo.type === "nextjs") {
851
- const nextDependency = checkDependency(context, "@collie-lang/next", "Collie Next.js integration", ["nextjs"]);
852
- if (nextDependency) {
853
- results.push(nextDependency);
854
- }
855
- results.push(await checkNextConfig(context));
856
848
  }
857
849
  results.push(await checkTypeDeclarations(context));
858
850
  results.push(await checkCollieFiles(context));
@@ -875,16 +867,16 @@ function filterDiagnostics(results, filter) {
875
867
  });
876
868
  }
877
869
  function printDoctorResults(results) {
878
- console.log(pc7.bold("collie doctor"));
879
- console.log(pc7.dim("Diagnosing your environment..."));
870
+ console.log(import_picocolors6.default.bold("collie doctor"));
871
+ console.log(import_picocolors6.default.dim("Diagnosing your environment..."));
880
872
  console.log("");
881
873
  let errors = 0;
882
874
  let warnings = 0;
883
875
  for (const result of results) {
884
- const icon = result.status === "pass" ? pc7.green("\u2714") : result.status === "warn" ? pc7.yellow("\u26A0") : pc7.red("\u2716");
876
+ const icon = result.status === "pass" ? import_picocolors6.default.green("\u2714") : result.status === "warn" ? import_picocolors6.default.yellow("\u26A0") : import_picocolors6.default.red("\u2716");
885
877
  console.log(`${icon} ${result.check}: ${result.message}`);
886
878
  if (result.fix) {
887
- console.log(pc7.dim(` Fix: ${result.fix}`));
879
+ console.log(import_picocolors6.default.dim(` Fix: ${result.fix}`));
888
880
  }
889
881
  console.log("");
890
882
  if (result.status === "fail") {
@@ -963,19 +955,6 @@ function detectBuildSystem(context) {
963
955
  };
964
956
  }
965
957
  const hasVite = hasDependency(context.packageJson, "vite");
966
- const hasNext = hasDependency(context.packageJson, "next");
967
- if (hasVite && hasNext) {
968
- return {
969
- type: "vite",
970
- result: {
971
- id: "build-system",
972
- check: "Build system",
973
- status: "warn",
974
- message: "Both Vite and Next.js detected (defaulting to Vite)",
975
- tags: ["build"]
976
- }
977
- };
978
- }
979
958
  if (hasVite) {
980
959
  return {
981
960
  type: "vite",
@@ -988,26 +967,14 @@ function detectBuildSystem(context) {
988
967
  }
989
968
  };
990
969
  }
991
- if (hasNext) {
992
- return {
993
- type: "nextjs",
994
- result: {
995
- id: "build-system",
996
- check: "Build system",
997
- status: "pass",
998
- message: "Next.js detected",
999
- tags: ["build", "nextjs"]
1000
- }
1001
- };
1002
- }
1003
970
  return {
1004
971
  type: null,
1005
972
  result: {
1006
973
  id: "build-system",
1007
974
  check: "Build system",
1008
975
  status: "warn",
1009
- message: "No Vite or Next.js dependency found",
1010
- fix: "Install Vite or Next.js for the best Collie experience.",
976
+ message: "No Vite dependency found",
977
+ fix: "Install Vite for the best Collie experience.",
1011
978
  tags: ["build"]
1012
979
  }
1013
980
  };
@@ -1037,9 +1004,9 @@ function checkDependency(context, dependency, label, tags) {
1037
1004
  }
1038
1005
  async function checkViteConfig(context) {
1039
1006
  for (const filename of VITE_CONFIG_FILES) {
1040
- const configPath = path8.join(context.cwd, filename);
1041
- if (!existsSync3(configPath)) continue;
1042
- const contents = await fs8.readFile(configPath, "utf8");
1007
+ const configPath = import_node_path7.default.join(context.cwd, filename);
1008
+ if (!(0, import_node_fs2.existsSync)(configPath)) continue;
1009
+ const contents = await import_promises7.default.readFile(configPath, "utf8");
1043
1010
  const hasPlugin = /@collie-lang\/vite/.test(contents) && /collie\s*\(/.test(contents);
1044
1011
  if (hasPlugin) {
1045
1012
  return {
@@ -1068,43 +1035,10 @@ async function checkViteConfig(context) {
1068
1035
  tags: ["vite", "config"]
1069
1036
  };
1070
1037
  }
1071
- async function checkNextConfig(context) {
1072
- for (const filename of NEXT_CONFIG_FILES) {
1073
- const configPath = path8.join(context.cwd, filename);
1074
- if (!existsSync3(configPath)) continue;
1075
- const contents = await fs8.readFile(configPath, "utf8");
1076
- const hasLoader = /@collie-lang\/next/.test(contents) || /withCollie\s*\(/.test(contents);
1077
- if (hasLoader) {
1078
- return {
1079
- id: "next-config",
1080
- check: "Next.js config",
1081
- status: "pass",
1082
- message: `Collie loader configured in ${filename}`,
1083
- tags: ["nextjs", "config"]
1084
- };
1085
- }
1086
- return {
1087
- id: "next-config",
1088
- check: "Next.js config",
1089
- status: "fail",
1090
- message: `Found ${filename} but Collie loader not configured`,
1091
- fix: "Wrap your Next.js config with withCollie() or run collie init --nextjs.",
1092
- tags: ["nextjs", "config"]
1093
- };
1094
- }
1095
- return {
1096
- id: "next-config",
1097
- check: "Next.js config",
1098
- status: "fail",
1099
- message: "Next.js config not found",
1100
- fix: "Create next.config.js and configure withCollie().",
1101
- tags: ["nextjs", "config"]
1102
- };
1103
- }
1104
1038
  async function checkTypeDeclarations(context) {
1105
1039
  for (const relativePath of DECLARATION_CANDIDATES) {
1106
- const fullPath = path8.join(context.cwd, relativePath);
1107
- if (existsSync3(fullPath)) {
1040
+ const fullPath = import_node_path7.default.join(context.cwd, relativePath);
1041
+ if ((0, import_node_fs2.existsSync)(fullPath)) {
1108
1042
  return {
1109
1043
  id: "type-declarations",
1110
1044
  check: "Type declarations",
@@ -1124,7 +1058,7 @@ async function checkTypeDeclarations(context) {
1124
1058
  };
1125
1059
  }
1126
1060
  async function checkCollieFiles(context) {
1127
- const files = await fg3("**/*.collie", {
1061
+ const files = await (0, import_fast_glob3.default)("**/*.collie", {
1128
1062
  cwd: context.cwd,
1129
1063
  ignore: ["node_modules/**", "dist/**", ".next/**"],
1130
1064
  absolute: false
@@ -1152,7 +1086,7 @@ async function testCompilation() {
1152
1086
  "\n"
1153
1087
  );
1154
1088
  try {
1155
- const result = compileToJsx(template, { componentNameHint: "DoctorCheck" });
1089
+ const result = (0, import_compiler6.compileToJsx)(template, { componentNameHint: "DoctorCheck" });
1156
1090
  const hasError = result.diagnostics.some((diag) => diag.severity === "error");
1157
1091
  if (hasError) {
1158
1092
  return {
@@ -1184,8 +1118,8 @@ async function testCompilation() {
1184
1118
  }
1185
1119
  async function readPackageJson(cwd) {
1186
1120
  try {
1187
- const pkgPath = path8.join(cwd, "package.json");
1188
- const raw = await fs8.readFile(pkgPath, "utf8");
1121
+ const pkgPath = import_node_path7.default.join(cwd, "package.json");
1122
+ const raw = await import_promises7.default.readFile(pkgPath, "utf8");
1189
1123
  return JSON.parse(raw);
1190
1124
  } catch {
1191
1125
  return null;
@@ -1205,7 +1139,7 @@ function formatDependencyVersion(spec) {
1205
1139
  }
1206
1140
 
1207
1141
  // src/index.ts
1208
- var VITE_CONFIG_FILES2 = ["vite.config.ts", "vite.config.mts", "vite.config.js", "vite.config.mjs"];
1142
+ var VITE_CONFIG_PATTERNS = ["vite.config.ts", "vite.config.js", "vite.config.mjs", "vite.config.cjs"];
1209
1143
  var TAILWIND_CONFIG_FILES = [
1210
1144
  "tailwind.config.js",
1211
1145
  "tailwind.config.cjs",
@@ -1231,21 +1165,14 @@ var CLI_DEPENDENCY_SPECS = CLI_PACKAGE_INFO.dependencies;
1231
1165
  var DEFAULT_DEPENDENCY_RANGE = CLI_PACKAGE_VERSION === "latest" ? "latest" : `^${CLI_PACKAGE_VERSION}`;
1232
1166
  var COLLIE_COMPILER_DEPENDENCY = formatCollieDependency("@collie-lang/compiler");
1233
1167
  var COLLIE_VITE_DEPENDENCY = formatCollieDependency("@collie-lang/vite");
1234
- var COLLIE_NEXT_DEPENDENCY = formatCollieDependency("@collie-lang/next");
1235
- var COLLIE_NEXT_VERSION_RANGE = normalizeDependencyRange(
1236
- CLI_DEPENDENCY_SPECS["@collie-lang/next"],
1237
- DEFAULT_DEPENDENCY_RANGE
1238
- );
1239
1168
  var COLLIE_CORE_PACKAGES = ["@collie-lang/compiler", "@collie-lang/config"];
1240
1169
  var COLLIE_VITE_PACKAGES = [
1241
1170
  ...COLLIE_CORE_PACKAGES,
1242
- "@collie-lang/vite",
1243
- "@collie-lang/html-runtime"
1171
+ "@collie-lang/vite"
1244
1172
  ];
1245
- var COLLIE_NEXT_PACKAGES = [...COLLIE_CORE_PACKAGES, "@collie-lang/next"];
1246
1173
  var PROMPT_OPTIONS = {
1247
1174
  onCancel: () => {
1248
- console.log(pc8.yellow("\nCancelled"));
1175
+ console.log(import_picocolors7.default.yellow("\nCancelled"));
1249
1176
  process.exit(0);
1250
1177
  }
1251
1178
  };
@@ -1301,7 +1228,7 @@ async function main() {
1301
1228
  printCliError(
1302
1229
  `Exceeded maximum warnings: ${result.warningCount} warning${result.warningCount === 1 ? "" : "s"} (limit ${maxWarnings})`
1303
1230
  );
1304
- console.error(pc8.dim("Next: fix warnings or raise --max-warnings."));
1231
+ console.error(import_picocolors7.default.dim("Next: fix warnings or raise --max-warnings."));
1305
1232
  process.exitCode = 1;
1306
1233
  }
1307
1234
  return;
@@ -1343,7 +1270,7 @@ async function main() {
1343
1270
  }
1344
1271
  const filePath = getFlag(rest, "--file");
1345
1272
  const cwdFlag = getFlag(rest, "--cwd");
1346
- const cwd = cwdFlag ? path9.resolve(process.cwd(), cwdFlag) : filePath ? path9.dirname(path9.resolve(process.cwd(), filePath)) : process.cwd();
1273
+ const cwd = cwdFlag ? import_node_path8.default.resolve(process.cwd(), cwdFlag) : filePath ? import_node_path8.default.dirname(import_node_path8.default.resolve(process.cwd(), filePath)) : process.cwd();
1347
1274
  let loadAndNormalizeConfig;
1348
1275
  try {
1349
1276
  ({ loadAndNormalizeConfig } = await import("@collie-lang/config"));
@@ -1371,7 +1298,7 @@ async function main() {
1371
1298
  }
1372
1299
  const templateListRequested = hasFlag(flagArgs, "--list-templates");
1373
1300
  if (templateListRequested) {
1374
- console.log(pc8.bold("Available templates:\n"));
1301
+ console.log(import_picocolors7.default.bold("Available templates:\n"));
1375
1302
  console.log(formatTemplateList());
1376
1303
  console.log("\nRun collie create <project-name> --template <template> to scaffold with a specific option.\n");
1377
1304
  return;
@@ -1405,7 +1332,7 @@ async function main() {
1405
1332
  if (removeOriginal && !write) {
1406
1333
  throw new Error("--remove-original can only be used with --write.");
1407
1334
  }
1408
- const files = await fg4(patterns, {
1335
+ const files = await (0, import_fast_glob4.default)(patterns, {
1409
1336
  absolute: false,
1410
1337
  onlyFiles: true,
1411
1338
  unique: true
@@ -1423,10 +1350,10 @@ async function main() {
1423
1350
  const result = await convertFile(file, options);
1424
1351
  if (write) {
1425
1352
  const target = result.outputPath ?? file.replace(/\.[tj]sx?$/, ".collie");
1426
- console.log(pc8.green(`\u2714 Converted ${file} \u2192 ${target}`));
1353
+ console.log(import_picocolors7.default.green(`\u2714 Converted ${file} \u2192 ${target}`));
1427
1354
  converted++;
1428
1355
  } else {
1429
- console.log(pc8.gray(`// Converted from ${file}
1356
+ console.log(import_picocolors7.default.gray(`// Converted from ${file}
1430
1357
  `));
1431
1358
  process.stdout.write(result.collie);
1432
1359
  if (!result.collie.endsWith("\n")) {
@@ -1435,11 +1362,11 @@ async function main() {
1435
1362
  console.log("");
1436
1363
  }
1437
1364
  for (const warning of result.warnings) {
1438
- console.warn(pc8.yellow(`\u26A0 ${file}: ${warning}`));
1365
+ console.warn(import_picocolors7.default.yellow(`\u26A0 ${file}: ${warning}`));
1439
1366
  }
1440
1367
  } catch (error) {
1441
1368
  const message = error instanceof Error ? error.message : String(error);
1442
- console.error(pc8.red(`\u2716 Failed to convert ${file}: ${message}`));
1369
+ console.error(import_picocolors7.default.red(`\u2716 Failed to convert ${file}: ${message}`));
1443
1370
  process.exitCode = 1;
1444
1371
  failed++;
1445
1372
  }
@@ -1472,7 +1399,7 @@ async function main() {
1472
1399
  const filtered = filterDiagnostics(results, subsystem);
1473
1400
  if (subsystem && filtered.length === 0) {
1474
1401
  printCliError(`Unknown subsystem for --check: ${subsystem}`);
1475
- console.error(pc8.dim("Next: run collie doctor to list available checks."));
1402
+ console.error(import_picocolors7.default.dim("Next: run collie doctor to list available checks."));
1476
1403
  process.exit(1);
1477
1404
  }
1478
1405
  if (jsonOutput) {
@@ -1560,7 +1487,7 @@ async function main() {
1560
1487
  throw new Error(`Unexpected argument(s): ${extraArgs.join(", ")}`);
1561
1488
  }
1562
1489
  const frameworkValue = getFlag(rest, "--framework");
1563
- const framework = (frameworkValue === "vite" || frameworkValue === "nextjs" ? frameworkValue : void 0) ?? (hasFlag(rest, "--nextjs") ? "nextjs" : void 0) ?? (hasFlag(rest, "--vite") ? "vite" : void 0);
1490
+ const framework = (frameworkValue === "vite" ? frameworkValue : void 0) ?? (hasFlag(rest, "--vite") ? "vite" : void 0);
1564
1491
  const typescriptFlag = hasFlag(rest, "--typescript");
1565
1492
  const javascriptFlag = hasFlag(rest, "--javascript");
1566
1493
  if (typescriptFlag && javascriptFlag) {
@@ -1602,7 +1529,7 @@ async function main() {
1602
1529
  process.exit(1);
1603
1530
  }
1604
1531
  function printHelp() {
1605
- console.log(`${pc8.bold("collie")}
1532
+ console.log(`${import_picocolors7.default.bold("collie")}
1606
1533
 
1607
1534
  Usage:
1608
1535
  collie <command> [options]
@@ -1701,7 +1628,7 @@ function formatTemplateLocation2(template) {
1701
1628
  function printTemplateDiagnostics(diagnostics) {
1702
1629
  for (const diag of diagnostics) {
1703
1630
  const message = formatDiagnosticLine(diag);
1704
- const writer = diag.severity === "warning" ? pc8.yellow : pc8.red;
1631
+ const writer = diag.severity === "warning" ? import_picocolors7.default.yellow : import_picocolors7.default.red;
1705
1632
  console.log(writer(message));
1706
1633
  }
1707
1634
  if (diagnostics.length) {
@@ -1711,23 +1638,65 @@ function printTemplateDiagnostics(diagnostics) {
1711
1638
  async function runInit(options = {}) {
1712
1639
  const projectRoot = process.cwd();
1713
1640
  const packageJson = await readProjectPackage(projectRoot);
1641
+ const viteConfigPath = findViteConfigPath(projectRoot);
1642
+ if (!viteConfigPath) {
1643
+ printCliError("No Vite config found. collie init currently requires a Vite project.");
1644
+ console.error(import_picocolors7.default.dim("Expected one of: vite.config.ts, vite.config.js, vite.config.mjs, vite.config.cjs"));
1645
+ process.exit(1);
1646
+ }
1647
+ if (!packageJson) {
1648
+ printCliError("No package.json found. collie init requires a Node.js project.");
1649
+ process.exit(1);
1650
+ }
1651
+ const missing = computeMissingCollieDeps(packageJson);
1652
+ const hasAnyMissing = missing.missingRuntime.length > 0 || missing.missingDev.length > 0;
1653
+ if (hasAnyMissing) {
1654
+ const packageManager = options.packageManager ?? detectPackageManager2(projectRoot);
1655
+ const versionSpec = getCollieVersionSpec(packageJson);
1656
+ const runtimeSpecs = missing.missingRuntime.map((pkg) => {
1657
+ return versionSpec ? `${pkg}@${versionSpec}` : pkg;
1658
+ });
1659
+ const devSpecs = missing.missingDev.map((pkg) => {
1660
+ return versionSpec ? `${pkg}@${versionSpec}` : pkg;
1661
+ });
1662
+ if (options.noInstall) {
1663
+ const allMissing = [...missing.missingRuntime, ...missing.missingDev];
1664
+ console.log(import_picocolors7.default.yellow(`\u26A0 Missing required Collie packages: ${allMissing.join(", ")}`));
1665
+ console.log(import_picocolors7.default.dim("\nTo install, run:"));
1666
+ if (runtimeSpecs.length > 0) {
1667
+ const cmd = packageManager === "npm" ? `npm i ${runtimeSpecs.join(" ")}` : packageManager === "pnpm" ? `pnpm add ${runtimeSpecs.join(" ")}` : `yarn add ${runtimeSpecs.join(" ")}`;
1668
+ console.log(import_picocolors7.default.dim(` ${cmd}`));
1669
+ }
1670
+ if (devSpecs.length > 0) {
1671
+ const cmd = packageManager === "npm" ? `npm i -D ${devSpecs.join(" ")}` : packageManager === "pnpm" ? `pnpm add -D ${devSpecs.join(" ")}` : `yarn add -D ${devSpecs.join(" ")}`;
1672
+ console.log(import_picocolors7.default.dim(` ${cmd}`));
1673
+ }
1674
+ console.log("");
1675
+ } else {
1676
+ const totalMissing = missing.missingRuntime.length + missing.missingDev.length;
1677
+ console.log(import_picocolors7.default.cyan(`Installing ${totalMissing} missing Collie package${totalMissing === 1 ? "" : "s"}...`));
1678
+ await installPackages(packageManager, runtimeSpecs, devSpecs, projectRoot);
1679
+ console.log(import_picocolors7.default.green(`\u2714 Installed ${totalMissing} package${totalMissing === 1 ? "" : "s"}.`));
1680
+ console.log("");
1681
+ }
1682
+ }
1714
1683
  const detectedFramework = packageJson ? detectFrameworkFromPackage(packageJson) : null;
1715
1684
  const cssDetection = await detectCssStrategy(projectRoot, packageJson);
1716
1685
  const framework = options.framework ?? detectedFramework;
1717
1686
  const projectType = framework ? mapFrameworkToProjectType(framework) : await promptProjectType();
1718
1687
  const existingConfig = findExistingCollieConfig(projectRoot);
1719
- const targetPath = existingConfig ?? path9.join(projectRoot, "collie.config.ts");
1720
- const relativeTarget = path9.relative(projectRoot, targetPath) || path9.basename(targetPath);
1721
- console.log(pc8.bold("collie init"));
1722
- console.log(pc8.dim("This creates a Collie config and applies framework wiring when possible."));
1688
+ const targetPath = existingConfig ?? import_node_path8.default.join(projectRoot, "collie.config.ts");
1689
+ const relativeTarget = import_node_path8.default.relative(projectRoot, targetPath) || import_node_path8.default.basename(targetPath);
1690
+ console.log(import_picocolors7.default.bold("collie init"));
1691
+ console.log(import_picocolors7.default.dim("This creates a Collie config and applies framework wiring when possible."));
1723
1692
  if (framework) {
1724
- console.log(pc8.dim(`Detected ${formatFrameworkLabel(framework)} project.`));
1693
+ console.log(import_picocolors7.default.dim(`Detected ${formatFrameworkLabel(framework)} project.`));
1725
1694
  } else {
1726
- console.log(pc8.dim("No framework detected."));
1695
+ console.log(import_picocolors7.default.dim("No framework detected."));
1727
1696
  }
1728
- console.log(pc8.dim(`CSS strategy: ${formatCssDetection(cssDetection)}.`));
1729
- console.log(pc8.dim(`Override in ${relativeTarget} via css.strategy and css.diagnostics.unknownClass.`));
1730
- console.log(pc8.dim(`Project type: ${describeProjectType(projectType)}.`));
1697
+ console.log(import_picocolors7.default.dim(`CSS strategy: ${formatCssDetection(cssDetection)}.`));
1698
+ console.log(import_picocolors7.default.dim(`Override in ${relativeTarget} via css.strategy and css.diagnostics.unknownClass.`));
1699
+ console.log(import_picocolors7.default.dim(`Project type: ${describeProjectType(projectType)}.`));
1731
1700
  console.log("");
1732
1701
  const configLabel = framework === "vite" ? "Vite-ready" : "Collie";
1733
1702
  const confirmMessage = existingConfig ? `${relativeTarget} already exists. Replace it with a ${configLabel} config?` : `Create ${relativeTarget}?`;
@@ -1737,12 +1706,12 @@ async function runInit(options = {}) {
1737
1706
  printSummary("warning", "No changes made", detail, "run collie init when you are ready");
1738
1707
  return;
1739
1708
  }
1740
- const contents = buildInitConfig(projectType, path9.extname(targetPath).toLowerCase(), cssDetection);
1741
- await fs9.writeFile(targetPath, contents, "utf8");
1742
- const typeDeclarationsPath = path9.join(projectRoot, "src", "collie.d.ts");
1709
+ const contents = buildInitConfig(projectType, import_node_path8.default.extname(targetPath).toLowerCase(), cssDetection);
1710
+ await import_promises8.default.writeFile(targetPath, contents, "utf8");
1711
+ const typeDeclarationsPath = import_node_path8.default.join(projectRoot, "src", "collie.d.ts");
1743
1712
  let typeDeclarationsStatus = "skipped";
1744
1713
  if (projectType !== "html" && shouldWriteTypeDeclarations(projectRoot, options)) {
1745
- if (existsSync4(typeDeclarationsPath)) {
1714
+ if ((0, import_node_fs3.existsSync)(typeDeclarationsPath)) {
1746
1715
  typeDeclarationsStatus = "exists";
1747
1716
  } else {
1748
1717
  await ensureCollieDeclaration(projectRoot);
@@ -1750,9 +1719,7 @@ async function runInit(options = {}) {
1750
1719
  }
1751
1720
  }
1752
1721
  let viteConfigStatus = "skipped";
1753
- let viteConfigPath = null;
1754
1722
  if (framework === "vite") {
1755
- viteConfigPath = findViteConfigFile(projectRoot);
1756
1723
  if (viteConfigPath) {
1757
1724
  viteConfigStatus = await patchViteConfig(viteConfigPath);
1758
1725
  } else {
@@ -1761,32 +1728,32 @@ async function runInit(options = {}) {
1761
1728
  }
1762
1729
  printSummary("success", "Initialized Collie config", `created ${relativeTarget}`);
1763
1730
  if (typeDeclarationsStatus !== "skipped") {
1764
- const declarationLabel = path9.relative(projectRoot, typeDeclarationsPath) || path9.basename(typeDeclarationsPath);
1731
+ const declarationLabel = import_node_path8.default.relative(projectRoot, typeDeclarationsPath) || import_node_path8.default.basename(typeDeclarationsPath);
1765
1732
  if (typeDeclarationsStatus === "created") {
1766
- console.log(pc8.green(`\u2714 Added ${declarationLabel} for .collie typings`));
1733
+ console.log(import_picocolors7.default.green(`\u2714 Added ${declarationLabel} for .collie typings`));
1767
1734
  } else {
1768
- console.log(pc8.dim(`- ${declarationLabel} already exists`));
1735
+ console.log(import_picocolors7.default.dim(`- ${declarationLabel} already exists`));
1769
1736
  }
1770
1737
  } else if (projectType !== "html") {
1771
1738
  console.log(
1772
- pc8.dim("Skipping .collie typings (no TypeScript config found). Add src/collie.d.ts if you enable TypeScript.")
1739
+ import_picocolors7.default.dim("Skipping .collie typings (no TypeScript config found). Add src/collie.d.ts if you enable TypeScript.")
1773
1740
  );
1774
1741
  }
1775
1742
  if (framework === "vite") {
1776
1743
  if (viteConfigStatus === "patched" && viteConfigPath) {
1777
- console.log(pc8.green(`\u2714 Updated ${path9.relative(projectRoot, viteConfigPath) || path9.basename(viteConfigPath)}`));
1744
+ console.log(import_picocolors7.default.green(`\u2714 Updated ${import_node_path8.default.relative(projectRoot, viteConfigPath) || import_node_path8.default.basename(viteConfigPath)}`));
1778
1745
  } else if (viteConfigStatus === "already-configured" && viteConfigPath) {
1779
1746
  console.log(
1780
- pc8.dim(`- ${path9.relative(projectRoot, viteConfigPath) || path9.basename(viteConfigPath)} already includes collie()`)
1747
+ import_picocolors7.default.dim(`- ${import_node_path8.default.relative(projectRoot, viteConfigPath) || import_node_path8.default.basename(viteConfigPath)} already includes collie()`)
1781
1748
  );
1782
1749
  } else if (viteConfigStatus === "manual" && viteConfigPath) {
1783
1750
  console.log(
1784
- pc8.yellow(
1785
- `\u26A0 Could not patch ${path9.relative(projectRoot, viteConfigPath) || path9.basename(viteConfigPath)}. Add collie() manually to the Vite plugins array.`
1751
+ import_picocolors7.default.yellow(
1752
+ `\u26A0 Could not patch ${import_node_path8.default.relative(projectRoot, viteConfigPath) || import_node_path8.default.basename(viteConfigPath)}. Add collie() manually to the Vite plugins array.`
1786
1753
  )
1787
1754
  );
1788
1755
  } else if (viteConfigStatus === "not-found") {
1789
- console.log(pc8.yellow("\u26A0 Vite config not found. Add the Collie plugin to vite.config.ts manually."));
1756
+ console.log(import_picocolors7.default.yellow("\u26A0 Vite config not found. Add the Collie plugin to vite.config.ts manually."));
1790
1757
  }
1791
1758
  }
1792
1759
  if (framework === "vite") {
@@ -1794,36 +1761,32 @@ async function runInit(options = {}) {
1794
1761
  printNextSteps(pkgManager, targetPath);
1795
1762
  }
1796
1763
  if (!framework) {
1797
- console.log(pc8.dim(`Tip: update the project type in ${relativeTarget} if needed.`));
1764
+ console.log(import_picocolors7.default.dim(`Tip: update the project type in ${relativeTarget} if needed.`));
1798
1765
  }
1799
1766
  }
1800
1767
  async function readProjectPackage(projectRoot) {
1801
- const packageJsonPath = path9.join(projectRoot, "package.json");
1802
- if (!existsSync4(packageJsonPath)) {
1768
+ const packageJsonPath = import_node_path8.default.join(projectRoot, "package.json");
1769
+ if (!(0, import_node_fs3.existsSync)(packageJsonPath)) {
1803
1770
  return null;
1804
1771
  }
1805
- const raw = await fs9.readFile(packageJsonPath, "utf8");
1772
+ const raw = await import_promises8.default.readFile(packageJsonPath, "utf8");
1806
1773
  return JSON.parse(raw);
1807
1774
  }
1808
1775
  function detectFrameworkFromPackage(pkg) {
1809
- if (hasNextDependency(pkg)) {
1810
- return "nextjs";
1811
- }
1812
1776
  if (getViteDependencyInfo(pkg)) {
1813
1777
  return "vite";
1814
1778
  }
1815
1779
  return null;
1816
1780
  }
1817
1781
  function mapFrameworkToProjectType(framework) {
1818
- return framework === "nextjs" ? "react-next" : "react-vite";
1782
+ return "react-vite";
1819
1783
  }
1820
1784
  function formatFrameworkLabel(framework) {
1821
- return framework === "nextjs" ? "Next.js" : "Vite";
1785
+ return "Vite";
1822
1786
  }
1823
1787
  function describeProjectType(projectType) {
1824
1788
  const labels = {
1825
1789
  "react-vite": "React (Vite)",
1826
- "react-next": "React (Next.js)",
1827
1790
  "react-generic": "React (generic)",
1828
1791
  html: "HTML (no framework)"
1829
1792
  };
@@ -1836,14 +1799,14 @@ function shouldWriteTypeDeclarations(projectRoot, options) {
1836
1799
  if (options.typescript === true) {
1837
1800
  return true;
1838
1801
  }
1839
- return existsSync4(path9.join(projectRoot, "tsconfig.json"));
1802
+ return (0, import_node_fs3.existsSync)(import_node_path8.default.join(projectRoot, "tsconfig.json"));
1840
1803
  }
1841
1804
  async function detectCssStrategy(projectRoot, packageJson) {
1842
1805
  const reasons = [];
1843
1806
  try {
1844
1807
  let tailwindDetected = false;
1845
1808
  for (const filename of TAILWIND_CONFIG_FILES) {
1846
- if (existsSync4(path9.join(projectRoot, filename))) {
1809
+ if ((0, import_node_fs3.existsSync)(import_node_path8.default.join(projectRoot, filename))) {
1847
1810
  reasons.push(`${filename} found`);
1848
1811
  tailwindDetected = true;
1849
1812
  }
@@ -1891,11 +1854,11 @@ function hasTailwindDependency(pkg) {
1891
1854
  }
1892
1855
  async function scanPostcssForTailwind(projectRoot) {
1893
1856
  for (const filename of POSTCSS_CONFIG_FILES) {
1894
- const fullPath = path9.join(projectRoot, filename);
1895
- if (!existsSync4(fullPath)) {
1857
+ const fullPath = import_node_path8.default.join(projectRoot, filename);
1858
+ if (!(0, import_node_fs3.existsSync)(fullPath)) {
1896
1859
  continue;
1897
1860
  }
1898
- const contents = await fs9.readFile(fullPath, "utf8");
1861
+ const contents = await import_promises8.default.readFile(fullPath, "utf8");
1899
1862
  if (contents.includes("tailwindcss")) {
1900
1863
  return filename;
1901
1864
  }
@@ -1903,10 +1866,10 @@ async function scanPostcssForTailwind(projectRoot) {
1903
1866
  return null;
1904
1867
  }
1905
1868
  async function scanTopLevelCssForTailwind(projectRoot) {
1906
- const files = await fg4("*.css", { cwd: projectRoot, onlyFiles: true });
1869
+ const files = await (0, import_fast_glob4.default)("*.css", { cwd: projectRoot, onlyFiles: true });
1907
1870
  for (const filename of files) {
1908
- const fullPath = path9.join(projectRoot, filename);
1909
- const contents = await fs9.readFile(fullPath, "utf8");
1871
+ const fullPath = import_node_path8.default.join(projectRoot, filename);
1872
+ const contents = await import_promises8.default.readFile(fullPath, "utf8");
1910
1873
  if (/\@tailwind\s+(base|components|utilities)\b/.test(contents)) {
1911
1874
  return filename;
1912
1875
  }
@@ -1948,15 +1911,15 @@ function buildInitConfig(projectType, ext, cssDetection) {
1948
1911
  }
1949
1912
  function findExistingCollieConfig(root) {
1950
1913
  for (const filename of COLLIE_CONFIG_FILES) {
1951
- const candidate = path9.join(root, filename);
1952
- if (existsSync4(candidate)) {
1914
+ const candidate = import_node_path8.default.join(root, filename);
1915
+ if ((0, import_node_fs3.existsSync)(candidate)) {
1953
1916
  return candidate;
1954
1917
  }
1955
1918
  }
1956
1919
  return null;
1957
1920
  }
1958
1921
  async function promptForConfirmation(message, initial) {
1959
- const response = await prompts2(
1922
+ const response = await (0, import_prompts2.default)(
1960
1923
  {
1961
1924
  type: "confirm",
1962
1925
  name: "confirmed",
@@ -1968,14 +1931,13 @@ async function promptForConfirmation(message, initial) {
1968
1931
  return Boolean(response.confirmed);
1969
1932
  }
1970
1933
  async function promptProjectType() {
1971
- const response = await prompts2(
1934
+ const response = await (0, import_prompts2.default)(
1972
1935
  {
1973
1936
  type: "select",
1974
1937
  name: "projectType",
1975
1938
  message: "What type of project should this config describe?",
1976
1939
  choices: [
1977
1940
  { title: "React (Vite)", value: "react-vite" },
1978
- { title: "React (Next.js)", value: "react-next" },
1979
1941
  { title: "React (generic)", value: "react-generic" },
1980
1942
  { title: "HTML (no framework)", value: "html" }
1981
1943
  ],
@@ -1992,7 +1954,7 @@ async function runPreflight(command, options = {}) {
1992
1954
  preflightCompleted = true;
1993
1955
  const projectRoot = findProjectRoot(process.cwd());
1994
1956
  if (!projectRoot) {
1995
- console.log(pc8.dim("Skipping dependency preflight (no package.json found)."));
1957
+ console.log(import_picocolors7.default.dim("Skipping dependency preflight (no package.json found)."));
1996
1958
  return true;
1997
1959
  }
1998
1960
  let packageJson = null;
@@ -2000,11 +1962,11 @@ async function runPreflight(command, options = {}) {
2000
1962
  packageJson = await readProjectPackage(projectRoot);
2001
1963
  } catch (error) {
2002
1964
  const message = error instanceof Error ? error.message : String(error);
2003
- console.log(pc8.yellow(`Skipping dependency preflight: failed to read package.json (${message}).`));
1965
+ console.log(import_picocolors7.default.yellow(`Skipping dependency preflight: failed to read package.json (${message}).`));
2004
1966
  return true;
2005
1967
  }
2006
1968
  if (!packageJson) {
2007
- console.log(pc8.dim("Skipping dependency preflight (package.json not found)."));
1969
+ console.log(import_picocolors7.default.dim("Skipping dependency preflight (package.json not found)."));
2008
1970
  return true;
2009
1971
  }
2010
1972
  const detectedFramework = detectFrameworkFromPackage(packageJson);
@@ -2021,25 +1983,25 @@ async function runPreflight(command, options = {}) {
2021
1983
  const prompt = `Missing required Collie packages: ${missing.join(", ")}. Install now?`;
2022
1984
  const shouldInstall = await promptForConfirmation(prompt, true);
2023
1985
  if (!shouldInstall) {
2024
- console.log(pc8.yellow("Skipped installing Collie dependencies."));
1986
+ console.log(import_picocolors7.default.yellow("Skipped installing Collie dependencies."));
2025
1987
  console.log(
2026
- pc8.dim(`Next: ${formatInstallCommand(packageManager, missing)} && collie ${command}`)
1988
+ import_picocolors7.default.dim(`Next: ${formatInstallCommand(packageManager, missing)} && collie ${command}`)
2027
1989
  );
2028
1990
  return false;
2029
1991
  }
2030
1992
  const specs = missing.map((dep) => resolveDependencySpec(dep));
2031
- console.log(pc8.cyan(`Installing ${missing.length} Collie package${missing.length === 1 ? "" : "s"}...`));
1993
+ console.log(import_picocolors7.default.cyan(`Installing ${missing.length} Collie package${missing.length === 1 ? "" : "s"}...`));
2032
1994
  await installDevDependencies(packageManager, projectRoot, specs);
2033
- console.log(pc8.green(`\u2714 Installed ${missing.length} Collie package${missing.length === 1 ? "" : "s"}.`));
1995
+ console.log(import_picocolors7.default.green(`\u2714 Installed ${missing.length} Collie package${missing.length === 1 ? "" : "s"}.`));
2034
1996
  return true;
2035
1997
  }
2036
1998
  function findProjectRoot(startDir) {
2037
1999
  let current = startDir;
2038
2000
  while (true) {
2039
- if (existsSync4(path9.join(current, "package.json"))) {
2001
+ if ((0, import_node_fs3.existsSync)(import_node_path8.default.join(current, "package.json"))) {
2040
2002
  return current;
2041
2003
  }
2042
- const parent = path9.dirname(current);
2004
+ const parent = import_node_path8.default.dirname(current);
2043
2005
  if (parent === current) {
2044
2006
  return null;
2045
2007
  }
@@ -2050,9 +2012,6 @@ function getRequiredPackages(command, framework) {
2050
2012
  if (command === "check") {
2051
2013
  return ["@collie-lang/compiler"];
2052
2014
  }
2053
- if (framework === "nextjs") {
2054
- return [...COLLIE_NEXT_PACKAGES];
2055
- }
2056
2015
  if (framework === "vite") {
2057
2016
  return [...COLLIE_VITE_PACKAGES];
2058
2017
  }
@@ -2068,8 +2027,8 @@ function isDependencySatisfied(projectRoot, packageJson, dependency) {
2068
2027
  if (listed) {
2069
2028
  return true;
2070
2029
  }
2071
- const modulePath = path9.join(projectRoot, "node_modules", ...dependency.split("/"));
2072
- return existsSync4(modulePath);
2030
+ const modulePath = import_node_path8.default.join(projectRoot, "node_modules", ...dependency.split("/"));
2031
+ return (0, import_node_fs3.existsSync)(modulePath);
2073
2032
  }
2074
2033
  function resolveDependencySpec(packageName) {
2075
2034
  const range = normalizeDependencyRange(CLI_DEPENDENCY_SPECS[packageName], "latest");
@@ -2086,8 +2045,8 @@ function formatInstallCommand(packageManager, dependencies) {
2086
2045
  return `npm install -D ${specs.join(" ")}`;
2087
2046
  }
2088
2047
  function detectPackageManager2(root) {
2089
- if (existsSync4(path9.join(root, "pnpm-lock.yaml"))) return "pnpm";
2090
- if (existsSync4(path9.join(root, "yarn.lock"))) return "yarn";
2048
+ if ((0, import_node_fs3.existsSync)(import_node_path8.default.join(root, "pnpm-lock.yaml"))) return "pnpm";
2049
+ if ((0, import_node_fs3.existsSync)(import_node_path8.default.join(root, "yarn.lock"))) return "yarn";
2091
2050
  return "npm";
2092
2051
  }
2093
2052
  async function installDevDependencies(packageManager, cwd, deps) {
@@ -2099,7 +2058,7 @@ async function installDevDependencies(packageManager, cwd, deps) {
2099
2058
  await runCommand2(packageManager, argsByManager[packageManager], cwd);
2100
2059
  }
2101
2060
  async function patchViteConfig(configPath) {
2102
- const original = await fs9.readFile(configPath, "utf8");
2061
+ const original = await import_promises8.default.readFile(configPath, "utf8");
2103
2062
  const hasImport = original.includes("@collie-lang/vite");
2104
2063
  const hasPlugin = /\bcollie\s*\(/.test(original);
2105
2064
  if (hasImport && hasPlugin) {
@@ -2110,37 +2069,37 @@ async function patchViteConfig(configPath) {
2110
2069
  if (!result.changed) {
2111
2070
  return "already-configured";
2112
2071
  }
2113
- await fs9.writeFile(configPath, result.code, "utf8");
2072
+ await import_promises8.default.writeFile(configPath, result.code, "utf8");
2114
2073
  return "patched";
2115
2074
  } catch (error) {
2116
2075
  return "manual";
2117
2076
  }
2118
2077
  }
2119
2078
  function transformViteConfig(source) {
2120
- const sourceFile = ts.createSourceFile(
2079
+ const sourceFile = import_typescript.default.createSourceFile(
2121
2080
  "vite.config.ts",
2122
2081
  source,
2123
- ts.ScriptTarget.Latest,
2082
+ import_typescript.default.ScriptTarget.Latest,
2124
2083
  true,
2125
- ts.ScriptKind.TS
2084
+ import_typescript.default.ScriptKind.TS
2126
2085
  );
2127
2086
  let needsImport = !source.includes("@collie-lang/vite");
2128
2087
  let needsPlugin = !/\bcollie\s*\(/.test(source);
2129
2088
  let changed = false;
2130
- const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
2089
+ const printer = import_typescript.default.createPrinter({ newLine: import_typescript.default.NewLineKind.LineFeed });
2131
2090
  const transformer = (context) => {
2132
2091
  return (rootNode) => {
2133
2092
  function visit(node) {
2134
- if (needsImport && ts.isImportDeclaration(node)) {
2093
+ if (needsImport && import_typescript.default.isImportDeclaration(node)) {
2135
2094
  return node;
2136
2095
  }
2137
- if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "defineConfig" && node.arguments.length > 0) {
2096
+ if (import_typescript.default.isCallExpression(node) && import_typescript.default.isIdentifier(node.expression) && node.expression.text === "defineConfig" && node.arguments.length > 0) {
2138
2097
  const configArg = node.arguments[0];
2139
- if (ts.isObjectLiteralExpression(configArg)) {
2098
+ if (import_typescript.default.isObjectLiteralExpression(configArg)) {
2140
2099
  const updatedConfig = updateConfigObject(configArg);
2141
2100
  if (updatedConfig !== configArg) {
2142
2101
  changed = true;
2143
- return ts.factory.updateCallExpression(
2102
+ return import_typescript.default.factory.updateCallExpression(
2144
2103
  node,
2145
2104
  node.expression,
2146
2105
  node.typeArguments,
@@ -2149,42 +2108,42 @@ function transformViteConfig(source) {
2149
2108
  }
2150
2109
  }
2151
2110
  }
2152
- return ts.visitEachChild(node, visit, context);
2111
+ return import_typescript.default.visitEachChild(node, visit, context);
2153
2112
  }
2154
2113
  function updateConfigObject(configObj) {
2155
2114
  let pluginsProperty;
2156
2115
  const otherProperties = [];
2157
2116
  for (const prop of configObj.properties) {
2158
- if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === "plugins") {
2117
+ if (import_typescript.default.isPropertyAssignment(prop) && import_typescript.default.isIdentifier(prop.name) && prop.name.text === "plugins") {
2159
2118
  pluginsProperty = prop;
2160
2119
  } else {
2161
2120
  otherProperties.push(prop);
2162
2121
  }
2163
2122
  }
2164
2123
  let updatedPluginsArray;
2165
- if (pluginsProperty && ts.isArrayLiteralExpression(pluginsProperty.initializer)) {
2124
+ if (pluginsProperty && import_typescript.default.isArrayLiteralExpression(pluginsProperty.initializer)) {
2166
2125
  updatedPluginsArray = ensurePluginOrdering(pluginsProperty.initializer);
2167
2126
  if (updatedPluginsArray === pluginsProperty.initializer) {
2168
2127
  return configObj;
2169
2128
  }
2170
2129
  } else if (needsPlugin) {
2171
- updatedPluginsArray = ts.factory.createArrayLiteralExpression(
2130
+ updatedPluginsArray = import_typescript.default.factory.createArrayLiteralExpression(
2172
2131
  [createCollieCall()],
2173
2132
  false
2174
2133
  );
2175
2134
  } else {
2176
2135
  return configObj;
2177
2136
  }
2178
- const updatedPluginsProperty = ts.factory.createPropertyAssignment(
2137
+ const updatedPluginsProperty = import_typescript.default.factory.createPropertyAssignment(
2179
2138
  "plugins",
2180
2139
  updatedPluginsArray
2181
2140
  );
2182
2141
  if (pluginsProperty) {
2183
2142
  const allProperties = [...otherProperties, updatedPluginsProperty];
2184
- return ts.factory.updateObjectLiteralExpression(configObj, allProperties);
2143
+ return import_typescript.default.factory.updateObjectLiteralExpression(configObj, allProperties);
2185
2144
  } else {
2186
2145
  const allProperties = [...otherProperties, updatedPluginsProperty];
2187
- return ts.factory.updateObjectLiteralExpression(configObj, allProperties);
2146
+ return import_typescript.default.factory.updateObjectLiteralExpression(configObj, allProperties);
2188
2147
  }
2189
2148
  }
2190
2149
  function ensurePluginOrdering(array) {
@@ -2194,7 +2153,7 @@ function transformViteConfig(source) {
2194
2153
  let reactIndex = -1;
2195
2154
  let collieIndex = -1;
2196
2155
  elements.forEach((elem, idx) => {
2197
- if (ts.isCallExpression(elem) && ts.isIdentifier(elem.expression)) {
2156
+ if (import_typescript.default.isCallExpression(elem) && import_typescript.default.isIdentifier(elem.expression)) {
2198
2157
  if (elem.expression.text === "react") {
2199
2158
  hasReact = true;
2200
2159
  reactIndex = idx;
@@ -2212,37 +2171,37 @@ function transformViteConfig(source) {
2212
2171
  const colliePlugin = newElements[collieIndex];
2213
2172
  newElements[collieIndex] = reactPlugin;
2214
2173
  newElements[reactIndex] = colliePlugin;
2215
- return ts.factory.createArrayLiteralExpression(newElements, isMultiLine);
2174
+ return import_typescript.default.factory.createArrayLiteralExpression(newElements, isMultiLine);
2216
2175
  }
2217
2176
  return array;
2218
2177
  }
2219
2178
  if (!hasCollie && needsPlugin) {
2220
2179
  const newElements = [...elements, createCollieCall()];
2221
- return ts.factory.createArrayLiteralExpression(newElements, isMultiLine);
2180
+ return import_typescript.default.factory.createArrayLiteralExpression(newElements, isMultiLine);
2222
2181
  }
2223
2182
  return array;
2224
2183
  }
2225
2184
  function createCollieCall() {
2226
- return ts.factory.createCallExpression(
2227
- ts.factory.createIdentifier("collie"),
2185
+ return import_typescript.default.factory.createCallExpression(
2186
+ import_typescript.default.factory.createIdentifier("collie"),
2228
2187
  void 0,
2229
2188
  []
2230
2189
  );
2231
2190
  }
2232
- const visited = ts.visitNode(rootNode, visit);
2191
+ const visited = import_typescript.default.visitNode(rootNode, visit);
2233
2192
  if (needsImport && changed) {
2234
- const collieImport = ts.factory.createImportDeclaration(
2193
+ const collieImport = import_typescript.default.factory.createImportDeclaration(
2235
2194
  void 0,
2236
- ts.factory.createImportClause(
2195
+ import_typescript.default.factory.createImportClause(
2237
2196
  false,
2238
- ts.factory.createIdentifier("collie"),
2197
+ import_typescript.default.factory.createIdentifier("collie"),
2239
2198
  void 0
2240
2199
  ),
2241
- ts.factory.createStringLiteral("@collie-lang/vite", true)
2200
+ import_typescript.default.factory.createStringLiteral("@collie-lang/vite", true)
2242
2201
  );
2243
2202
  let lastImportIndex = -1;
2244
2203
  for (let i = 0; i < visited.statements.length; i++) {
2245
- if (ts.isImportDeclaration(visited.statements[i])) {
2204
+ if (import_typescript.default.isImportDeclaration(visited.statements[i])) {
2246
2205
  lastImportIndex = i;
2247
2206
  }
2248
2207
  }
@@ -2252,12 +2211,12 @@ function transformViteConfig(source) {
2252
2211
  } else {
2253
2212
  statements.unshift(collieImport);
2254
2213
  }
2255
- return ts.factory.updateSourceFile(visited, statements);
2214
+ return import_typescript.default.factory.updateSourceFile(visited, statements);
2256
2215
  }
2257
2216
  return visited;
2258
2217
  };
2259
2218
  };
2260
- const result = ts.transform(sourceFile, [transformer]);
2219
+ const result = import_typescript.default.transform(sourceFile, [transformer]);
2261
2220
  const transformedSourceFile = result.transformed[0];
2262
2221
  result.dispose();
2263
2222
  if (!changed) {
@@ -2267,9 +2226,9 @@ function transformViteConfig(source) {
2267
2226
  return { code: output, changed: true };
2268
2227
  }
2269
2228
  async function ensureCollieDeclaration(root) {
2270
- const target = path9.join(root, "src", "collie.d.ts");
2271
- if (existsSync4(target)) return;
2272
- await fs9.mkdir(path9.dirname(target), { recursive: true });
2229
+ const target = import_node_path8.default.join(root, "src", "collie.d.ts");
2230
+ if ((0, import_node_fs3.existsSync)(target)) return;
2231
+ await import_promises8.default.mkdir(import_node_path8.default.dirname(target), { recursive: true });
2273
2232
  const declaration = `// Allows importing Collie templates as React components.
2274
2233
  // Customize this typing if your templates expose specific props.
2275
2234
  declare module "*.collie" {
@@ -2278,22 +2237,67 @@ declare module "*.collie" {
2278
2237
  export default component;
2279
2238
  }
2280
2239
  `;
2281
- await fs9.writeFile(target, declaration, "utf8");
2240
+ await import_promises8.default.writeFile(target, declaration, "utf8");
2282
2241
  }
2283
- function findViteConfigFile(root) {
2284
- for (const file of VITE_CONFIG_FILES2) {
2285
- const candidate = path9.join(root, file);
2286
- if (existsSync4(candidate)) {
2242
+ function findViteConfigPath(projectRoot) {
2243
+ for (const filename of VITE_CONFIG_PATTERNS) {
2244
+ const candidate = import_node_path8.default.join(projectRoot, filename);
2245
+ if ((0, import_node_fs3.existsSync)(candidate)) {
2287
2246
  return candidate;
2288
2247
  }
2289
2248
  }
2290
2249
  return null;
2291
2250
  }
2251
+ function getCollieVersionSpec(packageJson) {
2252
+ if (!packageJson) return null;
2253
+ const cliSpec = packageJson.dependencies?.["@collie-lang/cli"] || packageJson.devDependencies?.["@collie-lang/cli"];
2254
+ if (!cliSpec) return null;
2255
+ if (cliSpec.startsWith("workspace:") || cliSpec.startsWith("file:")) {
2256
+ return null;
2257
+ }
2258
+ return cliSpec;
2259
+ }
2260
+ function computeMissingCollieDeps(packageJson) {
2261
+ const missingRuntime = [];
2262
+ const missingDev = [];
2263
+ if (!packageJson) {
2264
+ return { missingRuntime, missingDev };
2265
+ }
2266
+ const deps = packageJson.dependencies || {};
2267
+ const devDeps = packageJson.devDependencies || {};
2268
+ const reactInDeps = "@collie-lang/react" in deps;
2269
+ const reactInDevDeps = "@collie-lang/react" in devDeps;
2270
+ if (!reactInDeps) {
2271
+ missingRuntime.push("@collie-lang/react");
2272
+ }
2273
+ const requiredDevPackages = [
2274
+ "@collie-lang/vite",
2275
+ "@collie-lang/compiler",
2276
+ "@collie-lang/config"
2277
+ ];
2278
+ for (const pkg of requiredDevPackages) {
2279
+ const inDeps = pkg in deps;
2280
+ const inDevDeps = pkg in devDeps;
2281
+ if (!inDeps && !inDevDeps) {
2282
+ missingDev.push(pkg);
2283
+ }
2284
+ }
2285
+ return { missingRuntime, missingDev };
2286
+ }
2287
+ async function installPackages(packageManager, runtimePkgs, devPkgs, cwd) {
2288
+ if (runtimePkgs.length > 0) {
2289
+ const args = packageManager === "npm" ? ["install", ...runtimePkgs] : packageManager === "pnpm" ? ["add", ...runtimePkgs] : ["add", ...runtimePkgs];
2290
+ await runCommand2(packageManager, args, cwd);
2291
+ }
2292
+ if (devPkgs.length > 0) {
2293
+ const args = packageManager === "npm" ? ["install", "-D", ...devPkgs] : packageManager === "pnpm" ? ["add", "-D", ...devPkgs] : ["add", "-D", ...devPkgs];
2294
+ await runCommand2(packageManager, args, cwd);
2295
+ }
2296
+ }
2292
2297
  function readCliPackageInfo() {
2293
2298
  try {
2294
- const dir = path9.dirname(fileURLToPath2(import.meta.url));
2295
- const pkgPath = path9.resolve(dir, "..", "package.json");
2296
- const raw = readFileSync(pkgPath, "utf8");
2299
+ const pkgPath = import_node_path8.default.resolve(__dirname, "..", "package.json");
2300
+ const raw = (0, import_node_fs3.readFileSync)(pkgPath, "utf8");
2297
2301
  const pkg = JSON.parse(raw);
2298
2302
  const version = typeof pkg.version === "string" ? pkg.version : "latest";
2299
2303
  const dependencies = pkg && typeof pkg === "object" && pkg.dependencies && typeof pkg.dependencies === "object" ? pkg.dependencies : {};
@@ -2325,10 +2329,10 @@ function getViteDependencyInfo(pkg) {
2325
2329
  function printNextSteps(pkgManager, configPath) {
2326
2330
  const devCommand = formatDevCommand(pkgManager);
2327
2331
  console.log("");
2328
- console.log(pc8.green("Next steps:"));
2332
+ console.log(import_picocolors7.default.green("Next steps:"));
2329
2333
  console.log(` - Create a Collie template under src (e.g. src/Hello.collie).`);
2330
2334
  console.log(` - Import it in your React app and run ${devCommand} to start Vite.`);
2331
- console.log(` - Need to adjust plugins later? Edit ${path9.basename(configPath)}.`);
2335
+ console.log(` - Need to adjust plugins later? Edit ${import_node_path8.default.basename(configPath)}.`);
2332
2336
  }
2333
2337
  function formatDevCommand(pkgManager) {
2334
2338
  if (pkgManager === "pnpm") return "pnpm dev";
@@ -2337,7 +2341,7 @@ function formatDevCommand(pkgManager) {
2337
2341
  }
2338
2342
  function runCommand2(command, args, cwd) {
2339
2343
  return new Promise((resolve, reject) => {
2340
- const child = spawn2(command, args, { cwd, stdio: "inherit" });
2344
+ const child = (0, import_node_child_process2.spawn)(command, args, { cwd, stdio: "inherit" });
2341
2345
  child.on("error", reject);
2342
2346
  child.on("close", (code) => {
2343
2347
  if (code === 0) resolve();
@@ -2352,7 +2356,7 @@ async function runFormat(args) {
2352
2356
  }
2353
2357
  const indent = flags.indent ?? 2;
2354
2358
  const cwd = process.cwd();
2355
- const files = await fg4(patterns, { cwd, onlyFiles: true, unique: true });
2359
+ const files = await (0, import_fast_glob4.default)(patterns, { cwd, onlyFiles: true, unique: true });
2356
2360
  if (!files.length) {
2357
2361
  printSummary("warning", "No files matched the provided patterns", void 0, "check the glob and try again");
2358
2362
  return;
@@ -2364,10 +2368,10 @@ async function runFormat(args) {
2364
2368
  for (const file of files) {
2365
2369
  let contents;
2366
2370
  try {
2367
- contents = await fs9.readFile(file, "utf8");
2371
+ contents = await import_promises8.default.readFile(file, "utf8");
2368
2372
  } catch (error) {
2369
2373
  const message = error instanceof Error ? error.message : String(error);
2370
- console.error(pc8.red(`\u2716 Failed to read ${file}: ${message}`));
2374
+ console.error(import_picocolors7.default.red(`\u2716 Failed to read ${file}: ${message}`));
2371
2375
  failures++;
2372
2376
  continue;
2373
2377
  }
@@ -2376,7 +2380,7 @@ async function runFormat(args) {
2376
2380
  result = formatSource(contents, { indent });
2377
2381
  } catch (error) {
2378
2382
  const message = error instanceof Error ? error.message : String(error);
2379
- console.error(pc8.red(`\u2716 Failed to format ${file}: ${message}`));
2383
+ console.error(import_picocolors7.default.red(`\u2716 Failed to format ${file}: ${message}`));
2380
2384
  failures++;
2381
2385
  continue;
2382
2386
  }
@@ -2391,20 +2395,20 @@ async function runFormat(args) {
2391
2395
  }
2392
2396
  if (flags.check) {
2393
2397
  if (changed) {
2394
- console.log(pc8.red(`\u2716 ${file} needs formatting`));
2398
+ console.log(import_picocolors7.default.red(`\u2716 ${file} needs formatting`));
2395
2399
  needsFormatting++;
2396
2400
  } else {
2397
- console.log(pc8.green(`\u2714 ${file} is formatted`));
2401
+ console.log(import_picocolors7.default.green(`\u2714 ${file} is formatted`));
2398
2402
  }
2399
2403
  continue;
2400
2404
  }
2401
2405
  if (flags.write) {
2402
2406
  if (changed) {
2403
- await fs9.writeFile(file, result.formatted, "utf8");
2407
+ await import_promises8.default.writeFile(file, result.formatted, "utf8");
2404
2408
  written++;
2405
- console.log(pc8.green(`\u2714 Formatted ${file}`));
2409
+ console.log(import_picocolors7.default.green(`\u2714 Formatted ${file}`));
2406
2410
  } else {
2407
- console.log(pc8.dim(`- ${file} already formatted`));
2411
+ console.log(import_picocolors7.default.dim(`- ${file} already formatted`));
2408
2412
  }
2409
2413
  continue;
2410
2414
  }
@@ -2420,7 +2424,7 @@ async function runFormat(args) {
2420
2424
  `${needsFormatting} file${needsFormatting === 1 ? "" : "s"} need formatting`,
2421
2425
  "no files changed"
2422
2426
  );
2423
- console.log(pc8.dim("Run: collie format --write to fix"));
2427
+ console.log(import_picocolors7.default.dim("Run: collie format --write to fix"));
2424
2428
  process.exitCode = 1;
2425
2429
  } else if (failures > 0) {
2426
2430
  printSummary(
@@ -2502,18 +2506,18 @@ function printDiagnostics(file, diagnostics) {
2502
2506
  for (const diag of diagnostics) {
2503
2507
  const message = formatDiagnosticLine({ ...diag, file }, file);
2504
2508
  if (diag.severity === "warning") {
2505
- console.warn(pc8.yellow(message));
2509
+ console.warn(import_picocolors7.default.yellow(message));
2506
2510
  } else {
2507
- console.error(pc8.red(message));
2511
+ console.error(import_picocolors7.default.red(message));
2508
2512
  }
2509
2513
  }
2510
2514
  }
2511
2515
  function printDiff(file, before, after) {
2512
- console.log(pc8.cyan(`diff -- ${file}`));
2513
- const diff = diffLines(before, after);
2516
+ console.log(import_picocolors7.default.cyan(`diff -- ${file}`));
2517
+ const diff = (0, import_diff.diffLines)(before, after);
2514
2518
  for (const part of diff) {
2515
2519
  const prefix = part.added ? "+" : part.removed ? "-" : " ";
2516
- const color = part.added ? pc8.green : part.removed ? pc8.red : pc8.dim;
2520
+ const color = part.added ? import_picocolors7.default.green : part.removed ? import_picocolors7.default.red : import_picocolors7.default.dim;
2517
2521
  const lines = part.value.split("\n");
2518
2522
  for (let i = 0; i < lines.length; i++) {
2519
2523
  const line = lines[i];
@@ -2554,7 +2558,7 @@ function validateFormatFlag(value) {
2554
2558
  throw new Error('Invalid --format flag. Use "text" or "json".');
2555
2559
  }
2556
2560
  function printCliError(message) {
2557
- console.error(pc8.red(`\u2716 ${message}`));
2561
+ console.error(import_picocolors7.default.red(`\u2716 ${message}`));
2558
2562
  }
2559
2563
  main().catch((error) => {
2560
2564
  printCliError(error instanceof Error ? error.message : String(error));