create-lunar-kit 0.1.15 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +136 -99
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import prompts from "prompts";
5
+ import { intro, text, select, multiselect, isCancel, cancel } from "@clack/prompts";
6
6
  import chalk3 from "chalk";
7
7
  import ora from "ora";
8
8
  import { execa } from "execa";
@@ -13,64 +13,61 @@ import { fileURLToPath as fileURLToPath2 } from "url";
13
13
  // src/assets/logo.ts
14
14
  import chalk from "chalk";
15
15
  var renderLogo = () => {
16
- console.log(
17
- chalk.cyan(` ............. ............
18
- ................. .................
19
- ...... .......... .......... ......
20
- ...... ......... ........ .....
21
- ..... ............. .....
22
- ..... ........ .....
23
- ..... ....... .....
24
- ..... ........... .....
25
- ..... ...... ...... .....
26
- ..... ...... ...... .....
27
- ..... .............................. .....
28
- .................................................
29
- ....................... .......................
30
- ................. ...... ...... ...............
31
- ........... ..... ...... ... ...... ..... ...........
32
- ........ ............ .... ............ ........
33
- ...... .......... ..... ......... ......
34
- ..... ....... ...... ....... .....
35
- .... ...... ....... ..... ....
36
- .... ....... .......... .. ....... .....
37
- ..... ......... .............. ......... .....
38
- ...... .......... ............ .......... .......
39
- ......... ..... ...... ....... ...... ..... ........
40
- ................. ..... ..... ................
41
- ................ ..... ......................
42
- ..................................................
43
- ................................................
44
- ..... ................... ......
45
- ..... ...... ...... .....
46
- ..... ...... ...... .....
47
- ..... ......... .....
48
- ..... ....... .....
49
- ..... ........... .....
50
- ..... ....... ....... .....
51
- ..... ......... ........ .....
52
- ................. .................
53
- ............. .............
54
- `)
55
- );
16
+ const lines = [
17
+ "\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
18
+ "\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D",
19
+ "\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 ",
20
+ "\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 ",
21
+ "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 ",
22
+ "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D ",
23
+ " "
24
+ ];
25
+ const colors = [
26
+ "#808080",
27
+ // line 1: gray
28
+ "#999999",
29
+ // line 2
30
+ "#b3b3b3",
31
+ // line 3
32
+ "#cccccc",
33
+ // line 4
34
+ "#e6e6e6",
35
+ // line 5
36
+ "#ffffff",
37
+ // line 6: white
38
+ "#ffffff"
39
+ // line 7: white
40
+ ];
41
+ const logo = lines.map((line, i) => chalk.hex(colors[i])(line)).join("\n");
42
+ console.log(logo + "\n");
56
43
  };
57
44
 
58
45
  // src/commands/init.ts
59
- import { LOCAL_COMPONENTS_PATH } from "@lunar-kit/core";
60
46
  import fs from "fs-extra";
61
47
  import path from "path";
62
48
  import { fileURLToPath } from "url";
63
49
  var __filename2 = fileURLToPath(import.meta.url);
64
50
  var __dirname2 = path.dirname(__filename2);
65
- var CORE_TEMPLATES_PATH = path.join(__dirname2, "../../node_modules/@lunar-kit/core/src/templates");
66
- var CORE_SOURCE_PATH = path.join(__dirname2, "../../node_modules/@lunar-kit/core/src");
51
+ var isFlattened = __dirname2.endsWith("dist");
52
+ var numLevelsUp = isFlattened ? "../.." : "../../..";
53
+ var PACKAGES_DIR = path.resolve(__dirname2, numLevelsUp);
54
+ var CORE_ROOT = path.join(PACKAGES_DIR, "core", "src");
55
+ var CORE_TEMPLATES_PATH = path.join(CORE_ROOT, "templates");
56
+ var CORE_SOURCE_PATH = CORE_ROOT;
57
+ var CORE_COMPONENTS_PATH = path.join(CORE_ROOT, "components");
67
58
  function copyTemplate(templatePath, destPath) {
68
59
  const fullPath = path.join(CORE_TEMPLATES_PATH, templatePath);
60
+ if (!fs.existsSync(fullPath)) {
61
+ throw new Error(`Template not found: ${fullPath}`);
62
+ }
69
63
  const content = fs.readFileSync(fullPath);
70
64
  fs.writeFileSync(destPath, content);
71
65
  }
72
66
  function copySource(sourcePath, destPath) {
73
67
  const fullPath = path.join(CORE_SOURCE_PATH, sourcePath);
68
+ if (!fs.existsSync(fullPath)) {
69
+ throw new Error(`Source not found: ${fullPath}`);
70
+ }
74
71
  const content = fs.readFileSync(fullPath);
75
72
  fs.writeFileSync(destPath, content);
76
73
  }
@@ -130,6 +127,17 @@ async function setupAppEntry(projectPath, navigation) {
130
127
  copyTemplate("scaffolding/Main.tsx", path.join(projectPath, "src", "Main.tsx"));
131
128
  }
132
129
  }
130
+ async function setupAppConfig(projectPath, name) {
131
+ const appJsonPath = path.join(projectPath, "app.json");
132
+ if (fs.existsSync(appJsonPath)) {
133
+ const appJson = await fs.readJson(appJsonPath);
134
+ if (!appJson.expo) appJson.expo = {};
135
+ if (!appJson.expo.scheme) {
136
+ appJson.expo.scheme = name.toLowerCase().replace(/[^a-z0-9]/g, "");
137
+ }
138
+ await fs.writeJson(appJsonPath, appJson, { spaces: 2 });
139
+ }
140
+ }
133
141
  async function setupExpoRouterSrc(projectPath) {
134
142
  const appDir = path.join(projectPath, "app");
135
143
  await fs.ensureDir(appDir);
@@ -181,8 +189,8 @@ async function setupNativeWind(projectPath) {
181
189
  copySource("lib/utils.ts", path.join(projectPath, "src", "lib", "utils.ts"));
182
190
  copySource("lib/theme.ts", path.join(projectPath, "src", "lib", "theme.ts"));
183
191
  await fs.ensureDir(path.join(projectPath, "src", "components", "ui"));
184
- const buttonContent = fs.readFileSync(path.join(LOCAL_COMPONENTS_PATH, "ui", "button.tsx"));
185
- const textContent = fs.readFileSync(path.join(LOCAL_COMPONENTS_PATH, "ui", "text.tsx"));
192
+ const buttonContent = fs.readFileSync(path.join(CORE_COMPONENTS_PATH, "ui", "button.tsx"));
193
+ const textContent = fs.readFileSync(path.join(CORE_COMPONENTS_PATH, "ui", "text.tsx"));
186
194
  await fs.writeFile(path.join(projectPath, "src", "components", "ui", "button.tsx"), buttonContent);
187
195
  await fs.writeFile(path.join(projectPath, "src", "components", "ui", "text.tsx"), textContent);
188
196
  }
@@ -327,7 +335,7 @@ function closeInitProject(packageManager, name) {
327
335
  // package.json
328
336
  var package_default = {
329
337
  name: "create-lunar-kit",
330
- version: "0.1.15",
338
+ version: "0.1.17",
331
339
  description: "Create a new React Native app with Lunar Kit and NativeWind pre-configured",
332
340
  author: "Your Name",
333
341
  license: "MIT",
@@ -351,7 +359,8 @@ var package_default = {
351
359
  "starter"
352
360
  ],
353
361
  dependencies: {
354
- "@lunar-kit/core": "0.1.15",
362
+ "@clack/prompts": "^1.1.0",
363
+ "@lunar-kit/core": "0.1.17",
355
364
  chalk: "^5.4.1",
356
365
  commander: "^12.1.0",
357
366
  execa: "^9.6.1",
@@ -372,55 +381,60 @@ var __filename3 = fileURLToPath2(import.meta.url);
372
381
  var program = new Command();
373
382
  program.name("create-lunar-kit").description("Create a new React Native app with Lunar Kit").argument("[project-name]", "Name of your project").action(async (projectName) => {
374
383
  renderLogo();
375
- console.log(chalk3.bold.cyan(`
376
- \u{1F319} Create Lunar Kit App (v${package_default.version})
377
- `));
378
- const response = await prompts([
379
- {
380
- type: projectName ? null : "text",
381
- name: "projectName",
382
- message: "What is your project named?",
383
- initial: "my-lunar-app",
384
- validate: (value) => /^[a-z0-9-]+$/.test(value) || "Project name must be lowercase and use hyphens"
385
- },
386
- {
387
- type: "select",
388
- name: "navigation",
389
- message: "Which navigation library?",
390
- choices: [
391
- { title: "Expo Router (File-based routing)", value: "expo-router" },
392
- { title: "React Navigation (Stack-based)", value: "react-navigation" },
393
- { title: "None (I'll add it later)", value: "none" }
394
- ],
395
- initial: 0
396
- },
397
- {
398
- type: "multiselect",
399
- name: "features",
400
- message: "Select features to include:",
401
- choices: [
402
- { title: "\u{1F30D} Localization (i18n)", value: "localization", selected: false },
403
- { title: "\u{1F510} Environment config (.env)", value: "env", selected: false },
404
- { title: "\u{1F4E1} API client (axios)", value: "api", selected: false },
405
- { title: "\u{1F511} Authentication screens", value: "auth", selected: false },
406
- { title: "\u{1F4DD} Form validation (react-hook-form)", value: "forms", selected: false }
407
- ]
408
- },
409
- {
410
- type: "select",
411
- name: "packageManager",
412
- message: "Which package manager?",
413
- choices: [
414
- { title: "bun", value: "bun" },
415
- { title: "pnpm", value: "pnpm" },
416
- { title: "npm", value: "npm" },
417
- { title: "yarn", value: "yarn" }
418
- ],
419
- initial: 0
384
+ intro(chalk3.bold.cyan(`\u{1F319} Create Lunar Kit App (v${package_default.version})`));
385
+ const name = projectName || await text({
386
+ message: "What is your project named?",
387
+ placeholder: "my-lunar-app",
388
+ // initialValue: 'my-lunar-app',
389
+ defaultValue: "my-lunar-app",
390
+ validate: (value) => {
391
+ if (value && !/^[a-z0-9-]+$/.test(value)) return "Project name must be lowercase and use hyphens";
420
392
  }
421
- ]);
422
- const name = projectName || response.projectName;
423
- const { navigation, features, packageManager } = response;
393
+ });
394
+ if (isCancel(name)) {
395
+ cancel("Project creation cancelled");
396
+ process.exit(1);
397
+ }
398
+ const navigation = await select({
399
+ message: "Which navigation library?",
400
+ options: [
401
+ { label: "Expo Router (File-based routing)", value: "expo-router" },
402
+ { label: "React Navigation (Stack-based)", value: "react-navigation" },
403
+ { label: "None (I'll add it later)", value: "none" }
404
+ ]
405
+ });
406
+ if (isCancel(navigation)) {
407
+ cancel("Project creation cancelled");
408
+ process.exit(1);
409
+ }
410
+ const features = await multiselect({
411
+ message: "Select features to include:",
412
+ options: [
413
+ { label: "Localization (i18n)", value: "localization" },
414
+ { label: "Environment config (.env)", value: "env" },
415
+ { label: "API client (axios)", value: "api" },
416
+ { label: "Authentication screens", value: "auth" },
417
+ { label: "Form validation (react-hook-form)", value: "forms" }
418
+ ],
419
+ required: false
420
+ });
421
+ if (isCancel(features)) {
422
+ cancel("Project creation cancelled");
423
+ process.exit(1);
424
+ }
425
+ const packageManager = await select({
426
+ message: "Which package manager?",
427
+ options: [
428
+ { label: "bun", value: "bun" },
429
+ { label: "pnpm", value: "pnpm" },
430
+ { label: "npm", value: "npm" },
431
+ { label: "yarn", value: "yarn" }
432
+ ]
433
+ });
434
+ if (isCancel(packageManager)) {
435
+ cancel("Project creation cancelled");
436
+ process.exit(1);
437
+ }
424
438
  if (!name) {
425
439
  console.log(chalk3.red("Project name is required"));
426
440
  process.exit(1);
@@ -441,6 +455,7 @@ program.name("create-lunar-kit").description("Create a new React Native app with
441
455
  template,
442
456
  "--no-install"
443
457
  ]);
458
+ await setupAppConfig(projectPath, name);
444
459
  spinner.text = "Setting up project structure...";
445
460
  await createSrcStructure(projectPath, navigation);
446
461
  await setupAppEntry(projectPath, navigation);
@@ -476,10 +491,32 @@ program.name("create-lunar-kit").description("Create a new React Native app with
476
491
  spinner.text = "Updating dependencies...";
477
492
  await updatePackageJson(projectPath, navigation, features);
478
493
  await createConfig(projectPath, navigation, features, packageManager);
479
- spinner.text = `Installing dependencies with ${packageManager}...`;
494
+ spinner.stop();
495
+ console.log(`
496
+ ${chalk3.cyan("\u{1F4E6} Installing dependencies...")}`);
480
497
  const installCmd = packageManager === "yarn" ? "yarn" : packageManager === "bun" ? "bun" : packageManager;
481
- const installArgs = packageManager === "npm" ? ["install"] : packageManager === "yarn" ? [] : ["install"];
482
- await execa(installCmd, installArgs, { cwd: projectPath });
498
+ const installArgs = packageManager === "yarn" ? [] : ["install"];
499
+ try {
500
+ await execa(installCmd, installArgs, {
501
+ cwd: projectPath,
502
+ stdio: "inherit"
503
+ });
504
+ console.log(chalk3.green("\u2705 Dependencies installed\n"));
505
+ } catch (error) {
506
+ console.error(chalk3.red("\u274C Failed to install dependencies"));
507
+ throw error;
508
+ }
509
+ const fixSpinner = ora("Aligning dependency versions...").start();
510
+ try {
511
+ await execa("npx expo install --fix", {
512
+ cwd: projectPath,
513
+ stdio: "ignore",
514
+ shell: true
515
+ });
516
+ fixSpinner.succeed(chalk3.green("Dependencies aligned"));
517
+ } catch {
518
+ fixSpinner.warn(chalk3.yellow("Could not auto-fix dependencies"));
519
+ }
483
520
  spinner.succeed(chalk3.green("Project created successfully! \u{1F389}"));
484
521
  closeInitProject(packageManager, name);
485
522
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-lunar-kit",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Create a new React Native app with Lunar Kit and NativeWind pre-configured",
5
5
  "author": "Your Name",
6
6
  "license": "MIT",
@@ -24,7 +24,8 @@
24
24
  "starter"
25
25
  ],
26
26
  "dependencies": {
27
- "@lunar-kit/core": "0.1.15",
27
+ "@clack/prompts": "^1.1.0",
28
+ "@lunar-kit/core": "0.1.17",
28
29
  "chalk": "^5.4.1",
29
30
  "commander": "^12.1.0",
30
31
  "execa": "^9.6.1",