@shipindays/shipindays 0.1.5 → 0.1.6

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.

Potentially problematic release.


This version of @shipindays/shipindays might be problematic. Click here for more details.

Files changed (2) hide show
  1. package/index.js +66 -64
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -20,7 +20,7 @@ const BLOCKS_DIR = path.join(TEMPLATES_DIR, "blocks");
20
20
 
21
21
  function printBanner() {
22
22
  console.log("\n");
23
- console.log(chalk.green(" shipindays testing"));
23
+ console.log(chalk.green(" shipindays"));
24
24
  console.log(chalk.dim(" Ship your SaaS in days, not months."));
25
25
  console.log(chalk.dim(" https://shipindays.nikhilsai.com\n"));
26
26
  }
@@ -72,7 +72,9 @@ const EMAIL_PROVIDERS = {
72
72
 
73
73
  const ENV_VARS = {
74
74
  base: {
75
- "# App": ["NEXT_PUBLIC_APP_URL=http://localhost:3000"],
75
+ "# App": [
76
+ "NEXT_PUBLIC_APP_URL=http://localhost:3000",
77
+ ],
76
78
  },
77
79
 
78
80
  auth: {
@@ -84,19 +86,26 @@ const ENV_VARS = {
84
86
  ],
85
87
  },
86
88
  nextauth: {
87
- "# NextAuth": ["AUTH_SECRET=", "NEXTAUTH_URL=http://localhost:3000"],
89
+ "# NextAuth": [
90
+ "AUTH_SECRET=",
91
+ "NEXTAUTH_URL=http://localhost:3000",
92
+ ],
88
93
  "# OAuth — Google (console.cloud.google.com)": [
89
94
  "AUTH_GOOGLE_ID=",
90
95
  "AUTH_GOOGLE_SECRET=",
91
96
  ],
92
- "# OAuth — GitHub (github.com → Settings → Developer settings → OAuth Apps)":
93
- ["AUTH_GITHUB_ID=", "AUTH_GITHUB_SECRET="],
97
+ "# OAuth — GitHub (github.com → Settings → Developer settings → OAuth Apps)": [
98
+ "AUTH_GITHUB_ID=",
99
+ "AUTH_GITHUB_SECRET=",
100
+ ],
94
101
  },
95
102
  },
96
103
 
97
104
  email: {
98
105
  resend: {
99
- "# Resend (resend.com → API Keys)": ["RESEND_API_KEY="],
106
+ "# Resend (resend.com → API Keys)": [
107
+ "RESEND_API_KEY=",
108
+ ],
100
109
  },
101
110
  nodemailer: {
102
111
  "# SMTP / Nodemailer": [
@@ -148,19 +157,19 @@ async function injectBlock(feature, provider, targetPath) {
148
157
  const blockSrcDir = path.join(blockRoot, "src");
149
158
 
150
159
  // Check block folder exists
151
- if (!(await fs.pathExists(blockRoot))) {
160
+ if (!await fs.pathExists(blockRoot)) {
152
161
  throw new Error(
153
162
  `Block not found: ${blockRoot}\n` +
154
- `Make sure templates/blocks/${feature}/${provider}/ exists.`,
163
+ `Make sure templates/blocks/${feature}/${provider}/ exists.`
155
164
  );
156
165
  }
157
166
 
158
167
  // Check src/ folder exists inside block
159
- if (!(await fs.pathExists(blockSrcDir))) {
168
+ if (!await fs.pathExists(blockSrcDir)) {
160
169
  throw new Error(
161
170
  `Block src/ folder missing: ${blockSrcDir}\n` +
162
- `Every block must have a src/ folder.\n` +
163
- `Structure: templates/blocks/${feature}/${provider}/src/...`,
171
+ `Every block must have a src/ folder.\n` +
172
+ `Structure: templates/blocks/${feature}/${provider}/src/...`
164
173
  );
165
174
  }
166
175
 
@@ -169,7 +178,9 @@ async function injectBlock(feature, provider, targetPath) {
169
178
  // - New files → created fresh in the project
170
179
  await fs.copy(blockSrcDir, path.join(targetPath, "src"), {
171
180
  overwrite: true,
172
- filter: (src) => !src.includes("node_modules") && !src.includes(".next"),
181
+ filter: (src) =>
182
+ !src.includes("node_modules") &&
183
+ !src.includes(".next"),
173
184
  });
174
185
  }
175
186
 
@@ -184,8 +195,8 @@ async function mergePackageJson(targetPath, feature, provider) {
184
195
  const blockPkgPath = path.join(BLOCKS_DIR, feature, provider, "package.json");
185
196
  const targetPkgPath = path.join(targetPath, "package.json");
186
197
 
187
- if (!(await fs.pathExists(blockPkgPath))) return;
188
- if (!(await fs.pathExists(targetPkgPath))) return;
198
+ if (!await fs.pathExists(blockPkgPath)) return;
199
+ if (!await fs.pathExists(targetPkgPath)) return;
189
200
 
190
201
  const targetPkg = await fs.readJson(targetPkgPath);
191
202
  const blockPkg = await fs.readJson(blockPkgPath);
@@ -233,16 +244,10 @@ function buildEnvExample(choices) {
233
244
  // ─────────────────────────────────────────────────────────────────────────────
234
245
  // HELPERS
235
246
  // ─────────────────────────────────────────────────────────────────────────────
236
- function isValidName(n) {
237
- return /^[a-zA-Z0-9-_]+$/.test(n);
238
- }
247
+ function isValidName(n) { return /^[a-zA-Z0-9-_]+$/.test(n); }
239
248
 
240
249
  function toSlug(s) {
241
- return s
242
- .trim()
243
- .toLowerCase()
244
- .replace(/\s+/g, "-")
245
- .replace(/[^a-z0-9-_]/g, "");
250
+ return s.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-_]/g, "");
246
251
  }
247
252
 
248
253
  function detectPM() {
@@ -250,9 +255,7 @@ function detectPM() {
250
255
  return a.includes("pnpm") ? "pnpm" : a.includes("yarn") ? "yarn" : "npm";
251
256
  }
252
257
 
253
- function run(cmd, cwd) {
254
- execSync(cmd, { cwd, stdio: "inherit" });
255
- }
258
+ function run(cmd, cwd) { execSync(cmd, { cwd, stdio: "inherit" }); }
256
259
 
257
260
  function buildGitignore() {
258
261
  return [
@@ -303,9 +306,7 @@ function printNextSteps(projectDir, pm, choices) {
303
306
  s(`${runCmd} db:push`);
304
307
  s(`${runCmd} dev`);
305
308
  console.log("");
306
- console.log(
307
- chalk.dim(" GitHub → https://github.com/nikhilsaiankilla/shipindays"),
308
- );
309
+ console.log(chalk.dim(" GitHub → https://github.com/nikhilsaiankilla/shipindays"));
309
310
  console.log(chalk.dim(" Twitter → https://x.com/itzznikhilsai"));
310
311
  console.log("");
311
312
  console.log(chalk.green(" ⚡ Now go build what only you can build.\n"));
@@ -333,10 +334,7 @@ async function main() {
333
334
  }
334
335
  },
335
336
  });
336
- if (p.isCancel(answer)) {
337
- p.cancel("Cancelled.");
338
- process.exit(0);
339
- }
337
+ if (p.isCancel(answer)) { p.cancel("Cancelled."); process.exit(0); }
340
338
  projectDir = answer;
341
339
  }
342
340
 
@@ -348,17 +346,14 @@ async function main() {
348
346
  ? path.basename(process.cwd())
349
347
  : toSlug(path.basename(projectDir.replace(/^\.\//, "")));
350
348
 
351
- if (!isCurrentDir && (await fs.pathExists(targetPath))) {
352
- const files = (await fs.readdir(targetPath)).filter((f) => f !== ".git");
349
+ if (!isCurrentDir && await fs.pathExists(targetPath)) {
350
+ const files = (await fs.readdir(targetPath)).filter(f => f !== ".git");
353
351
  if (files.length > 0) {
354
352
  const ok = await p.confirm({
355
353
  message: `${projectDir} is not empty. Overwrite?`,
356
354
  initialValue: false,
357
355
  });
358
- if (p.isCancel(ok) || !ok) {
359
- p.cancel("Cancelled.");
360
- process.exit(0);
361
- }
356
+ if (p.isCancel(ok) || !ok) { p.cancel("Cancelled."); process.exit(0); }
362
357
  }
363
358
  }
364
359
 
@@ -366,52 +361,44 @@ async function main() {
366
361
  const authProvider = await p.select({
367
362
  message: "Auth provider",
368
363
  options: Object.entries(AUTH_PROVIDERS).map(([value, { label, hint }]) => ({
369
- value,
370
- label,
371
- hint,
364
+ value, label, hint,
372
365
  })),
373
366
  });
374
- if (p.isCancel(authProvider)) {
375
- p.cancel("Cancelled.");
376
- process.exit(0);
377
- }
367
+ if (p.isCancel(authProvider)) { p.cancel("Cancelled."); process.exit(0); }
378
368
 
379
369
  // ── 3. Pick email provider ─────────────────────────────────────────────────
380
370
  const emailProvider = await p.select({
381
371
  message: "Email provider",
382
- options: Object.entries(EMAIL_PROVIDERS).map(
383
- ([value, { label, hint }]) => ({
384
- value,
385
- label,
386
- hint,
387
- }),
388
- ),
372
+ options: Object.entries(EMAIL_PROVIDERS).map(([value, { label, hint }]) => ({
373
+ value, label, hint,
374
+ })),
389
375
  });
390
- if (p.isCancel(emailProvider)) {
391
- p.cancel("Cancelled.");
392
- process.exit(0);
393
- }
376
+ if (p.isCancel(emailProvider)) { p.cancel("Cancelled."); process.exit(0); }
394
377
 
395
378
  const choices = {
396
379
  auth: authProvider,
397
380
  email: emailProvider,
398
381
  };
399
382
 
383
+ // ── 4. Git + install ───────────────────────────────────────────────────────
384
+ const initGit = await p.confirm({
385
+ message: "Initialize a git repository?",
386
+ initialValue: true,
387
+ });
388
+ if (p.isCancel(initGit)) { p.cancel("Cancelled."); process.exit(0); }
389
+
400
390
  const pm = detectPM();
401
391
  const install = await p.confirm({
402
392
  message: `Install dependencies with ${pm}?`,
403
393
  initialValue: true,
404
394
  });
405
- if (p.isCancel(install)) {
406
- p.cancel("Cancelled.");
407
- process.exit(0);
408
- }
395
+ if (p.isCancel(install)) { p.cancel("Cancelled."); process.exit(0); }
409
396
 
410
397
  const spin = p.spinner();
411
398
 
412
399
  // ── 5. Copy base template ──────────────────────────────────────────────────
413
400
  spin.start("Copying base template...");
414
- if (!(await fs.pathExists(BASE_DIR))) {
401
+ if (!await fs.pathExists(BASE_DIR)) {
415
402
  spin.stop(chalk.red(`Base template not found: ${BASE_DIR}`));
416
403
  process.exit(1);
417
404
  }
@@ -446,7 +433,7 @@ async function main() {
446
433
  spin.start("Writing .env.example...");
447
434
  await fs.outputFile(
448
435
  path.join(targetPath, ".env.example"),
449
- buildEnvExample(choices),
436
+ buildEnvExample(choices)
450
437
  );
451
438
  spin.stop(".env.example written.");
452
439
 
@@ -463,12 +450,27 @@ async function main() {
463
450
  }
464
451
  spin.stop("package.json configured.");
465
452
 
453
+ // ── 11. Git init ───────────────────────────────────────────────────────────
454
+ if (initGit) {
455
+ spin.start("Initialising git...");
456
+ try {
457
+ run("git init", targetPath);
458
+ run("git add -A", targetPath);
459
+ run(`git commit -m "chore: scaffold from shipindays"`, targetPath);
460
+ spin.stop("Git initialised.");
461
+ } catch {
462
+ spin.stop(chalk.yellow("Git skipped — run manually."));
463
+ }
464
+ }
465
+
466
466
  // ── 12. Install dependencies ───────────────────────────────────────────────
467
467
  if (install) {
468
468
  spin.start(`Installing with ${pm}...`);
469
469
  try {
470
470
  const cmd =
471
- pm === "yarn" ? "yarn" : pm === "pnpm" ? "pnpm install" : "npm install";
471
+ pm === "yarn" ? "yarn" :
472
+ pm === "pnpm" ? "pnpm install" :
473
+ "npm install";
472
474
  run(cmd, targetPath);
473
475
  spin.stop("Dependencies installed.");
474
476
  } catch {
@@ -483,4 +485,4 @@ async function main() {
483
485
  main().catch((err) => {
484
486
  console.error(chalk.red("\n Fatal: " + err.message));
485
487
  process.exit(1);
486
- });
488
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipindays/shipindays",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Scaffold a production ready Next.js SaaS in seconds. Pick your stack, get auth + payments + email wired up.",
5
5
  "type": "module",
6
6
  "bin": {