create-nattyjs 0.0.1-beta.66 → 0.0.1-beta.68
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/index.js +319 -286
- package/package.json +9 -2
- package/template-fullstack-angular/__examples/apps/api/controllers/requests.controller.ts +13 -0
- package/template-fullstack-angular/__examples/apps/web/src/app/app.component.ts +46 -0
- package/template-fullstack-angular/__examples/apps/web/src/app/lib/api.ts +15 -0
- package/template-fullstack-angular/_gitignore +8 -0
- package/template-fullstack-angular/apps/api/app.ts +8 -0
- package/template-fullstack-angular/apps/api/natty.config.ts +9 -0
- package/template-fullstack-angular/apps/api/package.json +24 -0
- package/template-fullstack-angular/apps/api/tsconfig.json +20 -0
- package/template-fullstack-angular/apps/web/angular.json +67 -0
- package/template-fullstack-angular/apps/web/package.json +30 -0
- package/template-fullstack-angular/apps/web/proxy.conf.json +7 -0
- package/template-fullstack-angular/apps/web/src/app/app.component.ts +29 -0
- package/template-fullstack-angular/apps/web/src/assets/.gitkeep +1 -0
- package/template-fullstack-angular/apps/web/src/index.html +12 -0
- package/template-fullstack-angular/apps/web/src/main.ts +5 -0
- package/template-fullstack-angular/apps/web/src/styles.css +110 -0
- package/template-fullstack-angular/apps/web/tsconfig.app.json +13 -0
- package/template-fullstack-angular/apps/web/tsconfig.json +31 -0
- package/template-fullstack-angular/package.json +20 -0
- package/template-fullstack-astro/__examples/apps/api/controllers/requests.controller.ts +13 -0
- package/template-fullstack-astro/__examples/apps/web/src/lib/api.ts +15 -0
- package/template-fullstack-astro/__examples/apps/web/src/pages/index.astro +53 -0
- package/template-fullstack-astro/_gitignore +8 -0
- package/template-fullstack-astro/apps/api/app.ts +8 -0
- package/template-fullstack-astro/apps/api/natty.config.ts +9 -0
- package/template-fullstack-astro/apps/api/package.json +24 -0
- package/template-fullstack-astro/apps/api/tsconfig.json +20 -0
- package/template-fullstack-astro/apps/web/astro.config.mjs +14 -0
- package/template-fullstack-astro/apps/web/package.json +17 -0
- package/template-fullstack-astro/apps/web/src/env.d.ts +1 -0
- package/template-fullstack-astro/apps/web/src/pages/index.astro +31 -0
- package/template-fullstack-astro/apps/web/src/styles/global.css +110 -0
- package/template-fullstack-astro/apps/web/tsconfig.json +5 -0
- package/template-fullstack-astro/package.json +20 -0
- package/template-fullstack-next/__examples/apps/api/controllers/requests.controller.ts +13 -0
- package/template-fullstack-next/__examples/apps/web/app/page.tsx +68 -0
- package/template-fullstack-next/__examples/apps/web/lib/api.ts +15 -0
- package/template-fullstack-next/_gitignore +8 -0
- package/template-fullstack-next/apps/api/app.ts +8 -0
- package/template-fullstack-next/apps/api/natty.config.ts +9 -0
- package/template-fullstack-next/apps/api/package.json +24 -0
- package/template-fullstack-next/apps/api/tsconfig.json +20 -0
- package/template-fullstack-next/apps/web/app/globals.css +110 -0
- package/template-fullstack-next/apps/web/app/layout.tsx +19 -0
- package/template-fullstack-next/apps/web/app/page.tsx +22 -0
- package/template-fullstack-next/apps/web/next-env.d.ts +4 -0
- package/template-fullstack-next/apps/web/next.config.mjs +13 -0
- package/template-fullstack-next/apps/web/package.json +22 -0
- package/template-fullstack-next/apps/web/tsconfig.json +24 -0
- package/template-fullstack-next/package.json +20 -0
- package/template-fullstack-nuxt/__examples/apps/api/controllers/requests.controller.ts +13 -0
- package/template-fullstack-nuxt/__examples/apps/web/app.vue +41 -0
- package/template-fullstack-nuxt/__examples/apps/web/lib/api.ts +15 -0
- package/template-fullstack-nuxt/_gitignore +8 -0
- package/template-fullstack-nuxt/apps/api/app.ts +8 -0
- package/template-fullstack-nuxt/apps/api/natty.config.ts +9 -0
- package/template-fullstack-nuxt/apps/api/package.json +24 -0
- package/template-fullstack-nuxt/apps/api/tsconfig.json +20 -0
- package/template-fullstack-nuxt/apps/web/app.vue +20 -0
- package/template-fullstack-nuxt/apps/web/assets/css/main.css +111 -0
- package/template-fullstack-nuxt/apps/web/nuxt.config.ts +14 -0
- package/template-fullstack-nuxt/apps/web/package.json +14 -0
- package/template-fullstack-nuxt/apps/web/tsconfig.json +3 -0
- package/template-fullstack-nuxt/package.json +20 -0
- package/template-fullstack-react/__examples/apps/api/controllers/requests.controller.ts +13 -0
- package/template-fullstack-react/__examples/apps/web/src/App.tsx +66 -0
- package/template-fullstack-react/__examples/apps/web/src/lib/api.ts +15 -0
- package/template-fullstack-react/_gitignore +7 -0
- package/template-fullstack-react/apps/api/app.ts +8 -0
- package/template-fullstack-react/apps/api/natty.config.ts +9 -0
- package/template-fullstack-react/apps/api/package.json +24 -0
- package/template-fullstack-react/apps/api/tsconfig.json +20 -0
- package/template-fullstack-react/apps/web/index.html +12 -0
- package/template-fullstack-react/apps/web/package.json +22 -0
- package/template-fullstack-react/apps/web/src/App.tsx +22 -0
- package/template-fullstack-react/apps/web/src/main.tsx +10 -0
- package/template-fullstack-react/apps/web/src/style.css +111 -0
- package/template-fullstack-react/apps/web/src/vite-env.d.ts +1 -0
- package/template-fullstack-react/apps/web/tsconfig.json +17 -0
- package/template-fullstack-react/apps/web/vite.config.ts +15 -0
- package/template-fullstack-react/package.json +20 -0
- package/template-fullstack-sveltekit/__examples/apps/api/controllers/requests.controller.ts +13 -0
- package/template-fullstack-sveltekit/__examples/apps/web/src/lib/api.ts +15 -0
- package/template-fullstack-sveltekit/__examples/apps/web/src/routes/+page.svelte +45 -0
- package/template-fullstack-sveltekit/_gitignore +8 -0
- package/template-fullstack-sveltekit/apps/api/app.ts +8 -0
- package/template-fullstack-sveltekit/apps/api/natty.config.ts +9 -0
- package/template-fullstack-sveltekit/apps/api/package.json +24 -0
- package/template-fullstack-sveltekit/apps/api/tsconfig.json +20 -0
- package/template-fullstack-sveltekit/apps/web/package.json +24 -0
- package/template-fullstack-sveltekit/apps/web/src/app.css +110 -0
- package/template-fullstack-sveltekit/apps/web/src/app.d.ts +10 -0
- package/template-fullstack-sveltekit/apps/web/src/app.html +11 -0
- package/template-fullstack-sveltekit/apps/web/src/routes/+layout.svelte +5 -0
- package/template-fullstack-sveltekit/apps/web/src/routes/+page.svelte +18 -0
- package/template-fullstack-sveltekit/apps/web/svelte.config.js +12 -0
- package/template-fullstack-sveltekit/apps/web/tsconfig.json +14 -0
- package/template-fullstack-sveltekit/apps/web/vite.config.ts +14 -0
- package/template-fullstack-sveltekit/package.json +20 -0
- package/template-fullstack-vue/__examples/apps/api/controllers/requests.controller.ts +13 -0
- package/template-fullstack-vue/__examples/apps/web/src/App.vue +122 -0
- package/template-fullstack-vue/__examples/apps/web/src/lib/api.ts +15 -0
- package/template-fullstack-vue/_gitignore +7 -0
- package/template-fullstack-vue/apps/api/app.ts +8 -0
- package/template-fullstack-vue/apps/api/natty.config.ts +9 -0
- package/template-fullstack-vue/apps/api/package.json +24 -0
- package/template-fullstack-vue/apps/api/tsconfig.json +20 -0
- package/template-fullstack-vue/apps/web/index.html +12 -0
- package/template-fullstack-vue/apps/web/package.json +20 -0
- package/template-fullstack-vue/apps/web/src/App.vue +77 -0
- package/template-fullstack-vue/apps/web/src/main.ts +5 -0
- package/template-fullstack-vue/apps/web/src/style.css +31 -0
- package/template-fullstack-vue/apps/web/src/vite-env.d.ts +1 -0
- package/template-fullstack-vue/apps/web/tsconfig.json +17 -0
- package/template-fullstack-vue/apps/web/vite.config.ts +15 -0
- package/template-fullstack-vue/package.json +20 -0
- package/template-nattyjs-blank/package.json +8 -8
package/index.js
CHANGED
|
@@ -1,316 +1,349 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import fs from
|
|
3
|
-
import path from
|
|
4
|
-
import minimist from
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {fileURLToPath} from 'url';
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
yellow,
|
|
12
|
-
green,
|
|
13
|
-
blue,
|
|
14
|
-
red,
|
|
15
|
-
reset
|
|
16
|
-
} from 'kolorist';
|
|
17
|
-
import { bold } from 'kleur/colors';
|
|
18
|
-
|
|
19
|
-
import chalk from 'chalk';
|
|
20
|
-
import ora from 'ora';
|
|
21
|
-
|
|
22
|
-
const gradients = [
|
|
23
|
-
`#00FF97`,
|
|
24
|
-
`#29FF8F`,
|
|
25
|
-
`#58FF38`,
|
|
26
|
-
`#3BFF24`,
|
|
27
|
-
`#93FF05`,
|
|
28
|
-
`#4EFF00`,
|
|
29
|
-
`#6FF500`,
|
|
30
|
-
`#14E684`,
|
|
31
|
-
`#36D629`,
|
|
32
|
-
`#38C266`,
|
|
33
|
-
];
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import minimist from "minimist";
|
|
5
|
+
import prompts from "prompts";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import { red, reset } from "kolorist";
|
|
34
8
|
|
|
35
|
-
|
|
9
|
+
const argv = minimist(process.argv.slice(2), {
|
|
10
|
+
string: ["template"],
|
|
11
|
+
boolean: ["examples"],
|
|
12
|
+
alias: {
|
|
13
|
+
t: "template",
|
|
14
|
+
e: "examples",
|
|
15
|
+
},
|
|
16
|
+
});
|
|
36
17
|
|
|
37
|
-
const
|
|
38
|
-
...gradients,
|
|
39
|
-
...[...gradients].reverse(),
|
|
40
|
-
...gradients,
|
|
41
|
-
];
|
|
18
|
+
const cwd = process.cwd();
|
|
42
19
|
|
|
20
|
+
const renameFiles = {
|
|
21
|
+
_gitignore: ".gitignore",
|
|
22
|
+
};
|
|
43
23
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
24
|
+
const TEMPLATE_DEFINITIONS = [
|
|
25
|
+
{
|
|
26
|
+
id: "api-only",
|
|
27
|
+
aliases: ["nattyjs-blank"],
|
|
28
|
+
title: "API Only",
|
|
29
|
+
description: "Backend API (current blank template)",
|
|
30
|
+
templateDir: "template-nattyjs-blank",
|
|
31
|
+
exampleExcludedPaths: ["controllers"],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "fullstack-vue",
|
|
35
|
+
aliases: ["vue", "nattyjs-vue"],
|
|
36
|
+
title: "Fullstack + Vue",
|
|
37
|
+
description: "NattyJS API + Vue (Vite)",
|
|
38
|
+
templateDir: "template-fullstack-vue",
|
|
39
|
+
exampleOverlayDir: "__examples",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "fullstack-react",
|
|
43
|
+
aliases: ["react", "nattyjs-react"],
|
|
44
|
+
title: "Fullstack + React",
|
|
45
|
+
description: "NattyJS API + React (Vite)",
|
|
46
|
+
templateDir: "template-fullstack-react",
|
|
47
|
+
exampleOverlayDir: "__examples",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "fullstack-next",
|
|
51
|
+
aliases: ["next", "nextjs", "nattyjs-next"],
|
|
52
|
+
title: "Fullstack + Next.js",
|
|
53
|
+
description: "NattyJS API + Next.js",
|
|
54
|
+
templateDir: "template-fullstack-next",
|
|
55
|
+
exampleOverlayDir: "__examples",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "fullstack-nuxt",
|
|
59
|
+
aliases: ["nuxt", "nuxtjs", "nattyjs-nuxt"],
|
|
60
|
+
title: "Fullstack + Nuxt",
|
|
61
|
+
description: "NattyJS API + Nuxt",
|
|
62
|
+
templateDir: "template-fullstack-nuxt",
|
|
63
|
+
exampleOverlayDir: "__examples",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "fullstack-angular",
|
|
67
|
+
aliases: ["angular", "ng", "nattyjs-angular"],
|
|
68
|
+
title: "Fullstack + Angular",
|
|
69
|
+
description: "NattyJS API + Angular",
|
|
70
|
+
templateDir: "template-fullstack-angular",
|
|
71
|
+
exampleOverlayDir: "__examples",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: "fullstack-astro",
|
|
75
|
+
aliases: ["astro", "nattyjs-astro"],
|
|
76
|
+
title: "Fullstack + Astro",
|
|
77
|
+
description: "NattyJS API + Astro",
|
|
78
|
+
templateDir: "template-fullstack-astro",
|
|
79
|
+
exampleOverlayDir: "__examples",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: "fullstack-sveltekit",
|
|
83
|
+
aliases: ["sveltekit", "svelte-kit", "svelte", "nattyjs-sveltekit"],
|
|
84
|
+
title: "Fullstack + SvelteKit",
|
|
85
|
+
description: "NattyJS API + SvelteKit",
|
|
86
|
+
templateDir: "template-fullstack-sveltekit",
|
|
87
|
+
exampleOverlayDir: "__examples",
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
if (process.env.NATTYJS_PROMPT_INJECT) {
|
|
92
|
+
prompts.inject(JSON.parse(process.env.NATTYJS_PROMPT_INJECT));
|
|
61
93
|
}
|
|
62
94
|
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
);
|
|
70
|
-
const gradientColors = gradients.slice(0, i).map((item) => chalk.bgHex(item)(' '));
|
|
71
|
-
animationFrames.push([...spaces, ...gradientColors].join(''));
|
|
72
|
-
}
|
|
73
|
-
return animationFrames;
|
|
95
|
+
function readJson(filePath) {
|
|
96
|
+
if (!fs.existsSync(filePath)) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
74
101
|
}
|
|
75
102
|
|
|
103
|
+
function getTemplateById(value) {
|
|
104
|
+
if (!value) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
76
107
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
spinner: {
|
|
81
|
-
interval: 30,
|
|
82
|
-
frames:animationFrames,
|
|
83
|
-
},
|
|
84
|
-
text: `${arrow} ${text}`,
|
|
85
|
-
});
|
|
86
|
-
startSpinner.start();
|
|
87
|
-
await sleepProcess((animationFrames.length - 1) * startSpinner.interval);
|
|
88
|
-
startSpinner.stop();
|
|
89
|
-
const spinner = ora({
|
|
90
|
-
spinner: {
|
|
91
|
-
interval: 80,
|
|
92
|
-
frames: getInstallAnimationFrames(),
|
|
93
|
-
},
|
|
94
|
-
text: `${arrow} ${text}`,
|
|
95
|
-
}).start();
|
|
96
|
-
|
|
97
|
-
return spinner;
|
|
108
|
+
return TEMPLATE_DEFINITIONS.find((template) => {
|
|
109
|
+
return template.id === value || template.aliases.includes(value);
|
|
110
|
+
});
|
|
98
111
|
}
|
|
99
|
-
|
|
100
|
-
const cwd = process.cwd()
|
|
101
112
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
name: 'nattyjs-blank',
|
|
106
|
-
color: yellow
|
|
107
|
-
}
|
|
113
|
+
function isValidPackageName(projectName) {
|
|
114
|
+
return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(projectName);
|
|
115
|
+
}
|
|
108
116
|
|
|
109
|
-
|
|
117
|
+
function toValidPackageName(projectName) {
|
|
118
|
+
return projectName
|
|
119
|
+
.trim()
|
|
120
|
+
.toLowerCase()
|
|
121
|
+
.replace(/\s+/g, "-")
|
|
122
|
+
.replace(/^[._]/, "")
|
|
123
|
+
.replace(/[^a-z0-9-~]+/g, "-");
|
|
124
|
+
}
|
|
110
125
|
|
|
126
|
+
function isEmpty(dirPath) {
|
|
127
|
+
const files = fs.readdirSync(dirPath);
|
|
128
|
+
return files.length === 0 || (files.length === 1 && files[0] === ".git");
|
|
129
|
+
}
|
|
111
130
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
131
|
+
function emptyDir(dir) {
|
|
132
|
+
if (!fs.existsSync(dir)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
115
135
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
136
|
+
for (const file of fs.readdirSync(dir)) {
|
|
137
|
+
const absolutePath = path.resolve(dir, file);
|
|
138
|
+
if (fs.lstatSync(absolutePath).isDirectory()) {
|
|
139
|
+
emptyDir(absolutePath);
|
|
140
|
+
fs.rmdirSync(absolutePath);
|
|
141
|
+
} else {
|
|
142
|
+
fs.unlinkSync(absolutePath);
|
|
143
|
+
}
|
|
121
144
|
}
|
|
122
145
|
}
|
|
123
146
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
let result = {}
|
|
131
|
-
|
|
132
|
-
try {
|
|
133
|
-
result = await prompts(
|
|
134
|
-
[
|
|
135
|
-
{
|
|
136
|
-
type: targetDir ? null : 'text',
|
|
137
|
-
name: 'projectName',
|
|
138
|
-
message: reset('Project name:'),
|
|
139
|
-
initial: defaultProjectName,
|
|
140
|
-
onState: (state) =>
|
|
141
|
-
(targetDir = state.value.trim() || defaultProjectName)
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
type: () =>
|
|
145
|
-
!fs.existsSync(targetDir) || isEmpty(targetDir) ? null : 'confirm',
|
|
146
|
-
name: 'overwrite',
|
|
147
|
-
message: () =>
|
|
148
|
-
(targetDir === '.'
|
|
149
|
-
? 'Current directory'
|
|
150
|
-
: `Target directory "${targetDir}"`) +
|
|
151
|
-
` is not empty. Remove existing files and continue?`
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
type: (_, { overwrite } = {}) => {
|
|
155
|
-
if (overwrite === false) {
|
|
156
|
-
throw new Error(red('✖') + ' Operation cancelled')
|
|
157
|
-
}
|
|
158
|
-
return null
|
|
159
|
-
},
|
|
160
|
-
name: 'overwriteChecker'
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
type: () => (isValidPackageName(targetDir) ? null : 'text'),
|
|
164
|
-
name: 'packageName',
|
|
165
|
-
message: reset('Package name:'),
|
|
166
|
-
initial: () => toValidPackageName(targetDir),
|
|
167
|
-
validate: (dir) =>
|
|
168
|
-
isValidPackageName(dir) || 'Invalid package.json name'
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
type: 'select',
|
|
172
|
-
name: 'variant',
|
|
173
|
-
message: reset('Select a scaffolding template:'),
|
|
174
|
-
// @ts-ignore
|
|
175
|
-
choices: () =>
|
|
176
|
-
SCAFFOLDING_TEMPLATES.map((template) => {
|
|
177
|
-
const templateColor = template.color
|
|
178
|
-
return {
|
|
179
|
-
title: templateColor(template.title),
|
|
180
|
-
value: template.name
|
|
181
|
-
}
|
|
182
|
-
})
|
|
183
|
-
}
|
|
184
|
-
],
|
|
185
|
-
{
|
|
186
|
-
onCancel: () => {
|
|
187
|
-
throw new Error(red('✖') + ' Operation cancelled')
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
)
|
|
191
|
-
} catch (cancelled) {
|
|
192
|
-
console.log(cancelled.message)
|
|
193
|
-
return
|
|
147
|
+
function copy(src, dest) {
|
|
148
|
+
const stat = fs.statSync(src);
|
|
149
|
+
if (stat.isDirectory()) {
|
|
150
|
+
copyDir(src, dest);
|
|
151
|
+
return;
|
|
194
152
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
153
|
+
|
|
154
|
+
fs.copyFileSync(src, dest);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function copyDir(srcDir, destDir) {
|
|
158
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
159
|
+
for (const file of fs.readdirSync(srcDir)) {
|
|
160
|
+
const srcFile = path.resolve(srcDir, file);
|
|
161
|
+
const destFile = path.resolve(destDir, file);
|
|
162
|
+
copy(srcFile, destFile);
|
|
204
163
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const templateDir = path.join(__dirname, `template-${template}`)
|
|
211
|
-
const write = (file, content) => {
|
|
212
|
-
const targetPath = renameFiles[file]
|
|
213
|
-
? path.join(root, renameFiles[file])
|
|
214
|
-
: path.join(root, file)
|
|
215
|
-
if (content) {
|
|
216
|
-
fs.writeFileSync(targetPath, content)
|
|
217
|
-
} else {
|
|
218
|
-
copy(path.join(templateDir, file), targetPath)
|
|
219
|
-
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function pkgFromUserAgent(userAgent) {
|
|
167
|
+
if (!userAgent) {
|
|
168
|
+
return undefined;
|
|
220
169
|
}
|
|
221
|
-
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
170
|
+
|
|
171
|
+
const pkgSpec = userAgent.split(" ")[0];
|
|
172
|
+
const [name, version] = pkgSpec.split("/");
|
|
173
|
+
return { name, version };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function shouldSkipTemplateFile(relativePath, template, includeExamples) {
|
|
177
|
+
if (includeExamples) {
|
|
178
|
+
return false;
|
|
225
179
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
180
|
+
|
|
181
|
+
const excludedPaths = template.exampleExcludedPaths || [];
|
|
182
|
+
return excludedPaths.some((excludedPath) => {
|
|
183
|
+
return relativePath === excludedPath || relativePath.startsWith(`${excludedPath}${path.sep}`);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function copyTemplateContents(templateDir, root, template, includeExamples) {
|
|
188
|
+
const entries = fs.readdirSync(templateDir);
|
|
189
|
+
for (const entry of entries) {
|
|
190
|
+
if (entry === "package.json") {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (entry === template.exampleOverlayDir) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (shouldSkipTemplateFile(entry, template, includeExamples)) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const sourcePath = path.join(templateDir, entry);
|
|
203
|
+
const targetPath = renameFiles[entry]
|
|
204
|
+
? path.join(root, renameFiles[entry])
|
|
205
|
+
: path.join(root, entry);
|
|
206
|
+
|
|
207
|
+
copy(sourcePath, targetPath);
|
|
237
208
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
console.log(` ${pkgManager} install`)
|
|
245
|
-
console.log(` ${pkgManager} run dev`)
|
|
246
|
-
break
|
|
209
|
+
|
|
210
|
+
if (includeExamples && template.exampleOverlayDir) {
|
|
211
|
+
const overlayDir = path.join(templateDir, template.exampleOverlayDir);
|
|
212
|
+
if (fs.existsSync(overlayDir)) {
|
|
213
|
+
copyDir(overlayDir, root);
|
|
214
|
+
}
|
|
247
215
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async function resolveProjectOptions() {
|
|
219
|
+
let targetDir = typeof argv._[0] === "string" ? argv._[0].trim() : "";
|
|
220
|
+
let selectedTemplate = getTemplateById(argv.template);
|
|
221
|
+
const defaultProjectName = targetDir || "nattyjs-project";
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
return await prompts(
|
|
225
|
+
[
|
|
226
|
+
{
|
|
227
|
+
type: targetDir ? null : "text",
|
|
228
|
+
name: "projectName",
|
|
229
|
+
message: reset("Project name:"),
|
|
230
|
+
initial: defaultProjectName,
|
|
231
|
+
validate: (value) => {
|
|
232
|
+
const trimmed = value.trim();
|
|
233
|
+
return trimmed.length > 0 || "Project name is required";
|
|
234
|
+
},
|
|
235
|
+
onState: (state) => {
|
|
236
|
+
targetDir = state.value.trim() || defaultProjectName;
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
type: () => {
|
|
241
|
+
return !targetDir || !fs.existsSync(targetDir) || isEmpty(targetDir) ? null : "confirm";
|
|
242
|
+
},
|
|
243
|
+
name: "overwrite",
|
|
244
|
+
message: () => {
|
|
245
|
+
const label = targetDir === "." ? "Current directory" : `Target directory "${targetDir}"`;
|
|
246
|
+
return `${label} is not empty. Remove existing files and continue?`;
|
|
247
|
+
},
|
|
248
|
+
initial: false,
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
type: (_, { overwrite } = {}) => {
|
|
252
|
+
if (overwrite === false) {
|
|
253
|
+
throw new Error(`${red("x")} Operation cancelled`);
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
},
|
|
257
|
+
name: "overwriteChecker",
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
type: () => (isValidPackageName(path.basename(targetDir || defaultProjectName)) ? null : "text"),
|
|
261
|
+
name: "packageName",
|
|
262
|
+
message: reset("Package name:"),
|
|
263
|
+
initial: () => toValidPackageName(path.basename(targetDir || defaultProjectName)),
|
|
264
|
+
validate: (value) => isValidPackageName(value) || "Invalid package.json name",
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
type: selectedTemplate ? null : "select",
|
|
268
|
+
name: "templateId",
|
|
269
|
+
message: reset("Select a template:"),
|
|
270
|
+
choices: TEMPLATE_DEFINITIONS.map((template) => ({
|
|
271
|
+
title: template.title,
|
|
272
|
+
description: template.description,
|
|
273
|
+
value: template.id,
|
|
274
|
+
})),
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
type: typeof argv.examples === "boolean" ? null : "toggle",
|
|
278
|
+
name: "includeExamples",
|
|
279
|
+
message: reset("Include examples?"),
|
|
280
|
+
initial: true,
|
|
281
|
+
active: "Yes",
|
|
282
|
+
inactive: "No",
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
{
|
|
286
|
+
onCancel: () => {
|
|
287
|
+
throw new Error(`${red("x")} Operation cancelled`);
|
|
288
|
+
},
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.log(error.message);
|
|
293
|
+
return undefined;
|
|
257
294
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function toValidPackageName(projectName) {
|
|
267
|
-
return projectName
|
|
268
|
-
.trim()
|
|
269
|
-
.toLowerCase()
|
|
270
|
-
.replace(/\s+/g, '-')
|
|
271
|
-
.replace(/^[._]/, '')
|
|
272
|
-
.replace(/[^a-z0-9-~]+/g, '-')
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function copyDir(srcDir, destDir) {
|
|
276
|
-
fs.mkdirSync(destDir, { recursive: true })
|
|
277
|
-
for (const file of fs.readdirSync(srcDir)) {
|
|
278
|
-
const srcFile = path.resolve(srcDir, file)
|
|
279
|
-
const destFile = path.resolve(destDir, file)
|
|
280
|
-
copy(srcFile, destFile)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async function initNatty() {
|
|
298
|
+
const promptResult = await resolveProjectOptions();
|
|
299
|
+
if (!promptResult) {
|
|
300
|
+
return;
|
|
281
301
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (!fs.existsSync(
|
|
291
|
-
|
|
302
|
+
|
|
303
|
+
const targetDir = (promptResult.projectName || argv._[0] || "").trim() || "nattyjs-project";
|
|
304
|
+
const template = getTemplateById(promptResult.templateId || argv.template) || TEMPLATE_DEFINITIONS[0];
|
|
305
|
+
const includeExamples = typeof argv.examples === "boolean" ? argv.examples : promptResult.includeExamples !== false;
|
|
306
|
+
const root = path.join(cwd, targetDir);
|
|
307
|
+
|
|
308
|
+
if (promptResult.overwrite) {
|
|
309
|
+
emptyDir(root);
|
|
310
|
+
} else if (!fs.existsSync(root)) {
|
|
311
|
+
fs.mkdirSync(root, { recursive: true });
|
|
292
312
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
313
|
+
|
|
314
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
315
|
+
const __dirname = path.dirname(__filename);
|
|
316
|
+
const templateDir = path.join(__dirname, template.templateDir);
|
|
317
|
+
|
|
318
|
+
console.log(`\nScaffolding project in ${root}...`);
|
|
319
|
+
|
|
320
|
+
copyTemplateContents(templateDir, root, template, includeExamples);
|
|
321
|
+
|
|
322
|
+
const packageJsonPath = path.join(templateDir, "package.json");
|
|
323
|
+
const pkg = readJson(packageJsonPath);
|
|
324
|
+
const packageName = promptResult.packageName || toValidPackageName(path.basename(targetDir));
|
|
325
|
+
pkg.name = packageName;
|
|
326
|
+
fs.writeFileSync(path.join(root, "package.json"), JSON.stringify(pkg, null, 2));
|
|
327
|
+
|
|
328
|
+
const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);
|
|
329
|
+
const pkgManager = pkgInfo ? pkgInfo.name : "npm";
|
|
330
|
+
|
|
331
|
+
console.log("\nDone. Now run:\n");
|
|
332
|
+
if (root !== cwd) {
|
|
333
|
+
console.log(` cd ${path.relative(cwd, root)}`);
|
|
301
334
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
name: pkgSpecArr[0],
|
|
310
|
-
version: pkgSpecArr[1]
|
|
335
|
+
|
|
336
|
+
if (pkgManager === "yarn") {
|
|
337
|
+
console.log(" yarn");
|
|
338
|
+
console.log(" yarn dev");
|
|
339
|
+
} else {
|
|
340
|
+
console.log(` ${pkgManager} install`);
|
|
341
|
+
console.log(` ${pkgManager} run dev`);
|
|
311
342
|
}
|
|
312
|
-
}
|
|
313
343
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
344
|
+
console.log();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
initNatty().catch((error) => {
|
|
348
|
+
console.error(error);
|
|
349
|
+
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-nattyjs",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.68",
|
|
4
4
|
"description": "Create NattyJS API Project",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"files": [
|
|
9
|
-
"template-nattyjs-blank"
|
|
9
|
+
"template-nattyjs-blank",
|
|
10
|
+
"template-fullstack-vue",
|
|
11
|
+
"template-fullstack-react",
|
|
12
|
+
"template-fullstack-next",
|
|
13
|
+
"template-fullstack-nuxt",
|
|
14
|
+
"template-fullstack-angular",
|
|
15
|
+
"template-fullstack-astro",
|
|
16
|
+
"template-fullstack-sveltekit"
|
|
10
17
|
],
|
|
11
18
|
"scripts": {
|
|
12
19
|
"test": "echo \"No tests defined\""
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { anonymous } from "@nattyjs/core"
|
|
2
|
+
|
|
3
|
+
export class RequestsController {
|
|
4
|
+
@anonymous()
|
|
5
|
+
async get(): Promise<Array<{ name: string }>> {
|
|
6
|
+
return [{ name: "NattyJS" }, { name: "Angular" }]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@anonymous()
|
|
10
|
+
async getBy(id: number): Promise<{ name: string; id: number }> {
|
|
11
|
+
return { name: "NattyJS", id }
|
|
12
|
+
}
|
|
13
|
+
}
|