@njinlabs/njin 0.3.0 → 0.4.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/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # njin
2
2
 
3
+ [![CI](https://github.com/njinlabs/njin/actions/workflows/ci.yml/badge.svg)](https://github.com/njinlabs/njin/actions/workflows/ci.yml)
4
+ [![CodeQL](https://github.com/njinlabs/njin/actions/workflows/codeql.yml/badge.svg)](https://github.com/njinlabs/njin/actions/workflows/codeql.yml)
5
+ [![npm version](https://img.shields.io/npm/v/%40njinlabs%2Fnjin.svg)](https://www.npmjs.com/package/@njinlabs/njin)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+
3
8
  A modern framework for building company profiles, landing pages, and content-driven websites. Define your data model once — get a full REST API, admin panel schema, and server-rendered website out of the box.
4
9
 
5
10
  ## Stack
@@ -13,7 +18,7 @@ A modern framework for building company profiles, landing pages, and content-dri
13
18
  ## Quick start
14
19
 
15
20
  ```bash
16
- bun create njin-app my-web
21
+ bunx @njinlabs/njin create my-web
17
22
  cd my-web
18
23
  bunx njin dev
19
24
  ```
@@ -389,6 +394,7 @@ adapters: {
389
394
  ## Commands
390
395
 
391
396
  ```bash
397
+ bunx @njinlabs/njin create my-web # Scaffold a new project
392
398
  bunx njin dev # Start dev server (Elysia + Vite HMR)
393
399
  bunx njin build # Build for production -> ./out (public/, _admin/, views/, compiled server)
394
400
  bunx njin start # Run from source in production mode (no compile)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@njinlabs/njin",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "A modern framework for building company profiles, landing pages, and content-driven websites.",
5
5
  "type": "module",
6
6
  "keywords": ["bun", "elysia", "surrealdb", "edgejs", "cms", "framework"],
@@ -0,0 +1,82 @@
1
+ import { existsSync, mkdirSync, readdirSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+
4
+ const c = { reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m", cyan: "\x1b[36m", green: "\x1b[32m" };
5
+
6
+ const targetArg = process.argv[3] ?? ".";
7
+ const targetDir = resolve(process.cwd(), targetArg);
8
+ const projectName = targetArg === "." ? "njin-app" : targetArg.split(/[\\/]/).filter(Boolean).pop()!;
9
+
10
+ if (existsSync(targetDir) && readdirSync(targetDir).length > 0) {
11
+ console.error(`✖ Directory "${targetArg}" already exists and is not empty.`);
12
+ process.exit(1);
13
+ }
14
+
15
+ // This CLI's own package.json — read at runtime (not a static JSON import) so it
16
+ // resolves correctly whether njin is a project-local dependency or fetched fresh
17
+ // by `bunx`. Doubles as the source of truth for which tagged template to fetch,
18
+ // and for the version pin written into the scaffolded project below.
19
+ const pkg = await Bun.file(join(import.meta.dir, "../../package.json")).json();
20
+ const tag = `v${pkg.version}`;
21
+ const tarballUrl = `https://codeload.github.com/njinlabs/njin/tar.gz/refs/tags/${tag}`;
22
+
23
+ console.log(`\nFetching template for njin ${tag}...\n`);
24
+
25
+ const res = await fetch(tarballUrl);
26
+ if (!res.ok || !res.body) {
27
+ console.error(
28
+ `✖ Could not download the project template for njin ${tag} (HTTP ${res.status}).\n` +
29
+ ` Check your internet connection, or that tag "${tag}" exists at github.com/njinlabs/njin.`,
30
+ );
31
+ process.exit(1);
32
+ }
33
+
34
+ mkdirSync(targetDir, { recursive: true });
35
+
36
+ // `--strip-components=2` drops the `njin-<version>/template/` prefix baked into
37
+ // GitHub's tag-tarball layout, so template/ contents land directly in targetDir.
38
+ const tar = Bun.spawn(["tar", "-xz", "--strip-components=2", "-C", targetDir, `njin-${pkg.version}/template`], {
39
+ stdin: res.body,
40
+ stdout: "inherit",
41
+ stderr: "inherit",
42
+ });
43
+
44
+ const tarExitCode = await tar.exited;
45
+
46
+ if (tarExitCode !== 0) {
47
+ console.error(
48
+ `✖ Failed to extract the template (tar exited with code ${tarExitCode}).\n` +
49
+ ` Make sure "tar" is installed and available on your PATH.`,
50
+ );
51
+ process.exit(tarExitCode);
52
+ }
53
+
54
+ const pkgPath = join(targetDir, "package.json");
55
+ const scaffoldedPkg = await Bun.file(pkgPath).json();
56
+ scaffoldedPkg.name = projectName;
57
+ scaffoldedPkg.dependencies = { "@njinlabs/njin": `^${pkg.version}`, ...scaffoldedPkg.dependencies };
58
+ await Bun.write(pkgPath, JSON.stringify(scaffoldedPkg, null, 2) + "\n");
59
+
60
+ console.log("Installing dependencies...\n");
61
+
62
+ const install = Bun.spawn(["bun", "install"], {
63
+ cwd: targetDir,
64
+ stdout: "inherit",
65
+ stderr: "inherit",
66
+ });
67
+
68
+ const installExitCode = await install.exited;
69
+
70
+ if (installExitCode !== 0) {
71
+ console.error(`\n✖ "bun install" failed (exit code ${installExitCode}).`);
72
+ console.error(` The project was scaffolded at ${targetDir}, but dependencies are not installed.`);
73
+ console.error(` Run "cd ${targetArg} && bun install" manually to retry.\n`);
74
+ process.exit(installExitCode);
75
+ }
76
+
77
+ console.log(`
78
+ ${c.bold}${c.cyan}njin create${c.reset} ${c.dim}done${c.reset}
79
+
80
+ ${c.green}➜${c.reset} cd ${targetArg === "." ? "." : targetArg}
81
+ ${c.green}➜${c.reset} bunx njin dev
82
+ `);
package/src/cli/index.ts CHANGED
@@ -2,6 +2,9 @@
2
2
  const [command] = process.argv.slice(2);
3
3
 
4
4
  switch (command) {
5
+ case "create":
6
+ await import("./create");
7
+ break;
5
8
  case "dev":
6
9
  await import("./dev");
7
10
  break;
@@ -12,10 +15,11 @@ switch (command) {
12
15
  await import("./build");
13
16
  break;
14
17
  default:
15
- console.log(`Usage: njin <dev|build|start>
18
+ console.log(`Usage: njin <create|dev|build|start>
16
19
 
17
- dev Run the dev server (Vite HMR + live reload)
18
- build Build for production -> ./out (public/, _admin/, views/, server)
19
- start Run from source in production mode (no compile)`);
20
+ create <dir> Scaffold a new project (defaults to current directory)
21
+ dev Run the dev server (Vite HMR + live reload)
22
+ build Build for production -> ./out (public/, _admin/, views/, server)
23
+ start Run from source in production mode (no compile)`);
20
24
  process.exit(command ? 1 : 0);
21
25
  }