create-nyoworks 2.5.0 → 2.6.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/checks.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export declare function checkDependencies(): Promise<void>;
2
+ export declare function getDockerComposeCommand(): Promise<string>;
2
3
  export declare function showClaudeMaxWarning(): void;
package/dist/checks.js CHANGED
@@ -87,6 +87,21 @@ export async function checkDependencies() {
87
87
  console.log(pc.red("Please install the required dependencies before continuing."));
88
88
  }
89
89
  }
90
+ export async function getDockerComposeCommand() {
91
+ try {
92
+ await execa("docker", ["compose", "version"]);
93
+ return "docker compose";
94
+ }
95
+ catch {
96
+ try {
97
+ await execa("docker-compose", ["version"]);
98
+ return "docker-compose";
99
+ }
100
+ catch {
101
+ return "docker compose";
102
+ }
103
+ }
104
+ }
90
105
  export function showClaudeMaxWarning() {
91
106
  console.log();
92
107
  console.log(pc.yellow("╔═══════════════════════════════════════════════════════════════════════╗"));
package/dist/init.js CHANGED
@@ -5,18 +5,42 @@ import path from "path";
5
5
  import os from "os";
6
6
  import { execa } from "execa";
7
7
  import { replacePlaceholders } from "./replace.js";
8
- import { checkDependencies, showClaudeMaxWarning } from "./checks.js";
8
+ import { checkDependencies, showClaudeMaxWarning, getDockerComposeCommand } from "./checks.js";
9
9
  const REPO = "naimozcan/nyoworks-framework";
10
10
  const BRANCH = "main";
11
+ const PRODUCT_TYPES = [
12
+ { title: "E-Commerce", value: "ecommerce", description: "Online store, product sales" },
13
+ { title: "Booking", value: "booking", description: "Appointment/reservation system" },
14
+ { title: "SaaS Platform", value: "saas", description: "Subscription-based software" },
15
+ { title: "Marketplace", value: "marketplace", description: "Multi-vendor platform" },
16
+ { title: "Content/Blog", value: "content", description: "Blog, news, CMS" },
17
+ { title: "CRM", value: "crm", description: "Customer relationship management" },
18
+ { title: "Custom", value: "custom", description: "Manual feature selection" },
19
+ ];
20
+ const REQUIRED_FEATURES = {
21
+ ecommerce: ["payments", "crm", "notifications", "search", "storage"],
22
+ booking: ["appointments", "payments", "crm", "notifications"],
23
+ saas: ["payments", "subscriptions", "analytics", "notifications", "audit", "multitenant"],
24
+ marketplace: ["payments", "crm", "analytics", "notifications", "audit", "search", "storage", "multitenant"],
25
+ content: ["analytics", "search", "storage"],
26
+ crm: ["crm", "analytics", "notifications", "audit", "export"],
27
+ custom: [],
28
+ };
11
29
  const AVAILABLE_FEATURES = [
12
30
  { title: "Analytics", value: "analytics", description: "User behavior tracking" },
13
- { title: "CRM", value: "crm", description: "Customer relationship management" },
14
- { title: "Payments", value: "payments", description: "Stripe integration" },
15
- { title: "Notifications", value: "notifications", description: "Email, SMS, Push" },
16
31
  { title: "Appointments", value: "appointments", description: "Booking system" },
17
32
  { title: "Audit", value: "audit", description: "Activity logging" },
33
+ { title: "Auth Social", value: "auth-social", description: "Google, Apple, GitHub OAuth" },
34
+ { title: "CRM", value: "crm", description: "Customer relationship management" },
18
35
  { title: "Export", value: "export", description: "PDF/CSV export" },
36
+ { title: "i18n", value: "i18n", description: "Multi-language support" },
37
+ { title: "Multitenant", value: "multitenant", description: "Multi-organization support" },
38
+ { title: "Notifications", value: "notifications", description: "Email, SMS, Push" },
39
+ { title: "Payments", value: "payments", description: "Stripe integration" },
19
40
  { title: "Realtime", value: "realtime", description: "WebSocket support" },
41
+ { title: "Search", value: "search", description: "Full-text search" },
42
+ { title: "Storage", value: "storage", description: "File uploads (S3/R2)" },
43
+ { title: "Subscriptions", value: "subscriptions", description: "Plans & usage limits" },
20
44
  ];
21
45
  const AVAILABLE_PLATFORMS = [
22
46
  { title: "Web", value: "web", description: "Next.js 16" },
@@ -65,14 +89,40 @@ export async function createProject(projectName) {
65
89
  console.log(pc.cyan(pc.bold(" NYOWORKS Framework")));
66
90
  console.log(pc.dim(" Create a new project"));
67
91
  console.log();
92
+ let productType = "custom";
93
+ let requiredFeatures = [];
94
+ const nameResponse = await prompts({
95
+ type: projectName ? null : "text",
96
+ name: "name",
97
+ message: "Project name:",
98
+ initial: projectName || "my-project",
99
+ validate: (value) => (value.length > 0 ? true : "Project name is required"),
100
+ });
101
+ if (!nameResponse.name && !projectName) {
102
+ console.log(pc.red("Aborted."));
103
+ process.exit(1);
104
+ }
105
+ const productResponse = await prompts({
106
+ type: "select",
107
+ name: "productType",
108
+ message: "Product type:",
109
+ choices: PRODUCT_TYPES,
110
+ initial: 0,
111
+ });
112
+ if (productResponse.productType) {
113
+ productType = productResponse.productType;
114
+ requiredFeatures = REQUIRED_FEATURES[productType] || [];
115
+ }
116
+ const featureChoices = AVAILABLE_FEATURES.map((f) => {
117
+ const isRequired = requiredFeatures.includes(f.value);
118
+ return {
119
+ title: isRequired ? `${f.title} [required]` : f.title,
120
+ value: f.value,
121
+ description: f.description,
122
+ selected: isRequired,
123
+ };
124
+ });
68
125
  const response = await prompts([
69
- {
70
- type: projectName ? null : "text",
71
- name: "name",
72
- message: "Project name:",
73
- initial: projectName || "my-project",
74
- validate: (value) => (value.length > 0 ? true : "Project name is required"),
75
- },
76
126
  {
77
127
  type: "multiselect",
78
128
  name: "platforms",
@@ -86,7 +136,7 @@ export async function createProject(projectName) {
86
136
  type: "multiselect",
87
137
  name: "features",
88
138
  message: "Select features:",
89
- choices: AVAILABLE_FEATURES,
139
+ choices: featureChoices,
90
140
  hint: "- Space to select. Return to submit",
91
141
  instructions: false,
92
142
  },
@@ -98,16 +148,13 @@ export async function createProject(projectName) {
98
148
  initial: 0,
99
149
  },
100
150
  ]);
101
- if (!response.name && !projectName) {
102
- console.log(pc.red("Aborted."));
103
- process.exit(1);
104
- }
105
- const name = response.name || projectName;
151
+ const name = (nameResponse.name || projectName);
106
152
  const code = generateCode(name);
107
153
  const slug = generateSlug(name);
108
154
  const databaseName = generateDatabaseName(name);
109
155
  const platforms = response.platforms || ["web"];
110
- const features = response.features || [];
156
+ const selectedFeatures = response.features || [];
157
+ const features = [...new Set([...requiredFeatures, ...selectedFeatures])];
111
158
  const language = response.language || "tr";
112
159
  const targetDir = path.resolve(process.cwd(), slug);
113
160
  if (fs.existsSync(targetDir)) {
@@ -155,6 +202,13 @@ export async function createProject(projectName) {
155
202
  await fs.copy(src, dest);
156
203
  }
157
204
  }
205
+ for (const feature of features) {
206
+ const src = path.join(repoDir, `packages/features/${feature}`);
207
+ const dest = path.join(targetDir, `packages/features/${feature}`);
208
+ if (await fs.pathExists(src)) {
209
+ await fs.copy(src, dest);
210
+ }
211
+ }
158
212
  const rootFiles = [
159
213
  "package.json",
160
214
  "pnpm-workspace.yaml",
@@ -180,6 +234,7 @@ export async function createProject(projectName) {
180
234
  "${PROJECT_CODE}": code,
181
235
  "${PROJECT_SLUG}": slug,
182
236
  "${DATABASE_NAME}": databaseName,
237
+ "${PRODUCT_TYPE}": productType,
183
238
  "${RESPONSE_LANGUAGE}": LANGUAGE_RESPONSES[language] || "Turkish",
184
239
  };
185
240
  process.stdout.write(pc.dim(" Replacing placeholders..."));
@@ -235,13 +290,14 @@ See \`docs/bible/data/schema.md\`
235
290
  console.log();
236
291
  console.log(pc.green(pc.bold("Project created successfully!")));
237
292
  await checkDependencies();
293
+ const dockerCmd = await getDockerComposeCommand();
238
294
  showClaudeMaxWarning();
239
295
  console.log();
240
296
  console.log(pc.bold(" Next steps:"));
241
297
  console.log();
242
298
  console.log(pc.cyan(` cd ${slug}`));
243
299
  console.log(pc.cyan(" pnpm install"));
244
- console.log(pc.cyan(" docker compose up -d ") + pc.dim("# Start PostgreSQL & Redis"));
300
+ console.log(pc.cyan(` ${dockerCmd} up -d`) + " " + pc.dim("# Start PostgreSQL & Redis"));
245
301
  console.log(pc.cyan(" pnpm dev"));
246
302
  console.log();
247
303
  console.log(pc.dim(" Optional:"));
@@ -251,18 +307,24 @@ See \`docs/bible/data/schema.md\`
251
307
  console.log(pc.dim(" Configuration:"));
252
308
  console.log(pc.dim(` Name: ${name}`));
253
309
  console.log(pc.dim(` Code: ${code}`));
310
+ console.log(pc.dim(` Product: ${productType}`));
254
311
  console.log(pc.dim(` Platforms: ${platforms.join(", ")}`));
255
312
  console.log(pc.dim(` Features: ${features.join(", ") || "none"}`));
256
313
  console.log(pc.dim(` Language: ${LANGUAGE_RESPONSES[language] || "Turkish"}`));
257
314
  console.log();
258
315
  process.stdout.write(pc.dim(" Building MCP server..."));
316
+ const mcpPath = path.join(targetDir, "mcp-server");
259
317
  try {
260
- await execa("pnpm", ["install"], { cwd: path.join(targetDir, "mcp-server") });
261
- await execa("pnpm", ["build"], { cwd: path.join(targetDir, "mcp-server") });
318
+ await execa("pnpm", ["install"], { cwd: mcpPath });
319
+ await execa("pnpm", ["build"], { cwd: mcpPath });
262
320
  console.log(pc.green(" done"));
263
321
  }
264
- catch {
265
- console.log(pc.yellow(" skipped (run manually: cd mcp-server && pnpm install && pnpm build)"));
322
+ catch (error) {
323
+ console.log(pc.yellow(" failed"));
324
+ if (error instanceof Error) {
325
+ console.log(pc.dim(` Error: ${error.message.split("\n")[0]}`));
326
+ }
327
+ console.log(pc.dim(" Run manually: cd mcp-server && pnpm install && pnpm build"));
266
328
  }
267
329
  const mcpConfigPath = path.join(targetDir, ".claude", "settings.local.json");
268
330
  const mcpConfig = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nyoworks",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Create a new NYOWORKS project",
5
5
  "type": "module",
6
6
  "bin": {