@nextsparkjs/cli 0.1.0-beta.10 → 0.1.0-beta.100

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/bin/nextspark.js CHANGED
@@ -1,3 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // Check Node.js version before importing anything
4
+ const nodeVersion = parseInt(process.versions.node.split('.')[0], 10);
5
+ if (nodeVersion < 18) {
6
+ console.error('\x1b[31m✗ NextSpark requires Node.js 18 or higher\x1b[0m');
7
+ console.error(` Current version: ${process.versions.node}`);
8
+ console.error(' Please upgrade Node.js: https://nodejs.org/');
9
+ process.exit(1);
10
+ }
11
+
3
12
  import '../dist/cli.js';
@@ -0,0 +1,10 @@
1
+ import {
2
+ addPlugin,
3
+ addPluginCommand
4
+ } from "./chunk-5GBCARGX.js";
5
+ import "./chunk-DGUM43GV.js";
6
+ export {
7
+ addPlugin,
8
+ addPluginCommand
9
+ };
10
+ //# sourceMappingURL=add-plugin-Q7DOR7XO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -151,60 +151,21 @@ function validateTheme(packageJson, extractedPath) {
151
151
  }
152
152
 
153
153
  // src/lib/installer.ts
154
- import { existsSync as existsSync5, cpSync, rmSync as rmSync2, mkdirSync } from "fs";
155
- import { join as join5 } from "path";
154
+ import { existsSync as existsSync4, cpSync, rmSync as rmSync2, mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
155
+ import { join as join4 } from "path";
156
156
  import chalk from "chalk";
157
157
 
158
- // src/lib/package-manager.ts
159
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
160
- import { join as join3 } from "path";
161
- import { execSync as execSync2 } from "child_process";
162
- function detectPackageManager() {
163
- const cwd = process.cwd();
164
- if (existsSync3(join3(cwd, "pnpm-lock.yaml"))) return "pnpm";
165
- if (existsSync3(join3(cwd, "yarn.lock"))) return "yarn";
166
- if (existsSync3(join3(cwd, "package-lock.json"))) return "npm";
167
- const pkgPath = join3(cwd, "package.json");
168
- if (existsSync3(pkgPath)) {
169
- try {
170
- const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
171
- if (pkg.packageManager) {
172
- if (pkg.packageManager.startsWith("pnpm")) return "pnpm";
173
- if (pkg.packageManager.startsWith("yarn")) return "yarn";
174
- }
175
- } catch {
176
- }
177
- }
178
- return "npm";
179
- }
180
- function getInstallCommand(pm, deps) {
181
- const depsStr = deps.join(" ");
182
- switch (pm) {
183
- case "pnpm":
184
- return `pnpm add ${depsStr}`;
185
- case "yarn":
186
- return `yarn add ${depsStr}`;
187
- default:
188
- return `npm install ${depsStr}`;
189
- }
190
- }
191
- async function runInstall(pm, deps) {
192
- if (deps.length === 0) return;
193
- const command = getInstallCommand(pm, deps);
194
- execSync2(command, { stdio: "inherit", cwd: process.cwd() });
195
- }
196
-
197
158
  // src/lib/config-updater.ts
198
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync } from "fs";
199
- import { join as join4 } from "path";
159
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "fs";
160
+ import { join as join3 } from "path";
200
161
  async function updateTsConfig(name, type) {
201
- const tsconfigPath = join4(process.cwd(), "tsconfig.json");
202
- if (!existsSync4(tsconfigPath)) {
162
+ const tsconfigPath = join3(process.cwd(), "tsconfig.json");
163
+ if (!existsSync3(tsconfigPath)) {
203
164
  console.log(" Warning: tsconfig.json not found, skipping path update");
204
165
  return;
205
166
  }
206
167
  try {
207
- const content = readFileSync4(tsconfigPath, "utf-8");
168
+ const content = readFileSync3(tsconfigPath, "utf-8");
208
169
  const tsconfig = JSON.parse(content);
209
170
  if (!tsconfig.compilerOptions) {
210
171
  tsconfig.compilerOptions = {};
@@ -224,13 +185,13 @@ async function updateTsConfig(name, type) {
224
185
  }
225
186
  }
226
187
  async function registerInPackageJson(npmName, version, type) {
227
- const pkgPath = join4(process.cwd(), "package.json");
228
- if (!existsSync4(pkgPath)) {
188
+ const pkgPath = join3(process.cwd(), "package.json");
189
+ if (!existsSync3(pkgPath)) {
229
190
  console.log(" Warning: package.json not found, skipping registration");
230
191
  return;
231
192
  }
232
193
  try {
233
- const content = readFileSync4(pkgPath, "utf-8");
194
+ const content = readFileSync3(pkgPath, "utf-8");
234
195
  const pkg = JSON.parse(content);
235
196
  if (!pkg.nextspark) {
236
197
  pkg.nextspark = {};
@@ -258,7 +219,7 @@ async function registerInPackageJson(npmName, version, type) {
258
219
  // src/lib/installer.ts
259
220
  async function installPlugin(extractedPath, packageJson, options = {}) {
260
221
  const pluginName = extractPluginName(packageJson.name);
261
- const targetDir = join5(process.cwd(), "contents", "plugins", pluginName);
222
+ const targetDir = join4(process.cwd(), "contents", "plugins", pluginName);
262
223
  if (options.dryRun) {
263
224
  console.log(chalk.cyan("\n [Dry Run] Would perform:"));
264
225
  console.log(` - Copy to: contents/plugins/${pluginName}/`);
@@ -269,7 +230,7 @@ async function installPlugin(extractedPath, packageJson, options = {}) {
269
230
  console.log(` - Register in package.json`);
270
231
  return { success: true, installedPath: targetDir, name: pluginName };
271
232
  }
272
- if (existsSync5(targetDir)) {
233
+ if (existsSync4(targetDir)) {
273
234
  if (!options.force) {
274
235
  throw new Error(
275
236
  `Plugin "${pluginName}" already exists at ${targetDir}.
@@ -279,24 +240,20 @@ Use --force to overwrite.`
279
240
  console.log(chalk.yellow(` Removing existing plugin...`));
280
241
  rmSync2(targetDir, { recursive: true, force: true });
281
242
  }
282
- const pluginsDir = join5(process.cwd(), "contents", "plugins");
283
- if (!existsSync5(pluginsDir)) {
243
+ const pluginsDir = join4(process.cwd(), "contents", "plugins");
244
+ if (!existsSync4(pluginsDir)) {
284
245
  mkdirSync(pluginsDir, { recursive: true });
285
246
  }
286
247
  console.log(` Copying to contents/plugins/${pluginName}/...`);
287
248
  cpSync(extractedPath, targetDir, { recursive: true });
288
- if (!options.skipDeps) {
289
- const deps = packageJson.dependencies || {};
290
- const depNames = Object.keys(deps);
291
- if (depNames.length > 0) {
292
- console.log(` Installing ${depNames.length} dependencies...`);
293
- const pm = detectPackageManager();
294
- const depsWithVersions = Object.entries(deps).map(([name, version]) => `${name}@${version}`);
295
- await runInstall(pm, depsWithVersions);
296
- }
249
+ const deps = packageJson.dependencies || {};
250
+ const depCount = Object.keys(deps).length;
251
+ if (depCount > 0) {
252
+ console.log(` Plugin has ${depCount} dependencies (will be installed via workspace)`);
297
253
  }
298
254
  await updateTsConfig(pluginName, "plugin");
299
255
  await registerInPackageJson(packageJson.name, packageJson.version || "0.0.0", "plugin");
256
+ await registerPluginInThemeConfig(pluginName);
300
257
  return {
301
258
  success: true,
302
259
  installedPath: targetDir,
@@ -305,7 +262,7 @@ Use --force to overwrite.`
305
262
  }
306
263
  async function installTheme(extractedPath, packageJson, options = {}) {
307
264
  const themeName = extractThemeName(packageJson.name);
308
- const targetDir = join5(process.cwd(), "contents", "themes", themeName);
265
+ const targetDir = join4(process.cwd(), "contents", "themes", themeName);
309
266
  if (options.dryRun) {
310
267
  console.log(chalk.cyan("\n [Dry Run] Would perform:"));
311
268
  console.log(` - Copy to: contents/themes/${themeName}/`);
@@ -316,7 +273,7 @@ async function installTheme(extractedPath, packageJson, options = {}) {
316
273
  console.log(` - Register in package.json`);
317
274
  return { success: true, installedPath: targetDir, name: themeName };
318
275
  }
319
- if (existsSync5(targetDir)) {
276
+ if (existsSync4(targetDir)) {
320
277
  if (!options.force) {
321
278
  throw new Error(
322
279
  `Theme "${themeName}" already exists at ${targetDir}.
@@ -326,8 +283,8 @@ Use --force to overwrite.`
326
283
  console.log(chalk.yellow(` Removing existing theme...`));
327
284
  rmSync2(targetDir, { recursive: true, force: true });
328
285
  }
329
- const themesDir = join5(process.cwd(), "contents", "themes");
330
- if (!existsSync5(themesDir)) {
286
+ const themesDir = join4(process.cwd(), "contents", "themes");
287
+ if (!existsSync4(themesDir)) {
331
288
  mkdirSync(themesDir, { recursive: true });
332
289
  }
333
290
  console.log(` Copying to contents/themes/${themeName}/...`);
@@ -346,23 +303,59 @@ function extractPluginName(npmName) {
346
303
  function extractThemeName(npmName) {
347
304
  return npmName.replace(/^@[^/]+\//, "").replace(/^nextspark-theme-/, "").replace(/^theme-/, "");
348
305
  }
306
+ async function registerPluginInThemeConfig(pluginName) {
307
+ const envPath = join4(process.cwd(), ".env");
308
+ let activeTheme = "starter";
309
+ if (existsSync4(envPath)) {
310
+ const envContent = readFileSync4(envPath, "utf-8");
311
+ const match = envContent.match(/NEXT_PUBLIC_ACTIVE_THEME=["']?([^"'\s\n]+)["']?/);
312
+ if (match) {
313
+ activeTheme = match[1];
314
+ }
315
+ }
316
+ const themeConfigPath = join4(process.cwd(), "contents", "themes", activeTheme, "config", "theme.config.ts");
317
+ if (!existsSync4(themeConfigPath)) {
318
+ console.log(chalk.gray(` Theme config not found, skipping plugin registration`));
319
+ return;
320
+ }
321
+ try {
322
+ let content = readFileSync4(themeConfigPath, "utf-8");
323
+ if (content.includes(`'${pluginName}'`) || content.includes(`"${pluginName}"`)) {
324
+ console.log(chalk.gray(` Plugin ${pluginName} already registered in theme config`));
325
+ return;
326
+ }
327
+ const pluginsArrayMatch = content.match(/plugins:\s*\[([^\]]*)\]/s);
328
+ if (pluginsArrayMatch) {
329
+ const existingPlugins = pluginsArrayMatch[1].trim();
330
+ const newPlugins = existingPlugins ? `${existingPlugins}, '${pluginName}'` : `'${pluginName}'`;
331
+ content = content.replace(
332
+ /plugins:\s*\[([^\]]*)\]/s,
333
+ `plugins: [${newPlugins}]`
334
+ );
335
+ writeFileSync2(themeConfigPath, content);
336
+ console.log(` Registered plugin in theme.config.ts`);
337
+ }
338
+ } catch (error) {
339
+ console.log(chalk.yellow(` Could not register plugin in theme config: ${error}`));
340
+ }
341
+ }
349
342
 
350
343
  // src/lib/postinstall/index.ts
351
344
  import chalk6 from "chalk";
352
345
 
353
346
  // src/lib/postinstall/templates.ts
354
- import { existsSync as existsSync6, cpSync as cpSync2, mkdirSync as mkdirSync2 } from "fs";
355
- import { join as join6, dirname } from "path";
347
+ import { existsSync as existsSync5, cpSync as cpSync2, mkdirSync as mkdirSync2 } from "fs";
348
+ import { join as join5, dirname } from "path";
356
349
  import chalk2 from "chalk";
357
350
  async function processTemplates(templates, sourcePath, context) {
358
351
  for (const template of templates) {
359
- const from = join6(sourcePath, template.from);
352
+ const from = join5(sourcePath, template.from);
360
353
  const to = resolveVariables(template.to, context);
361
- if (!existsSync6(from)) {
354
+ if (!existsSync5(from)) {
362
355
  console.log(chalk2.yellow(` Warning: Template source not found: ${template.from}`));
363
356
  continue;
364
357
  }
365
- const targetExists = existsSync6(to);
358
+ const targetExists = existsSync5(to);
366
359
  const condition = template.condition || "!exists";
367
360
  const desc = template.description || template.to;
368
361
  switch (condition) {
@@ -388,7 +381,7 @@ async function processTemplates(templates, sourcePath, context) {
388
381
  break;
389
382
  }
390
383
  const parentDir = dirname(to);
391
- if (!existsSync6(parentDir)) {
384
+ if (!existsSync5(parentDir)) {
392
385
  mkdirSync2(parentDir, { recursive: true });
393
386
  }
394
387
  console.log(chalk2.gray(` Copying ${desc}...`));
@@ -414,21 +407,21 @@ function resolveVariables(path, context) {
414
407
  throw new Error(`Unresolved template variable: ${unresolvedMatch[0]}`);
415
408
  }
416
409
  if (!resolved.startsWith("/")) {
417
- resolved = join6(context.projectRoot, resolved);
410
+ resolved = join5(context.projectRoot, resolved);
418
411
  }
419
412
  return resolved;
420
413
  }
421
414
 
422
415
  // src/lib/postinstall/env-vars.ts
423
- import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync2, appendFileSync } from "fs";
424
- import { join as join7 } from "path";
416
+ import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync3, appendFileSync } from "fs";
417
+ import { join as join6 } from "path";
425
418
  import chalk3 from "chalk";
426
419
  async function processEnvVars(envVars) {
427
- const envExamplePath = join7(process.cwd(), ".env.example");
428
- const envPath = join7(process.cwd(), ".env");
420
+ const envExamplePath = join6(process.cwd(), ".env.example");
421
+ const envPath = join6(process.cwd(), ".env");
429
422
  let added = 0;
430
423
  const existingVars = /* @__PURE__ */ new Set();
431
- if (existsSync7(envExamplePath)) {
424
+ if (existsSync6(envExamplePath)) {
432
425
  const content = readFileSync5(envExamplePath, "utf-8");
433
426
  const matches = content.match(/^[A-Z_][A-Z0-9_]*=/gm);
434
427
  if (matches) {
@@ -449,34 +442,34 @@ async function processEnvVars(envVars) {
449
442
  }
450
443
  if (newLines.length > 0) {
451
444
  const content = "\n" + newLines.join("\n");
452
- if (existsSync7(envExamplePath)) {
445
+ if (existsSync6(envExamplePath)) {
453
446
  appendFileSync(envExamplePath, content);
454
447
  } else {
455
- writeFileSync2(envExamplePath, content.trim() + "\n");
448
+ writeFileSync3(envExamplePath, content.trim() + "\n");
456
449
  }
457
450
  console.log(chalk3.gray(` Added ${added} env vars to .env.example`));
458
451
  }
459
452
  }
460
453
 
461
454
  // src/lib/postinstall/migrations.ts
462
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, cpSync as cpSync3 } from "fs";
463
- import { join as join8, basename } from "path";
455
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3, cpSync as cpSync3 } from "fs";
456
+ import { join as join7, basename } from "path";
464
457
  import chalk4 from "chalk";
465
458
  async function registerMigrations(migrations, installedPath) {
466
- const migrationsDir = join8(process.cwd(), "migrations");
467
- if (!existsSync8(migrationsDir)) {
459
+ const migrationsDir = join7(process.cwd(), "migrations");
460
+ if (!existsSync7(migrationsDir)) {
468
461
  mkdirSync3(migrationsDir, { recursive: true });
469
462
  }
470
463
  let copied = 0;
471
464
  for (const migration of migrations) {
472
- const sourcePath = join8(installedPath, migration);
473
- if (!existsSync8(sourcePath)) {
465
+ const sourcePath = join7(installedPath, migration);
466
+ if (!existsSync7(sourcePath)) {
474
467
  console.log(chalk4.yellow(` Warning: Migration not found: ${migration}`));
475
468
  continue;
476
469
  }
477
470
  const fileName = basename(migration);
478
- const targetPath = join8(migrationsDir, fileName);
479
- if (existsSync8(targetPath)) {
471
+ const targetPath = join7(migrationsDir, fileName);
472
+ if (existsSync7(targetPath)) {
480
473
  console.log(chalk4.gray(` Migration ${fileName} already exists, skipping`));
481
474
  continue;
482
475
  }
@@ -489,12 +482,12 @@ async function registerMigrations(migrations, installedPath) {
489
482
  }
490
483
 
491
484
  // src/lib/postinstall/script-runner.ts
492
- import { existsSync as existsSync9 } from "fs";
493
- import { join as join9 } from "path";
485
+ import { existsSync as existsSync8 } from "fs";
486
+ import { join as join8 } from "path";
494
487
  import chalk5 from "chalk";
495
488
  async function runCustomScript(scriptPath, installedPath, context) {
496
- const fullPath = join9(installedPath, scriptPath);
497
- if (!existsSync9(fullPath)) {
489
+ const fullPath = join8(installedPath, scriptPath);
490
+ if (!existsSync8(fullPath)) {
498
491
  console.log(chalk5.yellow(` Warning: Postinstall script not found: ${scriptPath}`));
499
492
  return;
500
493
  }
@@ -509,8 +502,8 @@ async function runCustomScript(scriptPath, installedPath, context) {
509
502
  }
510
503
 
511
504
  // src/lib/postinstall/index.ts
512
- import { existsSync as existsSync10 } from "fs";
513
- import { join as join10 } from "path";
505
+ import { existsSync as existsSync9 } from "fs";
506
+ import { join as join9 } from "path";
514
507
  async function runPostinstall(packageJson, installedPath, context) {
515
508
  const postinstall = packageJson.nextspark?.postinstall;
516
509
  if (!postinstall) {
@@ -527,7 +520,7 @@ async function runPostinstall(packageJson, installedPath, context) {
527
520
  if (!pluginExists) {
528
521
  console.log(` Installing required plugin: ${plugin}`);
529
522
  context.installingPlugins.add(plugin);
530
- const { addPlugin: addPlugin2 } = await import("./add-plugin-GCPJ4FHE.js");
523
+ const { addPlugin: addPlugin2 } = await import("./add-plugin-Q7DOR7XO.js");
531
524
  await addPlugin2(plugin, { installingPlugins: context.installingPlugins });
532
525
  }
533
526
  }
@@ -571,18 +564,18 @@ async function runPostinstall(packageJson, installedPath, context) {
571
564
  }
572
565
  async function checkPluginExists(pluginName) {
573
566
  const name = pluginName.replace(/^@[^/]+\//, "").replace(/^nextspark-plugin-/, "").replace(/^plugin-/, "");
574
- return existsSync10(join10(process.cwd(), "contents", "plugins", name));
567
+ return existsSync9(join9(process.cwd(), "contents", "plugins", name));
575
568
  }
576
569
 
577
570
  // src/lib/theme-detector.ts
578
- import { existsSync as existsSync11, readFileSync as readFileSync6, readdirSync as readdirSync2 } from "fs";
579
- import { join as join11 } from "path";
571
+ import { existsSync as existsSync10, readFileSync as readFileSync6, readdirSync as readdirSync2 } from "fs";
572
+ import { join as join10 } from "path";
580
573
  function detectActiveTheme() {
581
574
  if (process.env.NEXT_PUBLIC_ACTIVE_THEME) {
582
575
  return process.env.NEXT_PUBLIC_ACTIVE_THEME;
583
576
  }
584
- const configPath = join11(process.cwd(), "nextspark.config.ts");
585
- if (existsSync11(configPath)) {
577
+ const configPath = join10(process.cwd(), "nextspark.config.ts");
578
+ if (existsSync10(configPath)) {
586
579
  try {
587
580
  const content = readFileSync6(configPath, "utf-8");
588
581
  const match = content.match(/activeTheme\s*:\s*['"]([^'"]+)['"]/);
@@ -592,8 +585,8 @@ function detectActiveTheme() {
592
585
  } catch {
593
586
  }
594
587
  }
595
- const envPath = join11(process.cwd(), ".env");
596
- if (existsSync11(envPath)) {
588
+ const envPath = join10(process.cwd(), ".env");
589
+ if (existsSync10(envPath)) {
597
590
  try {
598
591
  const content = readFileSync6(envPath, "utf-8");
599
592
  const match = content.match(/NEXT_PUBLIC_ACTIVE_THEME=(.+)/);
@@ -603,8 +596,8 @@ function detectActiveTheme() {
603
596
  } catch {
604
597
  }
605
598
  }
606
- const themesDir = join11(process.cwd(), "contents", "themes");
607
- if (existsSync11(themesDir)) {
599
+ const themesDir = join10(process.cwd(), "contents", "themes");
600
+ if (existsSync10(themesDir)) {
608
601
  try {
609
602
  const themes = readdirSync2(themesDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
610
603
  if (themes.length === 1) {
@@ -617,14 +610,14 @@ function detectActiveTheme() {
617
610
  }
618
611
 
619
612
  // src/commands/add-plugin.ts
620
- import { existsSync as existsSync12, readFileSync as readFileSync7 } from "fs";
621
- import { join as join12 } from "path";
613
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
614
+ import { join as join11 } from "path";
622
615
  async function addPlugin(packageSpec, options = {}) {
623
616
  const spinner = ora(`Adding plugin ${packageSpec}`).start();
624
617
  let cleanup = null;
625
618
  try {
626
- const contentsDir = join12(process.cwd(), "contents");
627
- if (!existsSync12(contentsDir)) {
619
+ const contentsDir = join11(process.cwd(), "contents");
620
+ if (!existsSync11(contentsDir)) {
628
621
  spinner.fail('contents/ directory not found. Run "nextspark init" first.');
629
622
  return;
630
623
  }
@@ -673,8 +666,8 @@ async function addPlugin(packageSpec, options = {}) {
673
666
  }
674
667
  }
675
668
  function getCoreVersion() {
676
- const pkgPath = join12(process.cwd(), "node_modules", "@nextsparkjs", "core", "package.json");
677
- if (existsSync12(pkgPath)) {
669
+ const pkgPath = join11(process.cwd(), "node_modules", "@nextsparkjs", "core", "package.json");
670
+ if (existsSync11(pkgPath)) {
678
671
  try {
679
672
  const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
680
673
  return pkg.version || "0.0.0";
@@ -698,7 +691,8 @@ export {
698
691
  fetchPackage,
699
692
  validateTheme,
700
693
  installTheme,
701
- runPostinstall,
702
694
  addPlugin,
703
- addPluginCommand
695
+ addPluginCommand,
696
+ runPostinstall
704
697
  };
698
+ //# sourceMappingURL=chunk-5GBCARGX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/add-plugin.ts","../src/lib/package-fetcher.ts","../src/lib/validator.ts","../src/lib/installer.ts","../src/lib/config-updater.ts","../src/lib/postinstall/index.ts","../src/lib/postinstall/templates.ts","../src/lib/postinstall/env-vars.ts","../src/lib/postinstall/migrations.ts","../src/lib/postinstall/script-runner.ts","../src/lib/theme-detector.ts"],"sourcesContent":["import chalk from 'chalk'\nimport ora from 'ora'\nimport { fetchPackage } from '../lib/package-fetcher.js'\nimport { validatePlugin } from '../lib/validator.js'\nimport { installPlugin } from '../lib/installer.js'\nimport { runPostinstall } from '../lib/postinstall/index.js'\nimport { detectActiveTheme } from '../lib/theme-detector.js'\nimport { existsSync, readFileSync } from 'fs'\nimport { join } from 'path'\nimport type { InstallOptions, PostinstallContext } from '../types/nextspark-package.js'\n\ninterface AddPluginOptions extends InstallOptions {\n installingPlugins?: Set<string>\n}\n\nexport async function addPlugin(\n packageSpec: string,\n options: AddPluginOptions = {}\n): Promise<void> {\n const spinner = ora(`Adding plugin ${packageSpec}`).start()\n\n let cleanup: (() => void) | null = null\n\n try {\n // Pre-checks\n const contentsDir = join(process.cwd(), 'contents')\n if (!existsSync(contentsDir)) {\n spinner.fail('contents/ directory not found. Run \"nextspark init\" first.')\n return\n }\n\n // Fetch package\n spinner.text = 'Downloading package...'\n const { packageJson, extractedPath, cleanup: cleanupFn } = await fetchPackage(\n packageSpec,\n options.version\n )\n cleanup = cleanupFn\n\n // Validate\n spinner.text = 'Validating plugin...'\n const validation = validatePlugin(packageJson, extractedPath)\n\n if (!validation.valid) {\n spinner.fail('Invalid plugin')\n validation.errors.forEach(e => console.log(chalk.red(` ✗ ${e}`)))\n return\n }\n\n if (validation.warnings.length > 0) {\n validation.warnings.forEach(w => console.log(chalk.yellow(` ⚠ ${w}`)))\n }\n\n // Install\n spinner.text = 'Installing plugin...'\n spinner.stop()\n\n const result = await installPlugin(extractedPath, packageJson, options)\n\n // Postinstall\n if (!options.skipPostinstall) {\n const coreVersion = getCoreVersion()\n const context: PostinstallContext = {\n activeTheme: detectActiveTheme(),\n projectRoot: process.cwd(),\n pluginName: result.name,\n coreVersion,\n timestamp: Date.now(),\n installingPlugins: options.installingPlugins || new Set([packageSpec])\n }\n\n await runPostinstall(packageJson, result.installedPath, context)\n }\n\n console.log(chalk.green(`\\n ✓ Plugin ${result.name} installed successfully!`))\n console.log(chalk.gray(` Location: contents/plugins/${result.name}/`))\n\n } catch (error) {\n spinner.fail('Failed to add plugin')\n if (error instanceof Error) {\n console.log(chalk.red(` ${error.message}`))\n }\n throw error\n } finally {\n if (cleanup) cleanup()\n }\n}\n\nfunction getCoreVersion(): string {\n const pkgPath = join(process.cwd(), 'node_modules', '@nextsparkjs', 'core', 'package.json')\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))\n return pkg.version || '0.0.0'\n } catch {\n return '0.0.0'\n }\n }\n return '0.0.0'\n}\n\nexport function addPluginCommand(packageSpec: string, options: Record<string, unknown>): Promise<void> {\n return addPlugin(packageSpec, {\n force: options.force as boolean,\n skipDeps: options.noDeps as boolean,\n dryRun: options.dryRun as boolean,\n skipPostinstall: options.skipPostinstall as boolean,\n version: options.version as string\n })\n}\n","import { execSync } from 'child_process'\nimport { mkdtempSync, readdirSync, rmSync, existsSync, readFileSync, copyFileSync } from 'fs'\nimport { tmpdir } from 'os'\nimport { join, isAbsolute } from 'path'\nimport * as tar from 'tar'\nimport type { NextSparkPackageJson, FetchResult } from '../types/nextspark-package.js'\n\nexport async function fetchPackage(\n packageSpec: string,\n version?: string\n): Promise<FetchResult> {\n // Detectar si es path local\n if (packageSpec.endsWith('.tgz') || packageSpec.startsWith('./') || packageSpec.startsWith('/') || isAbsolute(packageSpec)) {\n return fetchLocalPackage(packageSpec)\n }\n\n return fetchNpmPackage(packageSpec, version)\n}\n\nasync function fetchLocalPackage(filePath: string): Promise<FetchResult> {\n const absolutePath = isAbsolute(filePath)\n ? filePath\n : join(process.cwd(), filePath)\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Local package not found: ${absolutePath}`)\n }\n\n const tempDir = mkdtempSync(join(tmpdir(), 'nextspark-add-'))\n\n try {\n // Copiar .tgz a temp y extraer\n const tgzPath = join(tempDir, 'package.tgz')\n copyFileSync(absolutePath, tgzPath)\n\n await tar.x({\n file: tgzPath,\n cwd: tempDir,\n })\n\n const extractedPath = join(tempDir, 'package')\n const packageJson = JSON.parse(\n readFileSync(join(extractedPath, 'package.json'), 'utf-8')\n )\n\n return {\n packageJson,\n extractedPath,\n cleanup: () => rmSync(tempDir, { recursive: true, force: true })\n }\n } catch (error) {\n rmSync(tempDir, { recursive: true, force: true })\n throw error\n }\n}\n\nasync function fetchNpmPackage(\n packageName: string,\n version?: string\n): Promise<FetchResult> {\n const spec = version ? `${packageName}@${version}` : packageName\n const tempDir = mkdtempSync(join(tmpdir(), 'nextspark-add-'))\n\n try {\n console.log(` Downloading ${spec}...`)\n\n // npm pack descarga el .tgz sin instalar\n execSync(`npm pack ${spec} --pack-destination \"${tempDir}\"`, {\n stdio: 'pipe',\n encoding: 'utf-8'\n })\n\n const tgzFile = readdirSync(tempDir).find(f => f.endsWith('.tgz'))\n if (!tgzFile) {\n throw new Error(`Failed to download package: ${spec}`)\n }\n\n await tar.x({\n file: join(tempDir, tgzFile),\n cwd: tempDir,\n })\n\n const extractedPath = join(tempDir, 'package')\n\n if (!existsSync(extractedPath)) {\n throw new Error(`Package extraction failed for: ${spec}`)\n }\n\n const packageJson = JSON.parse(\n readFileSync(join(extractedPath, 'package.json'), 'utf-8')\n )\n\n return {\n packageJson,\n extractedPath,\n cleanup: () => rmSync(tempDir, { recursive: true, force: true })\n }\n } catch (error) {\n rmSync(tempDir, { recursive: true, force: true })\n\n // Mejorar mensaje de error\n if (error instanceof Error) {\n if (error.message.includes('404') || error.message.includes('not found')) {\n throw new Error(`Package not found: ${spec}. Verify the package name exists on npm.`)\n }\n if (error.message.includes('ENETUNREACH') || error.message.includes('ENOTFOUND')) {\n throw new Error(`Network error. Check your internet connection.`)\n }\n }\n throw error\n }\n}\n","import { existsSync, readFileSync } from 'fs'\nimport { join } from 'path'\nimport type { NextSparkPackageJson, ValidationResult, PeerDepIssue } from '../types/nextspark-package.js'\n\nexport function validatePlugin(\n packageJson: NextSparkPackageJson,\n extractedPath: string\n): ValidationResult {\n const errors: string[] = []\n const warnings: string[] = []\n const peerDepIssues: PeerDepIssue[] = []\n\n // 1. Verificar plugin.config.ts\n if (!existsSync(join(extractedPath, 'plugin.config.ts'))) {\n errors.push('Missing plugin.config.ts - not a valid NextSpark plugin')\n }\n\n // 2. Verificar nextspark metadata\n if (!packageJson.nextspark) {\n warnings.push('Missing nextspark field in package.json (recommended)')\n } else if (packageJson.nextspark.type !== 'plugin') {\n warnings.push(`nextspark.type is \"${packageJson.nextspark.type}\", expected \"plugin\"`)\n }\n\n // 3. Verificar peerDependencies\n const peerDeps = packageJson.peerDependencies || {}\n if (!peerDeps['@nextsparkjs/core']) {\n warnings.push('Plugin should have @nextsparkjs/core as peerDependency')\n }\n\n // 4. Validar compatibilidad de peerDeps con proyecto\n const projectPkgPath = join(process.cwd(), 'package.json')\n if (existsSync(projectPkgPath)) {\n const projectPkg = JSON.parse(readFileSync(projectPkgPath, 'utf-8'))\n const projectDeps = {\n ...projectPkg.dependencies,\n ...projectPkg.devDependencies\n }\n\n for (const [name, required] of Object.entries(peerDeps)) {\n const installed = projectDeps[name]\n if (!installed) {\n peerDepIssues.push({\n name,\n required: required as string,\n installed: null,\n severity: 'warning'\n })\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n peerDepIssues\n }\n}\n\nexport function validateTheme(\n packageJson: NextSparkPackageJson,\n extractedPath: string\n): ValidationResult {\n const errors: string[] = []\n const warnings: string[] = []\n const peerDepIssues: PeerDepIssue[] = []\n\n // 1. Verificar config/theme.config.ts\n const configPath = join(extractedPath, 'config', 'theme.config.ts')\n if (!existsSync(configPath)) {\n errors.push('Missing config/theme.config.ts - not a valid NextSpark theme')\n }\n\n // 2. Verificar nextspark metadata\n if (!packageJson.nextspark) {\n warnings.push('Missing nextspark field in package.json (recommended)')\n } else if (packageJson.nextspark.type !== 'theme') {\n warnings.push(`nextspark.type is \"${packageJson.nextspark.type}\", expected \"theme\"`)\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n peerDepIssues\n }\n}\n","import { existsSync, cpSync, rmSync, mkdirSync, readFileSync, writeFileSync } from 'fs'\nimport { join } from 'path'\nimport chalk from 'chalk'\nimport type { NextSparkPackageJson, InstallOptions, InstallResult } from '../types/nextspark-package.js'\nimport { updateTsConfig, registerInPackageJson } from './config-updater.js'\n\nexport async function installPlugin(\n extractedPath: string,\n packageJson: NextSparkPackageJson,\n options: InstallOptions = {}\n): Promise<InstallResult> {\n const pluginName = extractPluginName(packageJson.name)\n const targetDir = join(process.cwd(), 'contents', 'plugins', pluginName)\n\n // Dry run: only show what would be done\n if (options.dryRun) {\n console.log(chalk.cyan('\\n [Dry Run] Would perform:'))\n console.log(` - Copy to: contents/plugins/${pluginName}/`)\n if (packageJson.dependencies && Object.keys(packageJson.dependencies).length > 0) {\n console.log(` - Install deps: ${Object.keys(packageJson.dependencies).join(', ')}`)\n }\n console.log(` - Update tsconfig.json paths`)\n console.log(` - Register in package.json`)\n return { success: true, installedPath: targetDir, name: pluginName }\n }\n\n // Check if already exists\n if (existsSync(targetDir)) {\n if (!options.force) {\n throw new Error(\n `Plugin \"${pluginName}\" already exists at ${targetDir}.\\n` +\n `Use --force to overwrite.`\n )\n }\n console.log(chalk.yellow(` Removing existing plugin...`))\n rmSync(targetDir, { recursive: true, force: true })\n }\n\n // Ensure contents/plugins directory exists\n const pluginsDir = join(process.cwd(), 'contents', 'plugins')\n if (!existsSync(pluginsDir)) {\n mkdirSync(pluginsDir, { recursive: true })\n }\n\n // Copy files\n console.log(` Copying to contents/plugins/${pluginName}/...`)\n cpSync(extractedPath, targetDir, { recursive: true })\n\n // Plugin dependencies are handled by pnpm workspaces\n // The pnpm-workspace.yaml includes contents/plugins/* so each plugin\n // gets its own node_modules when `pnpm install` is run at root\n const deps = packageJson.dependencies || {}\n const depCount = Object.keys(deps).length\n if (depCount > 0) {\n console.log(` Plugin has ${depCount} dependencies (will be installed via workspace)`)\n }\n\n // Update configs\n await updateTsConfig(pluginName, 'plugin')\n await registerInPackageJson(packageJson.name, packageJson.version || '0.0.0', 'plugin')\n\n // Register plugin in active theme's config\n await registerPluginInThemeConfig(pluginName)\n\n return {\n success: true,\n installedPath: targetDir,\n name: pluginName\n }\n}\n\nexport async function installTheme(\n extractedPath: string,\n packageJson: NextSparkPackageJson,\n options: InstallOptions = {}\n): Promise<InstallResult> {\n const themeName = extractThemeName(packageJson.name)\n const targetDir = join(process.cwd(), 'contents', 'themes', themeName)\n\n if (options.dryRun) {\n console.log(chalk.cyan('\\n [Dry Run] Would perform:'))\n console.log(` - Copy to: contents/themes/${themeName}/`)\n if (packageJson.requiredPlugins?.length) {\n console.log(` - Install required plugins: ${packageJson.requiredPlugins.join(', ')}`)\n }\n console.log(` - Update tsconfig.json paths`)\n console.log(` - Register in package.json`)\n return { success: true, installedPath: targetDir, name: themeName }\n }\n\n if (existsSync(targetDir)) {\n if (!options.force) {\n throw new Error(\n `Theme \"${themeName}\" already exists at ${targetDir}.\\n` +\n `Use --force to overwrite.`\n )\n }\n console.log(chalk.yellow(` Removing existing theme...`))\n rmSync(targetDir, { recursive: true, force: true })\n }\n\n // Ensure contents/themes directory exists\n const themesDir = join(process.cwd(), 'contents', 'themes')\n if (!existsSync(themesDir)) {\n mkdirSync(themesDir, { recursive: true })\n }\n\n // Copy files\n console.log(` Copying to contents/themes/${themeName}/...`)\n cpSync(extractedPath, targetDir, { recursive: true })\n\n // Update configs\n await updateTsConfig(themeName, 'theme')\n await registerInPackageJson(packageJson.name, packageJson.version || '0.0.0', 'theme')\n\n return {\n success: true,\n installedPath: targetDir,\n name: themeName\n }\n}\n\nfunction extractPluginName(npmName: string): string {\n return npmName\n .replace(/^@[^/]+\\//, '') // @scope/name → name\n .replace(/^nextspark-plugin-/, '') // nextspark-plugin-foo → foo\n .replace(/^plugin-/, '') // plugin-foo → foo\n}\n\nfunction extractThemeName(npmName: string): string {\n return npmName\n .replace(/^@[^/]+\\//, '') // @scope/name → name\n .replace(/^nextspark-theme-/, '') // nextspark-theme-foo → foo\n .replace(/^theme-/, '') // theme-foo → foo\n}\n\n/**\n * Register a plugin in the active theme's theme.config.ts\n */\nasync function registerPluginInThemeConfig(pluginName: string): Promise<void> {\n // Find active theme from .env\n const envPath = join(process.cwd(), '.env')\n let activeTheme = 'starter'\n\n if (existsSync(envPath)) {\n const envContent = readFileSync(envPath, 'utf-8')\n const match = envContent.match(/NEXT_PUBLIC_ACTIVE_THEME=[\"']?([^\"'\\s\\n]+)[\"']?/)\n if (match) {\n activeTheme = match[1]\n }\n }\n\n // Find theme.config.ts\n const themeConfigPath = join(process.cwd(), 'contents', 'themes', activeTheme, 'config', 'theme.config.ts')\n\n if (!existsSync(themeConfigPath)) {\n console.log(chalk.gray(` Theme config not found, skipping plugin registration`))\n return\n }\n\n try {\n let content = readFileSync(themeConfigPath, 'utf-8')\n\n // Check if plugin is already registered\n if (content.includes(`'${pluginName}'`) || content.includes(`\"${pluginName}\"`)) {\n console.log(chalk.gray(` Plugin ${pluginName} already registered in theme config`))\n return\n }\n\n // Find the plugins array and add the plugin\n // Match patterns like: plugins: [] or plugins: ['existing'] (supports multiline arrays)\n const pluginsArrayMatch = content.match(/plugins:\\s*\\[([^\\]]*)\\]/s)\n\n if (pluginsArrayMatch) {\n const existingPlugins = pluginsArrayMatch[1].trim()\n const newPlugins = existingPlugins\n ? `${existingPlugins}, '${pluginName}'`\n : `'${pluginName}'`\n\n content = content.replace(\n /plugins:\\s*\\[([^\\]]*)\\]/s,\n `plugins: [${newPlugins}]`\n )\n\n writeFileSync(themeConfigPath, content)\n console.log(` Registered plugin in theme.config.ts`)\n }\n } catch (error) {\n console.log(chalk.yellow(` Could not register plugin in theme config: ${error}`))\n }\n}\n","import { existsSync, readFileSync, writeFileSync } from 'fs'\nimport { join } from 'path'\n\nexport async function updateTsConfig(name: string, type: 'plugin' | 'theme'): Promise<void> {\n const tsconfigPath = join(process.cwd(), 'tsconfig.json')\n\n if (!existsSync(tsconfigPath)) {\n console.log(' Warning: tsconfig.json not found, skipping path update')\n return\n }\n\n try {\n const content = readFileSync(tsconfigPath, 'utf-8')\n const tsconfig = JSON.parse(content)\n\n if (!tsconfig.compilerOptions) {\n tsconfig.compilerOptions = {}\n }\n if (!tsconfig.compilerOptions.paths) {\n tsconfig.compilerOptions.paths = {}\n }\n\n const pathKey = type === 'plugin'\n ? `@plugins/${name}/*`\n : `@themes/${name}/*`\n\n const pathValue = type === 'plugin'\n ? [`./contents/plugins/${name}/*`]\n : [`./contents/themes/${name}/*`]\n\n // Solo añadir si no existe\n if (!tsconfig.compilerOptions.paths[pathKey]) {\n tsconfig.compilerOptions.paths[pathKey] = pathValue\n writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2) + '\\n')\n console.log(` Updated tsconfig.json with ${pathKey} path`)\n }\n } catch (error) {\n console.log(' Warning: Could not update tsconfig.json')\n }\n}\n\nexport async function registerInPackageJson(\n npmName: string,\n version: string,\n type: 'plugin' | 'theme'\n): Promise<void> {\n const pkgPath = join(process.cwd(), 'package.json')\n\n if (!existsSync(pkgPath)) {\n console.log(' Warning: package.json not found, skipping registration')\n return\n }\n\n try {\n const content = readFileSync(pkgPath, 'utf-8')\n const pkg = JSON.parse(content)\n\n if (!pkg.nextspark) {\n pkg.nextspark = {}\n }\n\n const key = type === 'plugin' ? 'plugins' : 'themes'\n if (!pkg.nextspark[key]) {\n pkg.nextspark[key] = []\n }\n\n // Registrar nombre y versión\n const entry = { name: npmName, version }\n const existingIndex = pkg.nextspark[key].findIndex(\n (e: { name: string }) => e.name === npmName\n )\n\n if (existingIndex >= 0) {\n pkg.nextspark[key][existingIndex] = entry\n } else {\n pkg.nextspark[key].push(entry)\n }\n\n writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n')\n console.log(` Registered ${type} in package.json`)\n } catch (error) {\n console.log(' Warning: Could not update package.json')\n }\n}\n","import chalk from 'chalk'\nimport type { NextSparkPackageJson, PostinstallContext } from '../../types/nextspark-package.js'\nimport { processTemplates } from './templates.js'\nimport { processEnvVars } from './env-vars.js'\nimport { registerMigrations } from './migrations.js'\nimport { runCustomScript } from './script-runner.js'\nimport { existsSync } from 'fs'\nimport { join } from 'path'\n\nexport async function runPostinstall(\n packageJson: NextSparkPackageJson,\n installedPath: string,\n context: PostinstallContext\n): Promise<void> {\n const postinstall = packageJson.nextspark?.postinstall\n if (!postinstall) {\n return\n }\n\n console.log(chalk.blue('\\n Running postinstall hooks...'))\n\n // 1. Instalar plugins requeridos (con tracking para evitar loops)\n if (postinstall.requiredPlugins?.length) {\n for (const plugin of postinstall.requiredPlugins) {\n // Evitar recursion infinita\n if (context.installingPlugins.has(plugin)) {\n console.log(chalk.yellow(` Skipping ${plugin} (already being installed)`))\n continue\n }\n\n const pluginExists = await checkPluginExists(plugin)\n if (!pluginExists) {\n console.log(` Installing required plugin: ${plugin}`)\n context.installingPlugins.add(plugin)\n\n // Importar dinamicamente para evitar dependencia circular\n const { addPlugin } = await import('../../commands/add-plugin.js')\n await addPlugin(plugin, { installingPlugins: context.installingPlugins })\n }\n }\n }\n\n // 2. Procesar templates\n if (postinstall.templates?.length) {\n const needsTheme = postinstall.templates.some(t =>\n t.to.includes('${activeTheme}')\n )\n\n if (needsTheme && !context.activeTheme) {\n console.log(chalk.yellow('\\n Warning: Templates require an active theme but none detected.'))\n console.log(chalk.gray(' Set NEXT_PUBLIC_ACTIVE_THEME or install a theme first.'))\n console.log(chalk.gray(' Skipping template installation.\\n'))\n } else {\n await processTemplates(postinstall.templates, installedPath, context)\n }\n }\n\n // 3. Variables de entorno\n if (postinstall.envVars?.length) {\n await processEnvVars(postinstall.envVars)\n }\n\n // 4. Migrations\n if (postinstall.migrations?.length) {\n await registerMigrations(postinstall.migrations, installedPath)\n }\n\n // 5. Script custom (CON CONFIRMACION)\n if (postinstall.script) {\n await runCustomScript(postinstall.script, installedPath, context)\n }\n\n // 6. Mensajes finales\n if (postinstall.messages) {\n console.log('')\n if (postinstall.messages.success) {\n console.log(chalk.green(` ${postinstall.messages.success}`))\n }\n if (postinstall.messages.docs) {\n console.log(chalk.gray(` Docs: ${postinstall.messages.docs}`))\n }\n if (postinstall.messages.nextSteps?.length) {\n console.log(chalk.blue('\\n Next steps:'))\n postinstall.messages.nextSteps.forEach((step, i) => {\n console.log(chalk.gray(` ${i + 1}. ${step}`))\n })\n }\n }\n}\n\nasync function checkPluginExists(pluginName: string): Promise<boolean> {\n const name = pluginName\n .replace(/^@[^/]+\\//, '')\n .replace(/^nextspark-plugin-/, '')\n .replace(/^plugin-/, '')\n\n return existsSync(join(process.cwd(), 'contents', 'plugins', name))\n}\n\nexport { PostinstallContext }\n","import { existsSync, cpSync, mkdirSync } from 'fs'\nimport { join, dirname } from 'path'\nimport chalk from 'chalk'\nimport type { PostinstallContext } from '../../types/nextspark-package.js'\n\ninterface TemplateConfig {\n from: string\n to: string\n condition?: 'exists' | '!exists' | 'always' | 'prompt'\n description?: string\n}\n\nexport async function processTemplates(\n templates: TemplateConfig[],\n sourcePath: string,\n context: PostinstallContext\n): Promise<void> {\n for (const template of templates) {\n const from = join(sourcePath, template.from)\n const to = resolveVariables(template.to, context)\n\n if (!existsSync(from)) {\n console.log(chalk.yellow(` Warning: Template source not found: ${template.from}`))\n continue\n }\n\n const targetExists = existsSync(to)\n const condition = template.condition || '!exists'\n const desc = template.description || template.to\n\n switch (condition) {\n case '!exists':\n if (targetExists) {\n console.log(chalk.gray(` Skipping ${desc} (already exists)`))\n continue\n }\n break\n\n case 'exists':\n if (!targetExists) {\n console.log(chalk.gray(` Skipping ${desc} (target doesn't exist)`))\n continue\n }\n break\n\n case 'prompt':\n if (targetExists) {\n // For now, skip if exists when prompting not implemented\n console.log(chalk.gray(` Skipping ${desc} (already exists, use --force to overwrite)`))\n continue\n }\n break\n\n case 'always':\n break\n }\n\n const parentDir = dirname(to)\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n\n console.log(chalk.gray(` Copying ${desc}...`))\n cpSync(from, to, { recursive: true })\n }\n}\n\nfunction resolveVariables(path: string, context: PostinstallContext): string {\n let resolved = path\n\n if (context.activeTheme) {\n resolved = resolved.replace(/\\$\\{activeTheme\\}/g, context.activeTheme)\n }\n resolved = resolved.replace(/\\$\\{projectRoot\\}/g, context.projectRoot)\n resolved = resolved.replace(/\\$\\{timestamp\\}/g, context.timestamp.toString())\n resolved = resolved.replace(/\\$\\{coreVersion\\}/g, context.coreVersion)\n\n if (context.pluginName) {\n resolved = resolved.replace(/\\$\\{pluginName\\}/g, context.pluginName)\n }\n if (context.themeName) {\n resolved = resolved.replace(/\\$\\{themeName\\}/g, context.themeName)\n }\n\n const unresolvedMatch = resolved.match(/\\$\\{([^}]+)\\}/)\n if (unresolvedMatch) {\n throw new Error(`Unresolved template variable: ${unresolvedMatch[0]}`)\n }\n\n if (!resolved.startsWith('/')) {\n resolved = join(context.projectRoot, resolved)\n }\n\n return resolved\n}\n","import { existsSync, readFileSync, writeFileSync, appendFileSync } from 'fs'\nimport { join } from 'path'\nimport chalk from 'chalk'\n\ninterface EnvVarConfig {\n key: string\n description: string\n required: boolean\n default?: string\n}\n\nexport async function processEnvVars(envVars: EnvVarConfig[]): Promise<void> {\n const envExamplePath = join(process.cwd(), '.env.example')\n const envPath = join(process.cwd(), '.env')\n\n let added = 0\n\n // Read existing vars to avoid duplicates\n const existingVars = new Set<string>()\n if (existsSync(envExamplePath)) {\n const content = readFileSync(envExamplePath, 'utf-8')\n const matches = content.match(/^[A-Z_][A-Z0-9_]*=/gm)\n if (matches) {\n matches.forEach(m => existingVars.add(m.replace('=', '')))\n }\n }\n\n const newLines: string[] = []\n\n for (const envVar of envVars) {\n if (existingVars.has(envVar.key)) {\n continue\n }\n\n const value = envVar.default || ''\n const requiredMark = envVar.required ? ' (required)' : ''\n newLines.push(`# ${envVar.description}${requiredMark}`)\n newLines.push(`${envVar.key}=${value}`)\n newLines.push('')\n added++\n }\n\n if (newLines.length > 0) {\n const content = '\\n' + newLines.join('\\n')\n\n if (existsSync(envExamplePath)) {\n appendFileSync(envExamplePath, content)\n } else {\n writeFileSync(envExamplePath, content.trim() + '\\n')\n }\n\n console.log(chalk.gray(` Added ${added} env vars to .env.example`))\n }\n}\n","import { existsSync, mkdirSync, cpSync } from 'fs'\nimport { join, basename } from 'path'\nimport chalk from 'chalk'\n\nexport async function registerMigrations(\n migrations: string[],\n installedPath: string\n): Promise<void> {\n const migrationsDir = join(process.cwd(), 'migrations')\n\n if (!existsSync(migrationsDir)) {\n mkdirSync(migrationsDir, { recursive: true })\n }\n\n let copied = 0\n\n for (const migration of migrations) {\n const sourcePath = join(installedPath, migration)\n\n if (!existsSync(sourcePath)) {\n console.log(chalk.yellow(` Warning: Migration not found: ${migration}`))\n continue\n }\n\n const fileName = basename(migration)\n const targetPath = join(migrationsDir, fileName)\n\n if (existsSync(targetPath)) {\n console.log(chalk.gray(` Migration ${fileName} already exists, skipping`))\n continue\n }\n\n cpSync(sourcePath, targetPath)\n copied++\n }\n\n if (copied > 0) {\n console.log(chalk.gray(` Copied ${copied} migration(s) to /migrations`))\n }\n}\n","import { existsSync } from 'fs'\nimport { join } from 'path'\nimport chalk from 'chalk'\nimport type { PostinstallContext } from '../../types/nextspark-package.js'\n\nexport async function runCustomScript(\n scriptPath: string,\n installedPath: string,\n context: PostinstallContext\n): Promise<void> {\n const fullPath = join(installedPath, scriptPath)\n\n if (!existsSync(fullPath)) {\n console.log(chalk.yellow(` Warning: Postinstall script not found: ${scriptPath}`))\n return\n }\n\n console.log('')\n console.log(chalk.yellow(' Warning: This package wants to run a custom postinstall script:'))\n console.log(chalk.gray(` ${scriptPath}`))\n console.log('')\n console.log(chalk.gray(' Custom scripts can execute arbitrary code.'))\n console.log(chalk.gray(' Only allow if you trust the package author.'))\n console.log(chalk.gray(' Skipping script execution (manual approval required).'))\n console.log('')\n\n // In MVP, we skip custom scripts by default for security\n // In future versions, we could add --allow-scripts flag or prompts\n}\n","import { existsSync, readFileSync, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\n\n/**\n * Detects the currently active theme in the project\n * Priority:\n * 1. NEXT_PUBLIC_ACTIVE_THEME environment variable\n * 2. activeTheme in nextspark.config.ts\n * 3. NEXT_PUBLIC_ACTIVE_THEME in .env file\n * 4. Single installed theme (if only one exists)\n * 5. null if cannot be determined\n */\nexport function detectActiveTheme(): string | null {\n // 1. Environment variable (for CI/CD and development)\n if (process.env.NEXT_PUBLIC_ACTIVE_THEME) {\n return process.env.NEXT_PUBLIC_ACTIVE_THEME\n }\n\n // 2. nextspark.config.ts (project configuration) - simplified check\n const configPath = join(process.cwd(), 'nextspark.config.ts')\n if (existsSync(configPath)) {\n try {\n const content = readFileSync(configPath, 'utf-8')\n // Simple regex to extract activeTheme value\n const match = content.match(/activeTheme\\s*:\\s*['\"]([^'\"]+)['\"]/)\n if (match) {\n return match[1]\n }\n } catch {\n // Ignore read errors\n }\n }\n\n // 3. .env file\n const envPath = join(process.cwd(), '.env')\n if (existsSync(envPath)) {\n try {\n const content = readFileSync(envPath, 'utf-8')\n const match = content.match(/NEXT_PUBLIC_ACTIVE_THEME=(.+)/)\n if (match) {\n return match[1].trim()\n }\n } catch {\n // Ignore read errors\n }\n }\n\n // 4. Single installed theme\n const themesDir = join(process.cwd(), 'contents', 'themes')\n if (existsSync(themesDir)) {\n try {\n const themes = readdirSync(themesDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name)\n if (themes.length === 1) {\n return themes[0]\n }\n } catch {\n // Ignore read errors\n }\n }\n\n // 5. Cannot determine\n return null\n}\n\n/**\n * Returns a list of all available themes in the project\n */\nexport function getAvailableThemes(): string[] {\n const themesDir = join(process.cwd(), 'contents', 'themes')\n if (!existsSync(themesDir)) {\n return []\n }\n\n try {\n return readdirSync(themesDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name)\n } catch {\n return []\n }\n}\n"],"mappings":"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","names":["chalk","existsSync","readFileSync","join","existsSync","rmSync","readFileSync","writeFileSync","join","existsSync","readFileSync","join","join","existsSync","rmSync","readFileSync","writeFileSync","chalk","existsSync","cpSync","mkdirSync","join","chalk","existsSync","readFileSync","writeFileSync","join","chalk","existsSync","mkdirSync","cpSync","join","chalk","existsSync","join","chalk","existsSync","join","chalk","addPlugin","existsSync","readFileSync","readdirSync","join","existsSync","readFileSync","join","chalk"]}
@@ -0,0 +1,11 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ export {
9
+ __require
10
+ };
11
+ //# sourceMappingURL=chunk-DGUM43GV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}