create-nene 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/LICENSE +21 -0
- package/README.md +61 -0
- package/bin/create-nene.js +8 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +192 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
- package/templates/default/README.md +43 -0
- package/templates/default/_gitignore +41 -0
- package/templates/default/eslint.config.mjs +10 -0
- package/templates/default/package.json +24 -0
- package/templates/default/src/app/layout.tsx +14 -0
- package/templates/default/src/app/page.tsx +28 -0
- package/templates/default/src/server/api/hello.ts +14 -0
- package/templates/default/src/server/index.ts +3 -0
- package/templates/default/tsconfig.json +24 -0
- package/templates/minimal/README.md +11 -0
- package/templates/minimal/_gitignore +6 -0
- package/templates/minimal/package.json +22 -0
- package/templates/minimal/src/app/layout.tsx +9 -0
- package/templates/minimal/src/app/page.tsx +7 -0
- package/templates/minimal/tsconfig.json +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 nene.js
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# create-nene
|
|
2
|
+
|
|
3
|
+
Create a new [nene.js](https://nene.js.org) project with a single command.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# npm
|
|
9
|
+
npm create nene@latest
|
|
10
|
+
|
|
11
|
+
# yarn
|
|
12
|
+
yarn create nene
|
|
13
|
+
|
|
14
|
+
# pnpm
|
|
15
|
+
pnpm create nene
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### With project name
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm create nene@latest my-app
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Templates
|
|
25
|
+
|
|
26
|
+
- **default** - Full-stack setup with frontend and backend
|
|
27
|
+
- **minimal** - Minimal setup for quick prototyping
|
|
28
|
+
|
|
29
|
+
## Options
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
Usage: create-nene [project-name] [options]
|
|
33
|
+
|
|
34
|
+
Options:
|
|
35
|
+
-t, --template <template> Template to use (default, minimal)
|
|
36
|
+
--typescript Use TypeScript (default: true)
|
|
37
|
+
--no-typescript Do not use TypeScript
|
|
38
|
+
--eslint Use ESLint (default: true)
|
|
39
|
+
--no-eslint Do not use ESLint
|
|
40
|
+
-V, --version Output the version number
|
|
41
|
+
-h, --help Display help for command
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## What's Inside
|
|
45
|
+
|
|
46
|
+
A newly created project includes:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
my-app/
|
|
50
|
+
├── src/
|
|
51
|
+
│ ├── app/ # Frontend pages and layouts
|
|
52
|
+
│ └── server/ # Backend API and services
|
|
53
|
+
├── public/ # Static assets
|
|
54
|
+
├── package.json
|
|
55
|
+
├── tsconfig.json
|
|
56
|
+
└── README.md
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { program } from "commander";
|
|
3
|
+
import prompts from "prompts";
|
|
4
|
+
import pc from "picocolors";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
import { execSync } from "child_process";
|
|
9
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
var __dirname = path.dirname(__filename);
|
|
11
|
+
function validateProjectName(name) {
|
|
12
|
+
const validNameRegex = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
13
|
+
return validNameRegex.test(name);
|
|
14
|
+
}
|
|
15
|
+
function detectPackageManager() {
|
|
16
|
+
const userAgent = process.env.npm_config_user_agent;
|
|
17
|
+
if (userAgent) {
|
|
18
|
+
if (userAgent.startsWith("yarn")) return "yarn";
|
|
19
|
+
if (userAgent.startsWith("pnpm")) return "pnpm";
|
|
20
|
+
}
|
|
21
|
+
return "npm";
|
|
22
|
+
}
|
|
23
|
+
function copyDir(src, dest) {
|
|
24
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
25
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const srcPath = path.join(src, entry.name);
|
|
28
|
+
const destPath = path.join(dest, entry.name);
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
copyDir(srcPath, destPath);
|
|
31
|
+
} else {
|
|
32
|
+
fs.copyFileSync(srcPath, destPath);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function getTemplateDir(template) {
|
|
37
|
+
const devPath = path.resolve(__dirname, "..", "templates", template);
|
|
38
|
+
const prodPath = path.resolve(__dirname, "..", "..", "templates", template);
|
|
39
|
+
if (fs.existsSync(devPath)) return devPath;
|
|
40
|
+
if (fs.existsSync(prodPath)) return prodPath;
|
|
41
|
+
throw new Error(`Template "${template}" not found`);
|
|
42
|
+
}
|
|
43
|
+
function updatePackageJson(projectPath, projectName) {
|
|
44
|
+
const pkgPath = path.join(projectPath, "package.json");
|
|
45
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
46
|
+
pkg.name = projectName;
|
|
47
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
48
|
+
}
|
|
49
|
+
function renameGitignore(projectPath) {
|
|
50
|
+
const gitignorePath = path.join(projectPath, "_gitignore");
|
|
51
|
+
const targetPath = path.join(projectPath, ".gitignore");
|
|
52
|
+
if (fs.existsSync(gitignorePath)) {
|
|
53
|
+
fs.renameSync(gitignorePath, targetPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function promptForOptions(projectName) {
|
|
57
|
+
const defaultProjectName = projectName || "my-nene-app";
|
|
58
|
+
const response = await prompts(
|
|
59
|
+
[
|
|
60
|
+
{
|
|
61
|
+
type: projectName ? null : "text",
|
|
62
|
+
name: "projectName",
|
|
63
|
+
message: "Project name:",
|
|
64
|
+
initial: defaultProjectName,
|
|
65
|
+
validate: (value) => {
|
|
66
|
+
if (!value) return "Project name is required";
|
|
67
|
+
if (!validateProjectName(value)) {
|
|
68
|
+
return "Invalid project name. Use lowercase letters, numbers, and hyphens only.";
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
type: "select",
|
|
75
|
+
name: "template",
|
|
76
|
+
message: "Select a template:",
|
|
77
|
+
choices: [
|
|
78
|
+
{
|
|
79
|
+
title: "Default",
|
|
80
|
+
description: "Full-stack with unified frontend and backend",
|
|
81
|
+
value: "default"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
title: "Minimal",
|
|
85
|
+
description: "Minimal setup for quick prototyping",
|
|
86
|
+
value: "minimal"
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
initial: 0
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
type: "confirm",
|
|
93
|
+
name: "typescript",
|
|
94
|
+
message: "Use TypeScript?",
|
|
95
|
+
initial: true
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: "confirm",
|
|
99
|
+
name: "eslint",
|
|
100
|
+
message: "Use ESLint?",
|
|
101
|
+
initial: true
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: "select",
|
|
105
|
+
name: "packageManager",
|
|
106
|
+
message: "Select a package manager:",
|
|
107
|
+
choices: [
|
|
108
|
+
{ title: "npm", value: "npm" },
|
|
109
|
+
{ title: "yarn", value: "yarn" },
|
|
110
|
+
{ title: "pnpm", value: "pnpm" }
|
|
111
|
+
],
|
|
112
|
+
initial: ["npm", "yarn", "pnpm"].indexOf(detectPackageManager())
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
{
|
|
116
|
+
onCancel: () => {
|
|
117
|
+
console.log(pc.red("\nOperation cancelled."));
|
|
118
|
+
process.exit(0);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
return {
|
|
123
|
+
projectName: projectName || response.projectName,
|
|
124
|
+
template: response.template,
|
|
125
|
+
typescript: response.typescript,
|
|
126
|
+
eslint: response.eslint,
|
|
127
|
+
packageManager: response.packageManager
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
async function createProject(options) {
|
|
131
|
+
const { projectName, template, packageManager } = options;
|
|
132
|
+
const projectPath = path.resolve(process.cwd(), projectName);
|
|
133
|
+
if (fs.existsSync(projectPath)) {
|
|
134
|
+
const { overwrite } = await prompts({
|
|
135
|
+
type: "confirm",
|
|
136
|
+
name: "overwrite",
|
|
137
|
+
message: `Directory "${projectName}" already exists. Overwrite?`,
|
|
138
|
+
initial: false
|
|
139
|
+
});
|
|
140
|
+
if (!overwrite) {
|
|
141
|
+
console.log(pc.red("Operation cancelled."));
|
|
142
|
+
process.exit(0);
|
|
143
|
+
}
|
|
144
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
145
|
+
}
|
|
146
|
+
console.log();
|
|
147
|
+
console.log(pc.cyan(`Creating a new nene.js project in ${pc.bold(projectPath)}`));
|
|
148
|
+
console.log();
|
|
149
|
+
const templateDir = getTemplateDir(template);
|
|
150
|
+
copyDir(templateDir, projectPath);
|
|
151
|
+
renameGitignore(projectPath);
|
|
152
|
+
updatePackageJson(projectPath, projectName);
|
|
153
|
+
console.log(pc.cyan("Installing dependencies..."));
|
|
154
|
+
console.log();
|
|
155
|
+
const installCmd = {
|
|
156
|
+
npm: "npm install",
|
|
157
|
+
yarn: "yarn",
|
|
158
|
+
pnpm: "pnpm install"
|
|
159
|
+
}[packageManager];
|
|
160
|
+
try {
|
|
161
|
+
execSync(installCmd, {
|
|
162
|
+
cwd: projectPath,
|
|
163
|
+
stdio: "inherit"
|
|
164
|
+
});
|
|
165
|
+
} catch {
|
|
166
|
+
console.log(pc.yellow("\nFailed to install dependencies. You can install them manually."));
|
|
167
|
+
}
|
|
168
|
+
console.log();
|
|
169
|
+
console.log(pc.green("Success!") + ` Created ${pc.bold(projectName)} at ${projectPath}`);
|
|
170
|
+
console.log();
|
|
171
|
+
console.log("Next steps:");
|
|
172
|
+
console.log();
|
|
173
|
+
console.log(` ${pc.cyan("cd")} ${projectName}`);
|
|
174
|
+
console.log(` ${pc.cyan(packageManager === "npm" ? "npm run" : packageManager)} dev`);
|
|
175
|
+
console.log();
|
|
176
|
+
console.log("Happy coding!");
|
|
177
|
+
console.log();
|
|
178
|
+
}
|
|
179
|
+
async function main() {
|
|
180
|
+
program.name("create-nene").description("Create a new nene.js project").version("0.1.0").argument("[project-name]", "Name of the project").option("-t, --template <template>", "Template to use (default, minimal)").option("--typescript", "Use TypeScript (default: true)").option("--no-typescript", "Do not use TypeScript").option("--eslint", "Use ESLint (default: true)").option("--no-eslint", "Do not use ESLint").action(async (projectName) => {
|
|
181
|
+
console.log();
|
|
182
|
+
console.log(pc.bold(pc.cyan(" nene.js ") + "- The AI-native full-stack framework"));
|
|
183
|
+
console.log();
|
|
184
|
+
const options = await promptForOptions(projectName);
|
|
185
|
+
await createProject(options);
|
|
186
|
+
});
|
|
187
|
+
await program.parseAsync(process.argv);
|
|
188
|
+
}
|
|
189
|
+
export {
|
|
190
|
+
main
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { program } from \"commander\";\nimport prompts from \"prompts\";\nimport pc from \"picocolors\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { execSync } from \"node:child_process\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\ninterface ProjectOptions {\n projectName: string;\n template: \"default\" | \"minimal\";\n typescript: boolean;\n eslint: boolean;\n packageManager: \"npm\" | \"yarn\" | \"pnpm\";\n}\n\nfunction validateProjectName(name: string): boolean {\n const validNameRegex = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/;\n return validNameRegex.test(name);\n}\n\nfunction detectPackageManager(): \"npm\" | \"yarn\" | \"pnpm\" {\n const userAgent = process.env.npm_config_user_agent;\n if (userAgent) {\n if (userAgent.startsWith(\"yarn\")) return \"yarn\";\n if (userAgent.startsWith(\"pnpm\")) return \"pnpm\";\n }\n return \"npm\";\n}\n\nfunction copyDir(src: string, dest: string): void {\n fs.mkdirSync(dest, { recursive: true });\n const entries = fs.readdirSync(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n\n if (entry.isDirectory()) {\n copyDir(srcPath, destPath);\n } else {\n fs.copyFileSync(srcPath, destPath);\n }\n }\n}\n\nfunction getTemplateDir(template: string): string {\n // In development, templates are relative to src\n // In production (dist), templates are at the package root\n const devPath = path.resolve(__dirname, \"..\", \"templates\", template);\n const prodPath = path.resolve(__dirname, \"..\", \"..\", \"templates\", template);\n \n if (fs.existsSync(devPath)) return devPath;\n if (fs.existsSync(prodPath)) return prodPath;\n \n throw new Error(`Template \"${template}\" not found`);\n}\n\nfunction updatePackageJson(projectPath: string, projectName: string): void {\n const pkgPath = path.join(projectPath, \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n pkg.name = projectName;\n fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + \"\\n\");\n}\n\nfunction renameGitignore(projectPath: string): void {\n const gitignorePath = path.join(projectPath, \"_gitignore\");\n const targetPath = path.join(projectPath, \".gitignore\");\n if (fs.existsSync(gitignorePath)) {\n fs.renameSync(gitignorePath, targetPath);\n }\n}\n\nasync function promptForOptions(projectName?: string): Promise<ProjectOptions> {\n const defaultProjectName = projectName || \"my-nene-app\";\n \n const response = await prompts(\n [\n {\n type: projectName ? null : \"text\",\n name: \"projectName\",\n message: \"Project name:\",\n initial: defaultProjectName,\n validate: (value: string) => {\n if (!value) return \"Project name is required\";\n if (!validateProjectName(value)) {\n return \"Invalid project name. Use lowercase letters, numbers, and hyphens only.\";\n }\n return true;\n },\n },\n {\n type: \"select\",\n name: \"template\",\n message: \"Select a template:\",\n choices: [\n {\n title: \"Default\",\n description: \"Full-stack with unified frontend and backend\",\n value: \"default\",\n },\n {\n title: \"Minimal\",\n description: \"Minimal setup for quick prototyping\",\n value: \"minimal\",\n },\n ],\n initial: 0,\n },\n {\n type: \"confirm\",\n name: \"typescript\",\n message: \"Use TypeScript?\",\n initial: true,\n },\n {\n type: \"confirm\",\n name: \"eslint\",\n message: \"Use ESLint?\",\n initial: true,\n },\n {\n type: \"select\",\n name: \"packageManager\",\n message: \"Select a package manager:\",\n choices: [\n { title: \"npm\", value: \"npm\" },\n { title: \"yarn\", value: \"yarn\" },\n { title: \"pnpm\", value: \"pnpm\" },\n ],\n initial: [\"npm\", \"yarn\", \"pnpm\"].indexOf(detectPackageManager()),\n },\n ],\n {\n onCancel: () => {\n console.log(pc.red(\"\\nOperation cancelled.\"));\n process.exit(0);\n },\n }\n );\n\n return {\n projectName: projectName || response.projectName,\n template: response.template,\n typescript: response.typescript,\n eslint: response.eslint,\n packageManager: response.packageManager,\n };\n}\n\nasync function createProject(options: ProjectOptions): Promise<void> {\n const { projectName, template, packageManager } = options;\n const projectPath = path.resolve(process.cwd(), projectName);\n\n // Check if directory exists\n if (fs.existsSync(projectPath)) {\n const { overwrite } = await prompts({\n type: \"confirm\",\n name: \"overwrite\",\n message: `Directory \"${projectName}\" already exists. Overwrite?`,\n initial: false,\n });\n\n if (!overwrite) {\n console.log(pc.red(\"Operation cancelled.\"));\n process.exit(0);\n }\n\n fs.rmSync(projectPath, { recursive: true, force: true });\n }\n\n console.log();\n console.log(pc.cyan(`Creating a new nene.js project in ${pc.bold(projectPath)}`));\n console.log();\n\n // Copy template\n const templateDir = getTemplateDir(template);\n copyDir(templateDir, projectPath);\n\n // Rename _gitignore to .gitignore\n renameGitignore(projectPath);\n\n // Update package.json with project name\n updatePackageJson(projectPath, projectName);\n\n // Install dependencies\n console.log(pc.cyan(\"Installing dependencies...\"));\n console.log();\n\n const installCmd = {\n npm: \"npm install\",\n yarn: \"yarn\",\n pnpm: \"pnpm install\",\n }[packageManager];\n\n try {\n execSync(installCmd, {\n cwd: projectPath,\n stdio: \"inherit\",\n });\n } catch {\n console.log(pc.yellow(\"\\nFailed to install dependencies. You can install them manually.\"));\n }\n\n // Success message\n console.log();\n console.log(pc.green(\"Success!\") + ` Created ${pc.bold(projectName)} at ${projectPath}`);\n console.log();\n console.log(\"Next steps:\");\n console.log();\n console.log(` ${pc.cyan(\"cd\")} ${projectName}`);\n console.log(` ${pc.cyan(packageManager === \"npm\" ? \"npm run\" : packageManager)} dev`);\n console.log();\n console.log(\"Happy coding!\");\n console.log();\n}\n\nexport async function main(): Promise<void> {\n program\n .name(\"create-nene\")\n .description(\"Create a new nene.js project\")\n .version(\"0.1.0\")\n .argument(\"[project-name]\", \"Name of the project\")\n .option(\"-t, --template <template>\", \"Template to use (default, minimal)\")\n .option(\"--typescript\", \"Use TypeScript (default: true)\")\n .option(\"--no-typescript\", \"Do not use TypeScript\")\n .option(\"--eslint\", \"Use ESLint (default: true)\")\n .option(\"--no-eslint\", \"Do not use ESLint\")\n .action(async (projectName: string | undefined) => {\n console.log();\n console.log(pc.bold(pc.cyan(\" nene.js \") + \"- The AI-native full-stack framework\"));\n console.log();\n\n const options = await promptForOptions(projectName);\n await createProject(options);\n });\n\n await program.parseAsync(process.argv);\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-nene",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Create a new nene.js project with a single command",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-nene": "./bin/create-nene.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"dist",
|
|
12
|
+
"templates"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsup",
|
|
16
|
+
"dev": "tsup --watch",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"nene",
|
|
21
|
+
"nenejs",
|
|
22
|
+
"create",
|
|
23
|
+
"scaffold",
|
|
24
|
+
"cli",
|
|
25
|
+
"fullstack",
|
|
26
|
+
"typescript"
|
|
27
|
+
],
|
|
28
|
+
"author": "nene.js Team",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/nene-js/nene",
|
|
33
|
+
"directory": "packages/create-nene"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://nene.js.org",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/nene-js/nene/issues"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18.0.0"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"commander": "^12.1.0",
|
|
44
|
+
"picocolors": "^1.1.1",
|
|
45
|
+
"prompts": "^2.4.2"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"@types/prompts": "^2.4.9",
|
|
50
|
+
"tsup": "^8.3.0",
|
|
51
|
+
"typescript": "^5.7.0"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# My Nene App
|
|
2
|
+
|
|
3
|
+
This project was bootstrapped with [create-nene](https://nene.js.org).
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
First, run the development server:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run dev
|
|
11
|
+
# or
|
|
12
|
+
yarn dev
|
|
13
|
+
# or
|
|
14
|
+
pnpm dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Open [http://localhost:3000](http://localhost:3000) in your browser to see the result.
|
|
18
|
+
|
|
19
|
+
## Project Structure
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
my-nene-app/
|
|
23
|
+
├── src/
|
|
24
|
+
│ ├── app/ # Frontend pages and layouts
|
|
25
|
+
│ │ ├── page.tsx # Home page
|
|
26
|
+
│ │ └── layout.tsx # Root layout
|
|
27
|
+
│ └── server/ # Backend API and services
|
|
28
|
+
│ └── api/ # API routes
|
|
29
|
+
├── public/ # Static assets
|
|
30
|
+
├── package.json
|
|
31
|
+
└── tsconfig.json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Learn More
|
|
35
|
+
|
|
36
|
+
To learn more about nene.js, check out the following resources:
|
|
37
|
+
|
|
38
|
+
- [nene.js Documentation](https://nene.js.org/docs) - learn about nene.js features and API.
|
|
39
|
+
- [GitHub Repository](https://github.com/nene-js/nene) - your feedback and contributions are welcome!
|
|
40
|
+
|
|
41
|
+
## Deploy
|
|
42
|
+
|
|
43
|
+
Deploy your nene.js app with [Vercel](https://vercel.com) or any Node.js hosting platform.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
.pnp
|
|
4
|
+
.pnp.js
|
|
5
|
+
|
|
6
|
+
# Build
|
|
7
|
+
dist/
|
|
8
|
+
.nene/
|
|
9
|
+
.next/
|
|
10
|
+
out/
|
|
11
|
+
|
|
12
|
+
# Environment
|
|
13
|
+
.env
|
|
14
|
+
.env.local
|
|
15
|
+
.env.*.local
|
|
16
|
+
|
|
17
|
+
# IDE
|
|
18
|
+
.idea/
|
|
19
|
+
.vscode/
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
|
|
23
|
+
# OS
|
|
24
|
+
.DS_Store
|
|
25
|
+
Thumbs.db
|
|
26
|
+
|
|
27
|
+
# Logs
|
|
28
|
+
*.log
|
|
29
|
+
npm-debug.log*
|
|
30
|
+
yarn-debug.log*
|
|
31
|
+
yarn-error.log*
|
|
32
|
+
pnpm-debug.log*
|
|
33
|
+
|
|
34
|
+
# Testing
|
|
35
|
+
coverage/
|
|
36
|
+
|
|
37
|
+
# TypeScript
|
|
38
|
+
*.tsbuildinfo
|
|
39
|
+
|
|
40
|
+
# Misc
|
|
41
|
+
.vercel
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-nene-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "nene dev",
|
|
8
|
+
"build": "nene build",
|
|
9
|
+
"start": "nene start",
|
|
10
|
+
"lint": "eslint ."
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"nene": "^0.1.0",
|
|
14
|
+
"react": "^19.0.0",
|
|
15
|
+
"react-dom": "^19.0.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^22.0.0",
|
|
19
|
+
"@types/react": "^19.0.0",
|
|
20
|
+
"@types/react-dom": "^19.0.0",
|
|
21
|
+
"eslint": "^9.0.0",
|
|
22
|
+
"typescript": "^5.7.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export const metadata = {
|
|
4
|
+
title: "My Nene App",
|
|
5
|
+
description: "Built with nene.js - The AI-native full-stack framework",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
9
|
+
return (
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<body>{children}</body>
|
|
12
|
+
</html>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default function HomePage() {
|
|
2
|
+
return (
|
|
3
|
+
<main className="min-h-screen flex flex-col items-center justify-center p-8">
|
|
4
|
+
<div className="max-w-2xl text-center">
|
|
5
|
+
<h1 className="text-4xl font-bold mb-4">
|
|
6
|
+
Welcome to <span className="text-blue-500">nene.js</span>
|
|
7
|
+
</h1>
|
|
8
|
+
<p className="text-lg text-gray-600 mb-8">
|
|
9
|
+
The AI-native full-stack framework for building modern web applications.
|
|
10
|
+
</p>
|
|
11
|
+
<div className="flex gap-4 justify-center">
|
|
12
|
+
<a
|
|
13
|
+
href="https://nene.js.org/docs"
|
|
14
|
+
className="px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition"
|
|
15
|
+
>
|
|
16
|
+
Read the Docs
|
|
17
|
+
</a>
|
|
18
|
+
<a
|
|
19
|
+
href="https://github.com/nene-js/nene"
|
|
20
|
+
className="px-6 py-3 border border-gray-300 rounded-lg hover:border-gray-400 transition"
|
|
21
|
+
>
|
|
22
|
+
GitHub
|
|
23
|
+
</a>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</main>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Controller, Get } from "nene/decorators";
|
|
2
|
+
|
|
3
|
+
@Controller("/api")
|
|
4
|
+
export class HelloController {
|
|
5
|
+
@Get("/hello")
|
|
6
|
+
hello() {
|
|
7
|
+
return { message: "Hello from nene.js!" };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@Get("/health")
|
|
11
|
+
health() {
|
|
12
|
+
return { status: "ok", timestamp: new Date().toISOString() };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "ES2022"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "ESNext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"baseUrl": ".",
|
|
17
|
+
"paths": {
|
|
18
|
+
"@/*": ["./src/*"],
|
|
19
|
+
"@server/*": ["./src/server/*"]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"include": ["src/**/*", "*.ts"],
|
|
23
|
+
"exclude": ["node_modules"]
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-nene-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "nene dev",
|
|
8
|
+
"build": "nene build",
|
|
9
|
+
"start": "nene start"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"nene": "^0.1.0",
|
|
13
|
+
"react": "^19.0.0",
|
|
14
|
+
"react-dom": "^19.0.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^22.0.0",
|
|
18
|
+
"@types/react": "^19.0.0",
|
|
19
|
+
"@types/react-dom": "^19.0.0",
|
|
20
|
+
"typescript": "^5.7.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "ES2022"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "ESNext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"incremental": true
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*"],
|
|
18
|
+
"exclude": ["node_modules"]
|
|
19
|
+
}
|