create-headless-store 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +399 -0
- package/package.json +44 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import prompts from "prompts";
|
|
7
|
+
import ora from "ora";
|
|
8
|
+
import { execa } from "execa";
|
|
9
|
+
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
10
|
+
import { join, resolve } from "path";
|
|
11
|
+
import crypto from "crypto";
|
|
12
|
+
var VERSION = "0.1.0";
|
|
13
|
+
var BANNER = `
|
|
14
|
+
${chalk.bold.blue("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}
|
|
15
|
+
${chalk.bold.blue("\u2551")} ${chalk.bold("\u26A1 Headless Commerce")} ${chalk.bold.blue("\u2551")}
|
|
16
|
+
${chalk.bold.blue("\u2551")} ${chalk.dim("AI-native commerce in 5 minutes")} ${chalk.bold.blue("\u2551")}
|
|
17
|
+
${chalk.bold.blue("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")}
|
|
18
|
+
`;
|
|
19
|
+
var program = new Command();
|
|
20
|
+
program.name("create-headless-store").description("Create a new headless commerce store").version(VERSION).argument("[directory]", "Project directory name").option("--no-demo", "Skip demo seed data").option("--port <port>", "API port", "3010").action(async (directory) => {
|
|
21
|
+
console.log(BANNER);
|
|
22
|
+
const opts = program.opts();
|
|
23
|
+
const answers = await prompts([
|
|
24
|
+
{
|
|
25
|
+
type: directory ? null : "text",
|
|
26
|
+
name: "directory",
|
|
27
|
+
message: "Project directory:",
|
|
28
|
+
initial: "my-store"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: "text",
|
|
32
|
+
name: "name",
|
|
33
|
+
message: "Store name:",
|
|
34
|
+
initial: "My Store"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
name: "stripeSecretKey",
|
|
39
|
+
message: `Stripe Secret Key ${chalk.dim("(optional, press Enter to skip)")}:`,
|
|
40
|
+
initial: ""
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: (prev) => prev ? "text" : null,
|
|
44
|
+
name: "stripePublishableKey",
|
|
45
|
+
message: "Stripe Publishable Key:",
|
|
46
|
+
initial: ""
|
|
47
|
+
}
|
|
48
|
+
], {
|
|
49
|
+
onCancel: () => {
|
|
50
|
+
console.log(chalk.yellow("\nSetup cancelled."));
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const config = {
|
|
55
|
+
name: answers.name || "My Store",
|
|
56
|
+
directory: directory || answers.directory || "my-store",
|
|
57
|
+
stripeSecretKey: answers.stripeSecretKey || void 0,
|
|
58
|
+
stripePublishableKey: answers.stripePublishableKey || void 0,
|
|
59
|
+
withDemo: opts.demo !== false,
|
|
60
|
+
port: parseInt(opts.port, 10) || 3010
|
|
61
|
+
};
|
|
62
|
+
await setup(config);
|
|
63
|
+
});
|
|
64
|
+
async function setup(config) {
|
|
65
|
+
const projectDir = resolve(process.cwd(), config.directory);
|
|
66
|
+
if (existsSync(projectDir)) {
|
|
67
|
+
console.log(chalk.red(`
|
|
68
|
+
Directory "${config.directory}" already exists.`));
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
console.log(`
|
|
72
|
+
${chalk.bold("Setting up:")} ${config.name} in ${chalk.cyan(config.directory)}
|
|
73
|
+
`);
|
|
74
|
+
const depSpinner = ora("Checking dependencies...").start();
|
|
75
|
+
await checkDependencies(depSpinner);
|
|
76
|
+
depSpinner.succeed("Dependencies verified (Docker, Node.js, pnpm)");
|
|
77
|
+
const scaffoldSpinner = ora("Scaffolding project...").start();
|
|
78
|
+
scaffoldProject(projectDir, config);
|
|
79
|
+
scaffoldSpinner.succeed("Project scaffolded");
|
|
80
|
+
const dockerSpinner = ora("Starting Docker containers (PostgreSQL + Redis + Inngest)...").start();
|
|
81
|
+
try {
|
|
82
|
+
await execa("docker", ["compose", "up", "-d"], { cwd: projectDir });
|
|
83
|
+
dockerSpinner.succeed("Docker containers running");
|
|
84
|
+
} catch (err) {
|
|
85
|
+
dockerSpinner.fail("Failed to start Docker containers");
|
|
86
|
+
console.log(chalk.yellow(" Make sure Docker is running and try: docker compose up -d"));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
const pgSpinner = ora("Waiting for PostgreSQL to be ready...").start();
|
|
90
|
+
await waitForPostgres(projectDir, pgSpinner);
|
|
91
|
+
pgSpinner.succeed("PostgreSQL is ready");
|
|
92
|
+
const installSpinner = ora("Installing dependencies (this may take a minute)...").start();
|
|
93
|
+
try {
|
|
94
|
+
await execa("pnpm", ["install"], { cwd: projectDir });
|
|
95
|
+
installSpinner.succeed("Dependencies installed");
|
|
96
|
+
} catch {
|
|
97
|
+
installSpinner.fail("Failed to install dependencies");
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
const buildSpinner = ora("Building packages...").start();
|
|
101
|
+
try {
|
|
102
|
+
await execa("pnpm", ["build"], { cwd: projectDir });
|
|
103
|
+
buildSpinner.succeed("Packages built");
|
|
104
|
+
} catch {
|
|
105
|
+
buildSpinner.fail("Build failed");
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
const schemaSpinner = ora("Pushing database schema...").start();
|
|
109
|
+
try {
|
|
110
|
+
await execa("pnpm", ["db:push"], { cwd: projectDir });
|
|
111
|
+
schemaSpinner.succeed("Database schema applied");
|
|
112
|
+
} catch {
|
|
113
|
+
schemaSpinner.fail("Schema push failed");
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
if (config.withDemo) {
|
|
117
|
+
const seedSpinner = ora("Seeding demo data...").start();
|
|
118
|
+
try {
|
|
119
|
+
await execa("pnpm", ["db:seed"], { cwd: projectDir });
|
|
120
|
+
seedSpinner.succeed("Demo data seeded");
|
|
121
|
+
} catch {
|
|
122
|
+
seedSpinner.fail("Seed failed (you can run pnpm db:seed manually)");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
printSuccess(config);
|
|
126
|
+
}
|
|
127
|
+
async function checkDependencies(spinner) {
|
|
128
|
+
try {
|
|
129
|
+
await execa("docker", ["--version"]);
|
|
130
|
+
} catch {
|
|
131
|
+
spinner.fail("Docker not found");
|
|
132
|
+
console.log(chalk.yellow(" Install Docker: https://docs.docker.com/get-docker/"));
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
await execa("docker", ["compose", "version"]);
|
|
137
|
+
} catch {
|
|
138
|
+
spinner.fail("Docker Compose not found");
|
|
139
|
+
console.log(chalk.yellow(" Docker Compose is included with Docker Desktop"));
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const { stdout } = await execa("node", ["--version"]);
|
|
144
|
+
const major = parseInt(stdout.replace("v", "").split(".")[0], 10);
|
|
145
|
+
if (major < 20) {
|
|
146
|
+
spinner.fail(`Node.js 20+ required (found ${stdout.trim()})`);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
} catch {
|
|
150
|
+
spinner.fail("Node.js not found");
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
await execa("pnpm", ["--version"]);
|
|
155
|
+
} catch {
|
|
156
|
+
spinner.warn("pnpm not found, installing...");
|
|
157
|
+
await execa("npm", ["install", "-g", "pnpm@9"]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function scaffoldProject(projectDir, config) {
|
|
161
|
+
mkdirSync(projectDir, { recursive: true });
|
|
162
|
+
const customerTokenSecret = crypto.randomBytes(32).toString("hex");
|
|
163
|
+
const authSecret = crypto.randomBytes(32).toString("hex");
|
|
164
|
+
writeFileSync(join(projectDir, "docker-compose.yml"), `services:
|
|
165
|
+
postgres:
|
|
166
|
+
image: postgres:16-alpine
|
|
167
|
+
container_name: ${config.directory}-postgres
|
|
168
|
+
ports:
|
|
169
|
+
- "5432:5432"
|
|
170
|
+
environment:
|
|
171
|
+
POSTGRES_DB: headless_commerce
|
|
172
|
+
POSTGRES_USER: postgres
|
|
173
|
+
POSTGRES_PASSWORD: postgres
|
|
174
|
+
volumes:
|
|
175
|
+
- postgres_data:/var/lib/postgresql/data
|
|
176
|
+
healthcheck:
|
|
177
|
+
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
178
|
+
interval: 5s
|
|
179
|
+
timeout: 5s
|
|
180
|
+
retries: 5
|
|
181
|
+
|
|
182
|
+
redis:
|
|
183
|
+
image: redis:7-alpine
|
|
184
|
+
container_name: ${config.directory}-redis
|
|
185
|
+
ports:
|
|
186
|
+
- "6379:6379"
|
|
187
|
+
volumes:
|
|
188
|
+
- redis_data:/data
|
|
189
|
+
healthcheck:
|
|
190
|
+
test: ["CMD", "redis-cli", "ping"]
|
|
191
|
+
interval: 5s
|
|
192
|
+
timeout: 5s
|
|
193
|
+
retries: 5
|
|
194
|
+
|
|
195
|
+
inngest:
|
|
196
|
+
image: inngest/inngest:latest
|
|
197
|
+
container_name: ${config.directory}-inngest
|
|
198
|
+
ports:
|
|
199
|
+
- "8288:8288"
|
|
200
|
+
environment:
|
|
201
|
+
INNGEST_EVENT_KEY: local-dev-key
|
|
202
|
+
INNGEST_SIGNING_KEY: local-dev-signing-key
|
|
203
|
+
command: inngest dev -u http://host.docker.internal:${config.port}/api/inngest
|
|
204
|
+
|
|
205
|
+
volumes:
|
|
206
|
+
postgres_data:
|
|
207
|
+
redis_data:
|
|
208
|
+
`);
|
|
209
|
+
writeFileSync(join(projectDir, "package.json"), JSON.stringify({
|
|
210
|
+
name: slugify(config.name),
|
|
211
|
+
private: true,
|
|
212
|
+
type: "module",
|
|
213
|
+
packageManager: "pnpm@9.15.0",
|
|
214
|
+
engines: { node: ">=20" },
|
|
215
|
+
scripts: {
|
|
216
|
+
dev: "turbo run dev",
|
|
217
|
+
build: "turbo run build",
|
|
218
|
+
typecheck: "turbo run typecheck",
|
|
219
|
+
"db:push": "pnpm --filter @headless-commerce/db push",
|
|
220
|
+
"db:seed": "pnpm --filter @headless-commerce/db seed",
|
|
221
|
+
"stripe:setup": "tsx apps/api/scripts/stripe-webhook-setup.ts"
|
|
222
|
+
},
|
|
223
|
+
devDependencies: {
|
|
224
|
+
"@types/node": "^20.14.0",
|
|
225
|
+
turbo: "^2.3.0",
|
|
226
|
+
typescript: "^5.5.0"
|
|
227
|
+
}
|
|
228
|
+
}, null, 2) + "\n");
|
|
229
|
+
writeFileSync(join(projectDir, "pnpm-workspace.yaml"), `packages:
|
|
230
|
+
- "apps/*"
|
|
231
|
+
- "packages/*"
|
|
232
|
+
`);
|
|
233
|
+
writeFileSync(join(projectDir, "turbo.json"), JSON.stringify({
|
|
234
|
+
$schema: "https://turbo.build/schema.json",
|
|
235
|
+
globalDependencies: [".env*"],
|
|
236
|
+
pipeline: {
|
|
237
|
+
build: {
|
|
238
|
+
dependsOn: ["^build"],
|
|
239
|
+
outputs: ["dist/**", ".next/**"],
|
|
240
|
+
env: [
|
|
241
|
+
"DATABASE_URL",
|
|
242
|
+
"REDIS_URL",
|
|
243
|
+
"NODE_ENV",
|
|
244
|
+
"PORT",
|
|
245
|
+
"STRIPE_SECRET_KEY",
|
|
246
|
+
"STRIPE_WEBHOOK_SECRET",
|
|
247
|
+
"NEXT_PUBLIC_API_URL",
|
|
248
|
+
"NEXT_PUBLIC_STOREFRONT_API_KEY",
|
|
249
|
+
"NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY"
|
|
250
|
+
]
|
|
251
|
+
},
|
|
252
|
+
dev: { cache: false, persistent: true },
|
|
253
|
+
typecheck: { dependsOn: ["^build"] }
|
|
254
|
+
}
|
|
255
|
+
}, null, 2) + "\n");
|
|
256
|
+
writeFileSync(join(projectDir, ".gitignore"), `node_modules
|
|
257
|
+
dist
|
|
258
|
+
.next
|
|
259
|
+
.env
|
|
260
|
+
.env.local
|
|
261
|
+
*.log
|
|
262
|
+
.turbo
|
|
263
|
+
`);
|
|
264
|
+
const apiEnvDir = join(projectDir, "apps", "api");
|
|
265
|
+
mkdirSync(apiEnvDir, { recursive: true });
|
|
266
|
+
writeFileSync(join(apiEnvDir, ".env"), `# Database
|
|
267
|
+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/headless_commerce
|
|
268
|
+
|
|
269
|
+
# Redis
|
|
270
|
+
REDIS_URL=redis://localhost:6379
|
|
271
|
+
|
|
272
|
+
# Inngest
|
|
273
|
+
INNGEST_EVENT_KEY=local-dev-key
|
|
274
|
+
INNGEST_SIGNING_KEY=local-dev-signing-key
|
|
275
|
+
|
|
276
|
+
# Stripe
|
|
277
|
+
STRIPE_SECRET_KEY=${config.stripeSecretKey || "sk_test_xxxxx"}
|
|
278
|
+
STRIPE_WEBHOOK_SECRET=whsec_xxxxx
|
|
279
|
+
|
|
280
|
+
# JWT
|
|
281
|
+
CUSTOMER_TOKEN_SECRET=${customerTokenSecret}
|
|
282
|
+
|
|
283
|
+
# Server
|
|
284
|
+
PORT=${config.port}
|
|
285
|
+
NODE_ENV=development
|
|
286
|
+
`);
|
|
287
|
+
const sfEnvDir = join(projectDir, "apps", "storefront");
|
|
288
|
+
mkdirSync(sfEnvDir, { recursive: true });
|
|
289
|
+
writeFileSync(join(sfEnvDir, ".env.local"), `NEXT_PUBLIC_API_URL=http://localhost:${config.port}/v1
|
|
290
|
+
NEXT_PUBLIC_STOREFRONT_API_KEY=pk_test_your_key_here
|
|
291
|
+
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${config.stripePublishableKey || "pk_test_xxxxx"}
|
|
292
|
+
CUSTOMER_AUTH_SECRET=${authSecret}
|
|
293
|
+
`);
|
|
294
|
+
const dashEnvDir = join(projectDir, "apps", "dashboard");
|
|
295
|
+
mkdirSync(dashEnvDir, { recursive: true });
|
|
296
|
+
writeFileSync(join(dashEnvDir, ".env.local"), `NEXT_PUBLIC_API_BASE_URL=http://localhost:${config.port}
|
|
297
|
+
NEXTAUTH_URL=http://localhost:3011
|
|
298
|
+
NEXTAUTH_SECRET=${authSecret}
|
|
299
|
+
AUTH_SECRET=${authSecret}
|
|
300
|
+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/headless_commerce
|
|
301
|
+
`);
|
|
302
|
+
writeFileSync(join(projectDir, "README.md"), `# ${config.name}
|
|
303
|
+
|
|
304
|
+
Powered by [Headless Commerce](https://github.com/your-repo/headless-commerce).
|
|
305
|
+
|
|
306
|
+
## Quick Start
|
|
307
|
+
|
|
308
|
+
\`\`\`bash
|
|
309
|
+
# Start infrastructure
|
|
310
|
+
docker compose up -d
|
|
311
|
+
|
|
312
|
+
# Install & build
|
|
313
|
+
pnpm install && pnpm build
|
|
314
|
+
|
|
315
|
+
# Push schema & seed data
|
|
316
|
+
pnpm db:push && pnpm db:seed
|
|
317
|
+
|
|
318
|
+
# Start development servers
|
|
319
|
+
pnpm dev
|
|
320
|
+
\`\`\`
|
|
321
|
+
|
|
322
|
+
## Ports
|
|
323
|
+
|
|
324
|
+
| Service | URL |
|
|
325
|
+
|---------|-----|
|
|
326
|
+
| API | http://localhost:${config.port} |
|
|
327
|
+
| Dashboard | http://localhost:3011 |
|
|
328
|
+
| Storefront | http://localhost:3012 |
|
|
329
|
+
| Inngest | http://localhost:8288 |
|
|
330
|
+
|
|
331
|
+
## API Keys
|
|
332
|
+
|
|
333
|
+
After seeding, check the console output for your API keys.
|
|
334
|
+
Use the Dashboard to manage products, orders, and settings.
|
|
335
|
+
`);
|
|
336
|
+
writeFileSync(join(projectDir, "setup.sh"), `#!/bin/bash
|
|
337
|
+
# This script sets up the headless-commerce source code.
|
|
338
|
+
# Run this if you haven't already cloned the source.
|
|
339
|
+
|
|
340
|
+
set -e
|
|
341
|
+
|
|
342
|
+
REPO_URL="https://github.com/your-repo/headless-commerce.git"
|
|
343
|
+
|
|
344
|
+
echo "Cloning headless-commerce..."
|
|
345
|
+
git clone --depth 1 "$REPO_URL" _source
|
|
346
|
+
|
|
347
|
+
echo "Linking packages..."
|
|
348
|
+
cp -r _source/packages ./
|
|
349
|
+
cp -r _source/apps ./
|
|
350
|
+
|
|
351
|
+
echo "Cleaning up..."
|
|
352
|
+
rm -rf _source
|
|
353
|
+
|
|
354
|
+
echo "Done! Run: pnpm install && pnpm build"
|
|
355
|
+
`);
|
|
356
|
+
}
|
|
357
|
+
async function waitForPostgres(projectDir, spinner) {
|
|
358
|
+
for (let i = 0; i < 30; i++) {
|
|
359
|
+
try {
|
|
360
|
+
await execa("docker", ["compose", "exec", "-T", "postgres", "pg_isready", "-U", "postgres"], {
|
|
361
|
+
cwd: projectDir
|
|
362
|
+
});
|
|
363
|
+
return;
|
|
364
|
+
} catch {
|
|
365
|
+
spinner.text = `Waiting for PostgreSQL to be ready... (${i + 1}s)`;
|
|
366
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
spinner.fail("PostgreSQL did not become ready in time");
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
function printSuccess(config) {
|
|
373
|
+
console.log("");
|
|
374
|
+
console.log(chalk.green.bold(" \u2713 Setup complete!"));
|
|
375
|
+
console.log("");
|
|
376
|
+
console.log(` ${chalk.bold("Next steps:")}`);
|
|
377
|
+
console.log("");
|
|
378
|
+
console.log(` ${chalk.cyan("cd")} ${config.directory}`);
|
|
379
|
+
console.log(` ${chalk.cyan("pnpm dev")}`);
|
|
380
|
+
console.log("");
|
|
381
|
+
console.log(` ${chalk.bold("Services:")}`);
|
|
382
|
+
console.log(` API ${chalk.cyan(`http://localhost:${config.port}`)}`);
|
|
383
|
+
console.log(` Dashboard ${chalk.cyan("http://localhost:3011")}`);
|
|
384
|
+
console.log(` Storefront ${chalk.cyan("http://localhost:3012")}`);
|
|
385
|
+
console.log(` API Docs ${chalk.cyan(`http://localhost:${config.port}/reference`)}`);
|
|
386
|
+
console.log(` Inngest ${chalk.cyan("http://localhost:8288")}`);
|
|
387
|
+
console.log("");
|
|
388
|
+
if (!config.stripeSecretKey) {
|
|
389
|
+
console.log(` ${chalk.yellow("Note:")} Stripe keys not configured.`);
|
|
390
|
+
console.log(` Edit ${chalk.dim(`${config.directory}/apps/api/.env`)} to add your Stripe keys.`);
|
|
391
|
+
console.log("");
|
|
392
|
+
}
|
|
393
|
+
console.log(` ${chalk.dim("Docs:")} https://docs.headlesscommerce.io`);
|
|
394
|
+
console.log("");
|
|
395
|
+
}
|
|
396
|
+
function slugify(text) {
|
|
397
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
398
|
+
}
|
|
399
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-headless-store",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Create a headless commerce store in minutes",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-headless-store": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsup",
|
|
15
|
+
"typecheck": "tsc --noEmit",
|
|
16
|
+
"dev": "tsx src/index.ts"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"chalk": "^5.3.0",
|
|
20
|
+
"commander": "^12.1.0",
|
|
21
|
+
"execa": "^9.3.0",
|
|
22
|
+
"ora": "^8.0.1",
|
|
23
|
+
"prompts": "^2.4.2"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/prompts": "^2.4.9",
|
|
27
|
+
"tsup": "^8.5.0",
|
|
28
|
+
"tsx": "^4.19.0",
|
|
29
|
+
"typescript": "^5.5.0"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"headless-commerce",
|
|
33
|
+
"ecommerce",
|
|
34
|
+
"cli",
|
|
35
|
+
"scaffolding",
|
|
36
|
+
"create"
|
|
37
|
+
],
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/Supia7/headless-commerce.git",
|
|
42
|
+
"directory": "packages/create-headless-store"
|
|
43
|
+
}
|
|
44
|
+
}
|