create-vatts-app 1.0.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 +13 -0
- package/dist/createApp/cli.d.ts +5 -0
- package/dist/createApp/cli.js +87 -0
- package/dist/createApp/createApp.d.ts +3 -0
- package/dist/createApp/createApp.js +78 -0
- package/dist/createApp/fs.d.ts +4 -0
- package/dist/createApp/fs.js +54 -0
- package/dist/createApp/index.d.ts +1 -0
- package/dist/createApp/index.js +17 -0
- package/dist/createApp/install.d.ts +1 -0
- package/dist/createApp/install.js +76 -0
- package/dist/createApp/packageJson.d.ts +2 -0
- package/dist/createApp/packageJson.js +51 -0
- package/dist/createApp/steps.d.ts +9 -0
- package/dist/createApp/steps.js +160 -0
- package/dist/createApp/templates.d.ts +10 -0
- package/dist/createApp/templates.js +255 -0
- package/dist/createApp/types.d.ts +24 -0
- package/dist/createApp/types.js +2 -0
- package/dist/createApp/validate.d.ts +2 -0
- package/dist/createApp/validate.js +105 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +18 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2026 itsmuzin
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CreateAppOptions } from "./types";
|
|
2
|
+
export declare function parseArgs(argv: string[]): CreateAppOptions;
|
|
3
|
+
export declare function promptForMissingOptions(opts: CreateAppOptions): Promise<Required<Omit<CreateAppOptions, "appName">> & {
|
|
4
|
+
appName: string;
|
|
5
|
+
}>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseArgs = parseArgs;
|
|
7
|
+
exports.promptForMissingOptions = promptForMissingOptions;
|
|
8
|
+
const console_1 = __importDefault(require("vatts/console"));
|
|
9
|
+
function normalizeAliasPrefix(raw) {
|
|
10
|
+
const trimmed = raw.trim();
|
|
11
|
+
if (!trimmed)
|
|
12
|
+
return "@/";
|
|
13
|
+
// Allow users to type "@" or "@/" or "@/*". We normalize to prefix form ("@/").
|
|
14
|
+
if (trimmed.endsWith("/*"))
|
|
15
|
+
return trimmed.slice(0, -1); // "@/*" -> "@/"
|
|
16
|
+
if (trimmed.endsWith("/"))
|
|
17
|
+
return trimmed;
|
|
18
|
+
return `${trimmed}/`;
|
|
19
|
+
}
|
|
20
|
+
function readArgValue(args, flag) {
|
|
21
|
+
const idx = args.indexOf(flag);
|
|
22
|
+
if (idx === -1)
|
|
23
|
+
return undefined;
|
|
24
|
+
const next = args[idx + 1];
|
|
25
|
+
if (!next || next.startsWith("-"))
|
|
26
|
+
return undefined;
|
|
27
|
+
return next;
|
|
28
|
+
}
|
|
29
|
+
function parseArgs(argv) {
|
|
30
|
+
const args = argv.slice(2);
|
|
31
|
+
const appName = args.find((a) => a.length > 0 && !a.startsWith("-"));
|
|
32
|
+
// flags
|
|
33
|
+
const tailwindFlag = args.includes("--tailwind") || args.includes("-t");
|
|
34
|
+
const noInstallFlag = args.includes("--no-install");
|
|
35
|
+
const installFlag = args.includes("--install");
|
|
36
|
+
const noExamplesFlag = args.includes("--no-examples");
|
|
37
|
+
const examplesFlag = args.includes("--examples");
|
|
38
|
+
const noAliasFlag = args.includes("--no-alias");
|
|
39
|
+
const aliasValue = readArgValue(args, "--alias");
|
|
40
|
+
return {
|
|
41
|
+
appName,
|
|
42
|
+
tailwind: tailwindFlag ? true : undefined,
|
|
43
|
+
// default examples = true (prompt still decides)
|
|
44
|
+
examples: noExamplesFlag ? false : examplesFlag ? true : undefined,
|
|
45
|
+
install: noInstallFlag ? false : installFlag ? true : undefined,
|
|
46
|
+
moduleAlias: noAliasFlag ? false : aliasValue ? true : undefined,
|
|
47
|
+
alias: aliasValue ? normalizeAliasPrefix(aliasValue) : undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function promptForMissingOptions(opts) {
|
|
51
|
+
const appName = opts.appName ?? (await console_1.default.ask("What is the name of your app?", "my-vatts-app"));
|
|
52
|
+
let tailwind = opts.tailwind;
|
|
53
|
+
if (tailwind === undefined) {
|
|
54
|
+
tailwind = await console_1.default.confirm("Do you want to include Tailwind CSS?", true);
|
|
55
|
+
}
|
|
56
|
+
let examples = opts.examples;
|
|
57
|
+
if (examples === undefined) {
|
|
58
|
+
examples = await console_1.default.confirm("Do you want to include example routes?", true);
|
|
59
|
+
}
|
|
60
|
+
let install = opts.install;
|
|
61
|
+
if (install === undefined) {
|
|
62
|
+
install = await console_1.default.confirm("Do you want to install dependencies?", true);
|
|
63
|
+
}
|
|
64
|
+
let moduleAlias = opts.moduleAlias;
|
|
65
|
+
if (moduleAlias === undefined) {
|
|
66
|
+
moduleAlias = await console_1.default.confirm("Do you want to set a module alias?", true);
|
|
67
|
+
}
|
|
68
|
+
let alias = opts.alias;
|
|
69
|
+
if (moduleAlias) {
|
|
70
|
+
if (alias === undefined) {
|
|
71
|
+
alias = await console_1.default.ask("Which alias do you want to set?", "@/");
|
|
72
|
+
}
|
|
73
|
+
alias = normalizeAliasPrefix(alias);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// keep a stable value even when disabled
|
|
77
|
+
alias = "@/";
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
appName,
|
|
81
|
+
tailwind,
|
|
82
|
+
examples,
|
|
83
|
+
install,
|
|
84
|
+
moduleAlias,
|
|
85
|
+
alias,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createAppFromArgv = createAppFromArgv;
|
|
37
|
+
exports.createApp = createApp;
|
|
38
|
+
const cli_1 = require("./cli");
|
|
39
|
+
const steps_1 = require("./steps");
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const validate_1 = require("./validate");
|
|
42
|
+
function resolveOwnPackageJson() {
|
|
43
|
+
const pkgPath = path.resolve(__dirname, "..", "..", "package.json");
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
45
|
+
return require(pkgPath);
|
|
46
|
+
}
|
|
47
|
+
async function createAppFromArgv(argv) {
|
|
48
|
+
const opts = (0, cli_1.parseArgs)(argv);
|
|
49
|
+
return createApp(opts);
|
|
50
|
+
}
|
|
51
|
+
async function createApp(options) {
|
|
52
|
+
const resolved = await (0, cli_1.promptForMissingOptions)(options);
|
|
53
|
+
const safeName = (0, validate_1.validateAppName)(resolved.appName);
|
|
54
|
+
const rootDir = safeName;
|
|
55
|
+
// Fail fast to avoid overwriting anything.
|
|
56
|
+
(0, validate_1.assertTargetDirIsSafeEmpty)(rootDir);
|
|
57
|
+
const ownPkg = resolveOwnPackageJson();
|
|
58
|
+
const ctx = {
|
|
59
|
+
appName: safeName,
|
|
60
|
+
rootDir,
|
|
61
|
+
willTailwind: resolved.tailwind,
|
|
62
|
+
willRouteExample: resolved.examples,
|
|
63
|
+
willInstallDependencies: resolved.install,
|
|
64
|
+
willUseModuleAlias: resolved.moduleAlias,
|
|
65
|
+
moduleAlias: resolved.alias,
|
|
66
|
+
vattsVersion: ownPkg.version,
|
|
67
|
+
packageJson: {},
|
|
68
|
+
};
|
|
69
|
+
console.clear();
|
|
70
|
+
await (0, steps_1.stepCreateProjectDirAndPackageJson)(ctx);
|
|
71
|
+
await (0, steps_1.stepCreateProjectStructure)(ctx);
|
|
72
|
+
await (0, steps_1.stepWriteVattsConfig)(ctx);
|
|
73
|
+
await (0, steps_1.stepWriteTsConfig)(ctx);
|
|
74
|
+
await (0, steps_1.stepSetupTailwind)(ctx);
|
|
75
|
+
await (0, steps_1.stepCreateExampleRoutes)(ctx);
|
|
76
|
+
await (0, steps_1.stepInstallDependencies)(ctx);
|
|
77
|
+
(0, steps_1.printSummary)(ctx);
|
|
78
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function ensureDir(dirPath: string): void;
|
|
2
|
+
export declare function writeFile(targetPath: string, content: string): void;
|
|
3
|
+
export declare function writeJson(targetPath: string, data: unknown): void;
|
|
4
|
+
export declare function exists(targetPath: string): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ensureDir = ensureDir;
|
|
37
|
+
exports.writeFile = writeFile;
|
|
38
|
+
exports.writeJson = writeJson;
|
|
39
|
+
exports.exists = exists;
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
function ensureDir(dirPath) {
|
|
43
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
function writeFile(targetPath, content) {
|
|
46
|
+
ensureDir(path.dirname(targetPath));
|
|
47
|
+
fs.writeFileSync(targetPath, content);
|
|
48
|
+
}
|
|
49
|
+
function writeJson(targetPath, data) {
|
|
50
|
+
writeFile(targetPath, JSON.stringify(data, null, 2));
|
|
51
|
+
}
|
|
52
|
+
function exists(targetPath) {
|
|
53
|
+
return fs.existsSync(targetPath);
|
|
54
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./createApp";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./createApp"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function npmInstall(cwd: string): Promise<void>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.npmInstall = npmInstall;
|
|
37
|
+
const node_child_process_1 = require("node:child_process");
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
|
+
function trySpawn(command, args, cwd) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const child = (0, node_child_process_1.spawn)(command, args, { cwd, stdio: "inherit" });
|
|
43
|
+
child.on("error", reject);
|
|
44
|
+
child.on("exit", (code) => {
|
|
45
|
+
if (code === 0)
|
|
46
|
+
resolve();
|
|
47
|
+
else
|
|
48
|
+
reject(new Error(`${command} ${args.join(" ")} failed with exit code ${code}`));
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async function npmInstall(cwd) {
|
|
53
|
+
// Strategy (Windows-safe):
|
|
54
|
+
// 1) Try npm.cmd from PATH
|
|
55
|
+
// 2) Fallback: run npm-cli.js with Node (process.execPath) at the same Node installation
|
|
56
|
+
// 3) Try npm from PATH (non-windows / alternative)
|
|
57
|
+
const args = ["install"];
|
|
58
|
+
// 1) npm.cmd
|
|
59
|
+
if (process.platform === "win32") {
|
|
60
|
+
try {
|
|
61
|
+
return await trySpawn("npm.cmd", args, cwd);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// ignore and fallback
|
|
65
|
+
}
|
|
66
|
+
// 2) npm-cli.js via node
|
|
67
|
+
// Typical location: <nodeDir>/node_modules/npm/bin/npm-cli.js
|
|
68
|
+
const nodeDir = path.dirname(process.execPath);
|
|
69
|
+
const npmCli = path.join(nodeDir, "node_modules", "npm", "bin", "npm-cli.js");
|
|
70
|
+
if (fs.existsSync(npmCli)) {
|
|
71
|
+
return await trySpawn(process.execPath, [npmCli, ...args], cwd);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// 3) npm
|
|
75
|
+
return await trySpawn("npm", args, cwd);
|
|
76
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildPackageJson = buildPackageJson;
|
|
7
|
+
const console_1 = __importDefault(require("vatts/console"));
|
|
8
|
+
async function buildPackageJson(ctx) {
|
|
9
|
+
async function verifyVersion() {
|
|
10
|
+
// node fetch
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetch('https://registry.npmjs.org/vatts/latest');
|
|
13
|
+
const data = await response.json();
|
|
14
|
+
return data.version;
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
console_1.default.error('Could not check for the latest Vatts.js version:', error);
|
|
18
|
+
return ctx.vattsVersion; // Retorna a versão atual em caso de erro
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const version = await verifyVersion();
|
|
22
|
+
const packageJson = {
|
|
23
|
+
name: ctx.appName,
|
|
24
|
+
version: "0.1.0",
|
|
25
|
+
description: "Basic application for Vatts.js framework",
|
|
26
|
+
scripts: {
|
|
27
|
+
start: "vatts start",
|
|
28
|
+
dev: "vatts dev",
|
|
29
|
+
},
|
|
30
|
+
dependencies: {
|
|
31
|
+
vatts: `${version}`,
|
|
32
|
+
react: "^19.2.3",
|
|
33
|
+
"react-dom": "^19.2.3",
|
|
34
|
+
"ts-node": "^10.9.2",
|
|
35
|
+
},
|
|
36
|
+
devDependencies: {
|
|
37
|
+
"@types/react": "^19.2.8",
|
|
38
|
+
typescript: "^5.9.3",
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
if (ctx.willTailwind) {
|
|
42
|
+
packageJson.dependencies = {
|
|
43
|
+
...packageJson.dependencies,
|
|
44
|
+
tailwindcss: "^4.1.18",
|
|
45
|
+
"@tailwindcss/postcss": "^4.1.18",
|
|
46
|
+
postcss: "^8.5.6",
|
|
47
|
+
autoprefixer: "^10.4.23",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return packageJson;
|
|
51
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CreateAppContext } from "./types";
|
|
2
|
+
export declare function stepCreateProjectDirAndPackageJson(ctx: CreateAppContext): Promise<void>;
|
|
3
|
+
export declare function stepCreateProjectStructure(ctx: CreateAppContext): Promise<void>;
|
|
4
|
+
export declare function stepWriteVattsConfig(ctx: CreateAppContext): Promise<void>;
|
|
5
|
+
export declare function stepWriteTsConfig(ctx: CreateAppContext): Promise<void>;
|
|
6
|
+
export declare function stepSetupTailwind(ctx: CreateAppContext): Promise<void>;
|
|
7
|
+
export declare function stepCreateExampleRoutes(ctx: CreateAppContext): Promise<void>;
|
|
8
|
+
export declare function stepInstallDependencies(ctx: CreateAppContext): Promise<void>;
|
|
9
|
+
export declare function printSummary(ctx: CreateAppContext): void;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.stepCreateProjectDirAndPackageJson = stepCreateProjectDirAndPackageJson;
|
|
37
|
+
exports.stepCreateProjectStructure = stepCreateProjectStructure;
|
|
38
|
+
exports.stepWriteVattsConfig = stepWriteVattsConfig;
|
|
39
|
+
exports.stepWriteTsConfig = stepWriteTsConfig;
|
|
40
|
+
exports.stepSetupTailwind = stepSetupTailwind;
|
|
41
|
+
exports.stepCreateExampleRoutes = stepCreateExampleRoutes;
|
|
42
|
+
exports.stepInstallDependencies = stepInstallDependencies;
|
|
43
|
+
exports.printSummary = printSummary;
|
|
44
|
+
const console_1 = __importStar(require("vatts/console"));
|
|
45
|
+
const path = __importStar(require("node:path"));
|
|
46
|
+
const fs_1 = require("./fs");
|
|
47
|
+
const templates_1 = require("./templates");
|
|
48
|
+
const packageJson_1 = require("./packageJson");
|
|
49
|
+
const install_1 = require("./install");
|
|
50
|
+
async function stepCreateProjectDirAndPackageJson(ctx) {
|
|
51
|
+
const dynamic = console_1.default.dynamicLine("Creating your Vatts.js app...");
|
|
52
|
+
(0, fs_1.ensureDir)(ctx.rootDir);
|
|
53
|
+
ctx.packageJson = await (0, packageJson_1.buildPackageJson)({
|
|
54
|
+
appName: ctx.appName,
|
|
55
|
+
vattsVersion: ctx.vattsVersion,
|
|
56
|
+
willTailwind: ctx.willTailwind,
|
|
57
|
+
});
|
|
58
|
+
(0, fs_1.writeJson)(path.join(ctx.rootDir, "package.json"), ctx.packageJson);
|
|
59
|
+
dynamic.end("Created project directory and package.json");
|
|
60
|
+
}
|
|
61
|
+
async function stepCreateProjectStructure(ctx) {
|
|
62
|
+
const dynamic = console_1.default.dynamicLine("Creating project structure...");
|
|
63
|
+
(0, fs_1.ensureDir)(path.join(ctx.rootDir, "src", "backend", "routes"));
|
|
64
|
+
(0, fs_1.ensureDir)(path.join(ctx.rootDir, "src", "web", "routes"));
|
|
65
|
+
(0, fs_1.writeFile)(path.join(ctx.rootDir, "src", "web", "globals.css"), (0, templates_1.globalsCssTemplate)(ctx.willTailwind));
|
|
66
|
+
(0, fs_1.writeFile)(path.join(ctx.rootDir, "src", "web", "layout.tsx"), (0, templates_1.layoutTsxTemplate)());
|
|
67
|
+
dynamic.end("Created project structure");
|
|
68
|
+
}
|
|
69
|
+
async function stepWriteVattsConfig(ctx) {
|
|
70
|
+
(0, fs_1.writeFile)(path.join(ctx.rootDir, "vatts.config.ts"), (0, templates_1.vattsConfigTemplate)());
|
|
71
|
+
}
|
|
72
|
+
async function stepWriteTsConfig(ctx) {
|
|
73
|
+
const dynamic = console_1.default.dynamicLine("Initializing TypeScript configuration...");
|
|
74
|
+
(0, fs_1.writeFile)(path.join(ctx.rootDir, "tsconfig.json"), (0, templates_1.tsconfigTemplate)(ctx.willUseModuleAlias ? { moduleAlias: ctx.moduleAlias } : { moduleAlias: false }));
|
|
75
|
+
dynamic.end("TypeScript configuration initialized.");
|
|
76
|
+
}
|
|
77
|
+
async function stepSetupTailwind(ctx) {
|
|
78
|
+
if (!ctx.willTailwind)
|
|
79
|
+
return;
|
|
80
|
+
const dynamic = console_1.default.dynamicLine("Setting up Tailwind CSS...");
|
|
81
|
+
(0, fs_1.writeFile)(path.join(ctx.rootDir, "postcss.config.js"), (0, templates_1.postcssConfigTemplate)());
|
|
82
|
+
(0, fs_1.writeFile)(path.join(ctx.rootDir, "tailwind.config.js"), (0, templates_1.tailwindConfigTemplate)());
|
|
83
|
+
dynamic.end("Tailwind CSS setup complete.");
|
|
84
|
+
}
|
|
85
|
+
async function stepCreateExampleRoutes(ctx) {
|
|
86
|
+
if (!ctx.willRouteExample)
|
|
87
|
+
return;
|
|
88
|
+
const dynamic = console_1.default.dynamicLine("Creating example routes...");
|
|
89
|
+
(0, fs_1.writeFile)(path.join(ctx.rootDir, "src", "web", "routes", "index.tsx"), (0, templates_1.webIndexRouteTemplate)(ctx.willTailwind));
|
|
90
|
+
(0, fs_1.writeFile)(path.join(ctx.rootDir, "src", "backend", "routes", "Example.ts"), (0, templates_1.backendExampleRouteTemplate)());
|
|
91
|
+
dynamic.end("Example routes created.");
|
|
92
|
+
}
|
|
93
|
+
async function stepInstallDependencies(ctx) {
|
|
94
|
+
if (!ctx.willInstallDependencies)
|
|
95
|
+
return;
|
|
96
|
+
const dynamic = console_1.default.dynamicLine("Installing dependencies...");
|
|
97
|
+
console.log(`\nInstalling dependencies:\n${ctx.packageJson.dependencies
|
|
98
|
+
? Object.keys(ctx.packageJson.dependencies)
|
|
99
|
+
.map((dep) => ` - ${console_1.Colors.FgCyan}${dep}${console_1.Colors.Reset}`)
|
|
100
|
+
.join("\n")
|
|
101
|
+
: ""}\n\nInstalling devDependencies:\n${ctx.packageJson.devDependencies
|
|
102
|
+
? Object.keys(ctx.packageJson.devDependencies)
|
|
103
|
+
.map((dep) => ` - ${console_1.Colors.FgCyan}${dep}${console_1.Colors.Reset}`)
|
|
104
|
+
.join("\n")
|
|
105
|
+
: ""}\n`);
|
|
106
|
+
const spinnerFrames = ["|", "/", "-", "\\"];
|
|
107
|
+
let frameIndex = 0;
|
|
108
|
+
const spinner = setInterval(() => {
|
|
109
|
+
dynamic.update(`${console_1.Colors.FgGreen}${spinnerFrames[frameIndex]}${console_1.Colors.Reset} Installing...`);
|
|
110
|
+
frameIndex = (frameIndex + 1) % spinnerFrames.length;
|
|
111
|
+
}, 100);
|
|
112
|
+
try {
|
|
113
|
+
await (0, install_1.npmInstall)(ctx.rootDir);
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
clearInterval(spinner);
|
|
117
|
+
}
|
|
118
|
+
dynamic.end("Dependencies installed.");
|
|
119
|
+
}
|
|
120
|
+
function printSummary(ctx) {
|
|
121
|
+
console.clear();
|
|
122
|
+
const now = new Date();
|
|
123
|
+
const time = now.toLocaleTimeString("pt-BR", { hour12: false });
|
|
124
|
+
const timer = ` ${console_1.Colors.FgGray}${time}${console_1.Colors.Reset} `;
|
|
125
|
+
const label = console_1.Colors.FgGray;
|
|
126
|
+
const cmd = console_1.Colors.Bright + console_1.Colors.FgCyan;
|
|
127
|
+
const ok = console_1.Colors.FgGreen;
|
|
128
|
+
const dim = console_1.Colors.Dim;
|
|
129
|
+
const bright = console_1.Colors.Bright;
|
|
130
|
+
const nodeVersion = process.version;
|
|
131
|
+
const platform = process.platform;
|
|
132
|
+
console.log("");
|
|
133
|
+
console.log(`${timer}${bright}${console_1.Colors.FgCyan}Vatts.js${console_1.Colors.Reset} ${dim}v${ctx.vattsVersion}${console_1.Colors.Reset}`);
|
|
134
|
+
console.log(`${timer}${dim}────────────────────────────────────────${console_1.Colors.Reset}`);
|
|
135
|
+
console.log(`${timer}${ok}✔${console_1.Colors.Reset} ${bright}Project ${console_1.Colors.FgWhite}${ctx.appName}${console_1.Colors.Reset}${bright} created successfully.${console_1.Colors.Reset}`);
|
|
136
|
+
console.log("");
|
|
137
|
+
console.log(`${timer}${label}Environment:${console_1.Colors.Reset}`);
|
|
138
|
+
console.log(`${timer}${label} • Runtime:${console_1.Colors.Reset} ${console_1.Colors.Bright + console_1.Colors.FgGreen}Node.js${console_1.Colors.Reset} ${dim}${nodeVersion}${console_1.Colors.Reset}`);
|
|
139
|
+
console.log(`${timer}${label} • Platform:${console_1.Colors.Reset} ${cmd}${platform}${console_1.Colors.Reset}`);
|
|
140
|
+
console.log(`${timer}${label} • Framework:${console_1.Colors.Reset} ${cmd}Vatts.js${console_1.Colors.Reset} ${dim}v${ctx.vattsVersion}${console_1.Colors.Reset}`);
|
|
141
|
+
console.log("");
|
|
142
|
+
console.log(`${timer}${label}Next steps:${console_1.Colors.Reset}`);
|
|
143
|
+
console.log(`${timer}${label} 1.${console_1.Colors.Reset} ${cmd}cd ${ctx.appName}${console_1.Colors.Reset}`);
|
|
144
|
+
let step = 2;
|
|
145
|
+
if (!ctx.willInstallDependencies) {
|
|
146
|
+
console.log(`${timer}${label} ${step++}.${console_1.Colors.Reset} ${cmd}npm install${console_1.Colors.Reset}`);
|
|
147
|
+
}
|
|
148
|
+
console.log(`${timer}${label} ${step++}.${console_1.Colors.Reset} ${cmd}vatts dev${console_1.Colors.Reset}${console_1.Colors.Reset}`);
|
|
149
|
+
console.log(`${timer}${label} or${console_1.Colors.Reset}`);
|
|
150
|
+
console.log(`${timer}${label} ${cmd}npm run dev${console_1.Colors.Reset}`);
|
|
151
|
+
console.log("");
|
|
152
|
+
console.log(`${timer}${label}Production:${console_1.Colors.Reset}`);
|
|
153
|
+
console.log(`${timer}${label} • Start:${console_1.Colors.Reset} ${cmd}vatts start${console_1.Colors.Reset}`);
|
|
154
|
+
console.log(`${timer}${label} or${console_1.Colors.Reset}`);
|
|
155
|
+
console.log(`${timer}${label} ${cmd}npm run start${console_1.Colors.Reset}`);
|
|
156
|
+
console.log("");
|
|
157
|
+
console.log(`${timer}${dim}Website:${console_1.Colors.Reset} ${console_1.Colors.FgCyan}https://vatts.mfraz.ovh${console_1.Colors.Reset}`);
|
|
158
|
+
console.log("");
|
|
159
|
+
console.log();
|
|
160
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function globalsCssTemplate(willTailwind: boolean): "@import \"tailwindcss\";\n" | "body {\nbackground-color: #030712; \n}";
|
|
2
|
+
export declare function layoutTsxTemplate(): string;
|
|
3
|
+
export declare function vattsConfigTemplate(): string;
|
|
4
|
+
export declare function tsconfigTemplate(opts?: {
|
|
5
|
+
moduleAlias?: string | false;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function postcssConfigTemplate(): string;
|
|
8
|
+
export declare function tailwindConfigTemplate(): string;
|
|
9
|
+
export declare function webIndexRouteTemplate(willTailwind: boolean): string;
|
|
10
|
+
export declare function backendExampleRouteTemplate(): string;
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.globalsCssTemplate = globalsCssTemplate;
|
|
4
|
+
exports.layoutTsxTemplate = layoutTsxTemplate;
|
|
5
|
+
exports.vattsConfigTemplate = vattsConfigTemplate;
|
|
6
|
+
exports.tsconfigTemplate = tsconfigTemplate;
|
|
7
|
+
exports.postcssConfigTemplate = postcssConfigTemplate;
|
|
8
|
+
exports.tailwindConfigTemplate = tailwindConfigTemplate;
|
|
9
|
+
exports.webIndexRouteTemplate = webIndexRouteTemplate;
|
|
10
|
+
exports.backendExampleRouteTemplate = backendExampleRouteTemplate;
|
|
11
|
+
function globalsCssTemplate(willTailwind) {
|
|
12
|
+
// even without tailwind, leave empty file to avoid import errors
|
|
13
|
+
return willTailwind ? `@import "tailwindcss";\n` : `body {
|
|
14
|
+
background-color: #030712;
|
|
15
|
+
}`;
|
|
16
|
+
}
|
|
17
|
+
function layoutTsxTemplate() {
|
|
18
|
+
// keeping same content/behavior as original generator
|
|
19
|
+
return `import React from 'react';
|
|
20
|
+
import {Metadata} from "vatts/react"
|
|
21
|
+
import './globals.css';
|
|
22
|
+
|
|
23
|
+
interface LayoutProps {
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const metadata: Metadata = {
|
|
28
|
+
title: "Vatts JS | The Fast and Simple Web Framework for React",
|
|
29
|
+
description: "The fastest and simplest web framework for React! Start building high-performance web applications today with Vatts JS.",
|
|
30
|
+
keywords: ["Vatts JS", "web framework", "React", "JavaScript", "TypeScript", "web development", "fast", "simple", "SSR", "frontend"],
|
|
31
|
+
author: "Vatts JS Team",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default function Layout({ children }: LayoutProps) {
|
|
35
|
+
return (
|
|
36
|
+
<>{children}</>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
}
|
|
41
|
+
function vattsConfigTemplate() {
|
|
42
|
+
return `import type { VattsConfigFunction } from 'vatts';
|
|
43
|
+
|
|
44
|
+
const hightConfig: VattsConfigFunction = (phase, { defaultConfig }) => {
|
|
45
|
+
return defaultConfig;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default hightConfig;`;
|
|
49
|
+
}
|
|
50
|
+
function tsconfigTemplate(opts) {
|
|
51
|
+
const aliasPrefix = opts?.moduleAlias;
|
|
52
|
+
const willAlias = typeof aliasPrefix === "string" && aliasPrefix.length > 0;
|
|
53
|
+
// convert "@/" => "@/*" and strip trailing "/" for prefix like "@"
|
|
54
|
+
const normalizedPrefix = willAlias ? (aliasPrefix.endsWith("/") ? aliasPrefix : `${aliasPrefix}/`) : "@/";
|
|
55
|
+
const aliasKey = `${normalizedPrefix}*`; // "@/*"
|
|
56
|
+
const aliasBlock = willAlias
|
|
57
|
+
? `,
|
|
58
|
+
"baseUrl": ".",
|
|
59
|
+
"paths": {
|
|
60
|
+
"${aliasKey}": ["src/*"]
|
|
61
|
+
}`
|
|
62
|
+
: "";
|
|
63
|
+
return `{
|
|
64
|
+
"compilerOptions": {
|
|
65
|
+
"target": "ES2020",
|
|
66
|
+
"module": "NodeNext",
|
|
67
|
+
"jsx": "react-jsx",
|
|
68
|
+
"strict": true,
|
|
69
|
+
"esModuleInterop": true,
|
|
70
|
+
"resolveJsonModule": true,
|
|
71
|
+
"skipLibCheck": true,
|
|
72
|
+
"forceConsistentCasingInFileNames": true,
|
|
73
|
+
"rootDir": "./src",
|
|
74
|
+
"outDir": "./dist",
|
|
75
|
+
"moduleResolution": "nodenext",
|
|
76
|
+
"types": ["vatts/global"]${aliasBlock}
|
|
77
|
+
},
|
|
78
|
+
"include": ["src/**/*"],
|
|
79
|
+
"exclude": ["node_modules", "dist"]
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
function postcssConfigTemplate() {
|
|
84
|
+
return `const config = {
|
|
85
|
+
plugins: {
|
|
86
|
+
"@tailwindcss/postcss": {},
|
|
87
|
+
autoprefixer: {},
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
module.exports = config;
|
|
92
|
+
`;
|
|
93
|
+
}
|
|
94
|
+
function tailwindConfigTemplate() {
|
|
95
|
+
return `/** @type {import('tailwindcss').Config} */
|
|
96
|
+
module.exports = {
|
|
97
|
+
content: [
|
|
98
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
99
|
+
"./src/web/**/*.{js,ts,jsx,tsx}",
|
|
100
|
+
],
|
|
101
|
+
theme: {
|
|
102
|
+
extend: {},
|
|
103
|
+
},
|
|
104
|
+
plugins: [],
|
|
105
|
+
}`;
|
|
106
|
+
}
|
|
107
|
+
function webIndexRouteTemplate(willTailwind) {
|
|
108
|
+
let base = `import React from 'react';
|
|
109
|
+
import {RouteConfig} from "vatts/react";`;
|
|
110
|
+
if (willTailwind) {
|
|
111
|
+
base += `
|
|
112
|
+
function Welcome() {
|
|
113
|
+
return (
|
|
114
|
+
<div className="flex min-h-screen flex-col items-center justify-center bg-gray-950 p-4 text-center">
|
|
115
|
+
<div className="group relative">
|
|
116
|
+
<div className="absolute -inset-1 rounded-lg bg-gradient-to-r from-purple-600 to-cyan-400 opacity-25 blur transition duration-500 group-hover:opacity-50"></div>
|
|
117
|
+
<div className="relative rounded-lg bg-gray-900 px-8 py-6 ring-1 ring-gray-800">
|
|
118
|
+
<h1 className="mb-2 text-4xl font-bold tracking-tight text-white sm:text-5xl">
|
|
119
|
+
Hello <span className="text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-cyan-400">World</span>
|
|
120
|
+
</h1>
|
|
121
|
+
|
|
122
|
+
<p className="text-sm font-medium text-gray-400">
|
|
123
|
+
Running with <span className="text-gray-200">Vatts.js</span>
|
|
124
|
+
</p>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
`;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
base += `
|
|
134
|
+
function Welcome() {
|
|
135
|
+
const [isHovered, setIsHovered] = React.useState(false);
|
|
136
|
+
|
|
137
|
+
// Definição dos estilos
|
|
138
|
+
const styles: { [key: string]: React.CSSProperties } = {
|
|
139
|
+
container: {
|
|
140
|
+
display: 'flex',
|
|
141
|
+
minHeight: '100vh',
|
|
142
|
+
flexDirection: 'column',
|
|
143
|
+
alignItems: 'center',
|
|
144
|
+
justifyContent: 'center',
|
|
145
|
+
backgroundColor: '#030712', // gray-950
|
|
146
|
+
padding: '1rem',
|
|
147
|
+
textAlign: 'center',
|
|
148
|
+
fontFamily: 'sans-serif', // Padrão para garantir consistência
|
|
149
|
+
},
|
|
150
|
+
groupWrapper: {
|
|
151
|
+
position: 'relative',
|
|
152
|
+
},
|
|
153
|
+
gradientBlur: {
|
|
154
|
+
position: 'absolute',
|
|
155
|
+
top: '-4px', // -inset-1 (aprox 0.25rem)
|
|
156
|
+
right: '-4px',
|
|
157
|
+
bottom: '-4px',
|
|
158
|
+
left: '-4px',
|
|
159
|
+
borderRadius: '0.5rem',
|
|
160
|
+
background: 'linear-gradient(to right, #9333ea, #22d3ee)', // purple-600 to cyan-400
|
|
161
|
+
filter: 'blur(8px)', // blur (padrao do tailwind é 8px ou 4px dependendo da versão, 8px fica bom aqui)
|
|
162
|
+
transition: 'opacity 500ms ease',
|
|
163
|
+
opacity: isHovered ? 0.5 : 0.25, // Controle via useState
|
|
164
|
+
},
|
|
165
|
+
card: {
|
|
166
|
+
position: 'relative',
|
|
167
|
+
borderRadius: '0.5rem',
|
|
168
|
+
backgroundColor: '#111827', // gray-900
|
|
169
|
+
padding: '1.5rem 2rem', // px-8 py-6
|
|
170
|
+
border: '1px solid #1f2937', // simulando ring-1 ring-gray-800
|
|
171
|
+
color: 'white',
|
|
172
|
+
},
|
|
173
|
+
title: {
|
|
174
|
+
marginBottom: '0.5rem',
|
|
175
|
+
fontSize: '2.25rem', // text-4xl
|
|
176
|
+
fontWeight: 'bold',
|
|
177
|
+
letterSpacing: '-0.025em', // tracking-tight
|
|
178
|
+
color: 'white',
|
|
179
|
+
lineHeight: 1,
|
|
180
|
+
},
|
|
181
|
+
gradientText: {
|
|
182
|
+
color: 'transparent',
|
|
183
|
+
backgroundClip: 'text',
|
|
184
|
+
WebkitBackgroundClip: 'text',
|
|
185
|
+
backgroundImage: 'linear-gradient(to right, #c084fc, #22d3ee)', // purple-400 to cyan-400
|
|
186
|
+
},
|
|
187
|
+
subtitle: {
|
|
188
|
+
fontSize: '0.875rem', // text-sm
|
|
189
|
+
fontWeight: 500,
|
|
190
|
+
color: '#9ca3af', // gray-400
|
|
191
|
+
margin: 0,
|
|
192
|
+
},
|
|
193
|
+
subtitleHighlight: {
|
|
194
|
+
color: '#e5e7eb', // gray-200
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<div style={styles.container}>
|
|
200
|
+
<div
|
|
201
|
+
style={styles.groupWrapper}
|
|
202
|
+
onMouseEnter={() => setIsHovered(true)}
|
|
203
|
+
onMouseLeave={() => setIsHovered(false)}
|
|
204
|
+
>
|
|
205
|
+
<div style={styles.gradientBlur}></div>
|
|
206
|
+
|
|
207
|
+
<div style={styles.card}>
|
|
208
|
+
<h1 style={styles.title}>
|
|
209
|
+
Hello <span style={styles.gradientText}>World</span>
|
|
210
|
+
</h1>
|
|
211
|
+
|
|
212
|
+
<p style={styles.subtitle}>
|
|
213
|
+
Running with <span style={styles.subtitleHighlight}>Vatts.js</span>
|
|
214
|
+
</p>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
);
|
|
219
|
+
}`;
|
|
220
|
+
}
|
|
221
|
+
base += `
|
|
222
|
+
|
|
223
|
+
export const config: RouteConfig = {
|
|
224
|
+
pattern: '/',
|
|
225
|
+
component: Welcome,
|
|
226
|
+
generateMetadata: () => ({
|
|
227
|
+
title: 'Vatts.js | Home'
|
|
228
|
+
})
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
export default config;
|
|
232
|
+
`;
|
|
233
|
+
return base;
|
|
234
|
+
}
|
|
235
|
+
function backendExampleRouteTemplate() {
|
|
236
|
+
return `import {BackendRouteConfig, VattsRequest, VattsResponse} from "vatts"
|
|
237
|
+
|
|
238
|
+
const ExampleRoute: BackendRouteConfig = {
|
|
239
|
+
pattern: '/api/example',
|
|
240
|
+
GET(request: VattsRequest, params) {
|
|
241
|
+
return VattsResponse.json({
|
|
242
|
+
message: 'Welcome to the Example API!'
|
|
243
|
+
})
|
|
244
|
+
},
|
|
245
|
+
POST: async (request: VattsRequest, params) => {
|
|
246
|
+
const data = await request.json();
|
|
247
|
+
return VattsResponse.json({
|
|
248
|
+
message: 'POST request received at Example API!',
|
|
249
|
+
body: data
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export default ExampleRoute;`;
|
|
255
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type CreateAppOptions = {
|
|
2
|
+
/** If omitted, we prompt */
|
|
3
|
+
appName?: string;
|
|
4
|
+
tailwind?: boolean;
|
|
5
|
+
examples?: boolean;
|
|
6
|
+
install?: boolean;
|
|
7
|
+
/** If omitted, we prompt (default: true) */
|
|
8
|
+
moduleAlias?: boolean;
|
|
9
|
+
/** Alias prefix to use when moduleAlias=true (default: "@/") */
|
|
10
|
+
alias?: string;
|
|
11
|
+
};
|
|
12
|
+
export type CreateAppContext = {
|
|
13
|
+
appName: string;
|
|
14
|
+
rootDir: string;
|
|
15
|
+
willTailwind: boolean;
|
|
16
|
+
willRouteExample: boolean;
|
|
17
|
+
willInstallDependencies: boolean;
|
|
18
|
+
willUseModuleAlias: boolean;
|
|
19
|
+
/** Normalized alias prefix (ex: "@/") */
|
|
20
|
+
moduleAlias: string;
|
|
21
|
+
/** computed */
|
|
22
|
+
vattsVersion: string;
|
|
23
|
+
packageJson: Record<string, any>;
|
|
24
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.validateAppName = validateAppName;
|
|
37
|
+
exports.assertTargetDirIsSafeEmpty = assertTargetDirIsSafeEmpty;
|
|
38
|
+
const fs = __importStar(require("node:fs"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const WINDOWS_RESERVED_NAMES = new Set([
|
|
41
|
+
"CON",
|
|
42
|
+
"PRN",
|
|
43
|
+
"AUX",
|
|
44
|
+
"NUL",
|
|
45
|
+
"COM1",
|
|
46
|
+
"COM2",
|
|
47
|
+
"COM3",
|
|
48
|
+
"COM4",
|
|
49
|
+
"COM5",
|
|
50
|
+
"COM6",
|
|
51
|
+
"COM7",
|
|
52
|
+
"COM8",
|
|
53
|
+
"COM9",
|
|
54
|
+
"LPT1",
|
|
55
|
+
"LPT2",
|
|
56
|
+
"LPT3",
|
|
57
|
+
"LPT4",
|
|
58
|
+
"LPT5",
|
|
59
|
+
"LPT6",
|
|
60
|
+
"LPT7",
|
|
61
|
+
"LPT8",
|
|
62
|
+
"LPT9",
|
|
63
|
+
]);
|
|
64
|
+
function validateAppName(appName) {
|
|
65
|
+
const name = appName.trim();
|
|
66
|
+
if (!name) {
|
|
67
|
+
throw new Error("App name cannot be empty.");
|
|
68
|
+
}
|
|
69
|
+
// We scaffold into a folder with this name, so keep it filesystem-safe.
|
|
70
|
+
if (name.includes(path.sep) || name.includes("/") || name.includes("\\")) {
|
|
71
|
+
throw new Error("App name must be a folder name, not a path.");
|
|
72
|
+
}
|
|
73
|
+
// Windows forbidden chars in file/dir names.
|
|
74
|
+
if (/[<>:"/\\|?*]/.test(name)) {
|
|
75
|
+
throw new Error("App name contains invalid filename characters.");
|
|
76
|
+
}
|
|
77
|
+
if (name.length > 214) {
|
|
78
|
+
throw new Error("App name is too long.");
|
|
79
|
+
}
|
|
80
|
+
// Avoid '.' and '..'
|
|
81
|
+
if (name === "." || name === "..") {
|
|
82
|
+
throw new Error("App name cannot be '.' or '..'.");
|
|
83
|
+
}
|
|
84
|
+
// Windows device names (case-insensitive), also invalid with extensions.
|
|
85
|
+
const upper = name.toUpperCase();
|
|
86
|
+
const base = upper.split(".")[0];
|
|
87
|
+
if (WINDOWS_RESERVED_NAMES.has(base)) {
|
|
88
|
+
throw new Error(`App name '${name}' is reserved on Windows.`);
|
|
89
|
+
}
|
|
90
|
+
return name;
|
|
91
|
+
}
|
|
92
|
+
function assertTargetDirIsSafeEmpty(rootDir) {
|
|
93
|
+
// If the directory doesn't exist, it's safe.
|
|
94
|
+
if (!fs.existsSync(rootDir))
|
|
95
|
+
return;
|
|
96
|
+
const stat = fs.statSync(rootDir);
|
|
97
|
+
if (!stat.isDirectory()) {
|
|
98
|
+
throw new Error(`Target path '${rootDir}' already exists and isn't a directory.`);
|
|
99
|
+
}
|
|
100
|
+
// Must be empty to avoid overwriting user's files.
|
|
101
|
+
const entries = fs.readdirSync(rootDir);
|
|
102
|
+
if (entries.length > 0) {
|
|
103
|
+
throw new Error(`Target directory '${rootDir}' already exists and isn't empty.`);
|
|
104
|
+
}
|
|
105
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const console_1 = __importDefault(require("vatts/console"));
|
|
8
|
+
const createApp_1 = require("./createApp");
|
|
9
|
+
async function main() {
|
|
10
|
+
try {
|
|
11
|
+
await (0, createApp_1.createAppFromArgv)(process.argv);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
console_1.default.error("An error occurred:", error);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-vatts-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to create a new Vatts.js application",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-vatts-app": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"vattsjs",
|
|
11
|
+
"vatts",
|
|
12
|
+
"framework",
|
|
13
|
+
"web",
|
|
14
|
+
"typescript",
|
|
15
|
+
"react"
|
|
16
|
+
],
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"author": "itsmuzin",
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^20.11.24",
|
|
24
|
+
"rimraf": "^5.0.0",
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"commander": "^14.0.2",
|
|
29
|
+
"ts-node": "^10.9.2",
|
|
30
|
+
"vatts": "1.0.1"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "rimraf dist && tsc",
|
|
34
|
+
"start": "node dist/index.js",
|
|
35
|
+
"dev": "ts-node src/index.ts",
|
|
36
|
+
"version:major": "pnpm version major --no-git-tag-version",
|
|
37
|
+
"version:minor": "pnpm version minor --no-git-tag-version",
|
|
38
|
+
"version:patch": "pnpm version patch --no-git-tag-version"
|
|
39
|
+
}
|
|
40
|
+
}
|