@buba_71/levit 0.3.3 → 0.3.4
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/dist/bin/cli.js +3 -12
- package/dist/src/commands/init.js +56 -0
- package/dist/src/core/paths.js +29 -0
- package/dist/src/core/version.js +22 -0
- package/dist/src/init.js +12 -40
- package/dist/tests/init.test.js +26 -1
- package/package.json +1 -1
- package/templates/default/agents/AGENTS.md +7 -0
- package/templates/default/pipelines/README.md +2 -0
- package/templates/default/roles/README.md +13 -0
package/dist/bin/cli.js
CHANGED
|
@@ -4,18 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const init_1 = require("../src/init");
|
|
7
|
+
const init_1 = require("../src/commands/init");
|
|
8
|
+
const version_1 = require("../src/core/version");
|
|
8
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
-
function getVersion() {
|
|
11
|
-
try {
|
|
12
|
-
const packageJson = fs_extra_1.default.readJsonSync(node_path_1.default.join(__dirname, "..", "..", "package.json"));
|
|
13
|
-
return packageJson.version;
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return "unknown";
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
10
|
function showHelp() {
|
|
20
11
|
console.log(`
|
|
21
12
|
Usage: levit [command] [options]
|
|
@@ -35,7 +26,7 @@ function main() {
|
|
|
35
26
|
process.exit(0);
|
|
36
27
|
}
|
|
37
28
|
if (args.includes("-v") || args.includes("--version")) {
|
|
38
|
-
console.log(`levit-kit v${getVersion()}`);
|
|
29
|
+
console.log(`levit-kit v${(0, version_1.getVersion)()}`);
|
|
39
30
|
process.exit(0);
|
|
40
31
|
}
|
|
41
32
|
if (args[0] === "init") {
|
|
@@ -0,0 +1,56 @@
|
|
|
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.initProject = initProject;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const paths_1 = require("../core/paths");
|
|
9
|
+
const version_1 = require("../core/version");
|
|
10
|
+
const init_1 = require("../init");
|
|
11
|
+
/**
|
|
12
|
+
* Initializes a new project by copying the default template.
|
|
13
|
+
*
|
|
14
|
+
* @param projectName The name of the project to create
|
|
15
|
+
* @param targetPath The absolute path where the project should be created
|
|
16
|
+
*/
|
|
17
|
+
function initProject(projectName, targetPath) {
|
|
18
|
+
const templatePath = (0, paths_1.getTemplatePath)("default");
|
|
19
|
+
const version = (0, version_1.getVersion)();
|
|
20
|
+
if (!projectName) {
|
|
21
|
+
throw new Error("Project name is required.");
|
|
22
|
+
}
|
|
23
|
+
// Ensure project name is valid for a directory
|
|
24
|
+
if (!/^[a-z0-9-_]+$/i.test(projectName)) {
|
|
25
|
+
throw new Error("Invalid project name. Use only letters, numbers, dashes, and underscores.");
|
|
26
|
+
}
|
|
27
|
+
if (fs_extra_1.default.existsSync(targetPath)) {
|
|
28
|
+
throw new Error(`Directory "${projectName}" already exists.`);
|
|
29
|
+
}
|
|
30
|
+
if (!fs_extra_1.default.existsSync(templatePath)) {
|
|
31
|
+
throw new Error(`Default template not found at ${templatePath}`);
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
(0, init_1.generateProject)(targetPath, "default");
|
|
35
|
+
console.log("");
|
|
36
|
+
console.log(`🚀 levit-kit v${version}`);
|
|
37
|
+
console.log("");
|
|
38
|
+
console.log(" ✔ Structure initialized");
|
|
39
|
+
console.log(" ✔ Conventions applied");
|
|
40
|
+
console.log("");
|
|
41
|
+
console.log(`✨ Project "${projectName}" is ready for development.`);
|
|
42
|
+
console.log("");
|
|
43
|
+
console.log("Next steps:");
|
|
44
|
+
console.log(` 1. cd ${projectName}`);
|
|
45
|
+
console.log(" 2. Review SOCIAL_CONTRACT.md to understand the foundations");
|
|
46
|
+
console.log(" 3. Define your first feature in features/README.md");
|
|
47
|
+
console.log("");
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
// Attempt clean up if directory was created but copy failed
|
|
51
|
+
if (fs_extra_1.default.existsSync(targetPath) && fs_extra_1.default.readdirSync(targetPath).length === 0) {
|
|
52
|
+
fs_extra_1.default.rmSync(targetPath, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
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.getPackageRoot = getPackageRoot;
|
|
7
|
+
exports.getTemplatesPath = getTemplatesPath;
|
|
8
|
+
exports.getTemplatePath = getTemplatePath;
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
/**
|
|
11
|
+
* Resolves the root directory of the levit-kit package.
|
|
12
|
+
* Assuming this file is at src/core/paths.ts,
|
|
13
|
+
* after compilation it will be at dist/src/core/paths.js.
|
|
14
|
+
*/
|
|
15
|
+
function getPackageRoot() {
|
|
16
|
+
return node_path_1.default.resolve(__dirname, "..", "..", "..");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns the absolute path to the templates directory.
|
|
20
|
+
*/
|
|
21
|
+
function getTemplatesPath() {
|
|
22
|
+
return node_path_1.default.join(getPackageRoot(), "templates");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns the absolute path to a specific template.
|
|
26
|
+
*/
|
|
27
|
+
function getTemplatePath(templateName = "default") {
|
|
28
|
+
return node_path_1.default.join(getTemplatesPath(), templateName);
|
|
29
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
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.getVersion = getVersion;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const paths_1 = require("./paths");
|
|
10
|
+
/**
|
|
11
|
+
* Reads and returns the version from the package.json.
|
|
12
|
+
*/
|
|
13
|
+
function getVersion() {
|
|
14
|
+
try {
|
|
15
|
+
const packageJsonPath = node_path_1.default.join((0, paths_1.getPackageRoot)(), "package.json");
|
|
16
|
+
const packageJson = fs_extra_1.default.readJsonSync(packageJsonPath);
|
|
17
|
+
return packageJson.version || "unknown";
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return "unknown";
|
|
21
|
+
}
|
|
22
|
+
}
|
package/dist/src/init.js
CHANGED
|
@@ -3,49 +3,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.generateProject = generateProject;
|
|
7
7
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const packageJson = fs_extra_1.default.readJsonSync(node_path_1.default.join(getPackageRoot(), "package.json"));
|
|
17
|
-
return packageJson.version;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return "0.0.0";
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function initProject(projectName, targetPath) {
|
|
24
|
-
const packageRoot = getPackageRoot();
|
|
25
|
-
const templatePath = node_path_1.default.join(packageRoot, "templates", "default");
|
|
26
|
-
const version = getVersion();
|
|
27
|
-
if (!projectName) {
|
|
28
|
-
throw new Error("Project name is required.");
|
|
29
|
-
}
|
|
30
|
-
if (fs_extra_1.default.existsSync(targetPath)) {
|
|
31
|
-
throw new Error(`Directory "${projectName}" already exists.`);
|
|
32
|
-
}
|
|
8
|
+
const paths_1 = require("./core/paths");
|
|
9
|
+
/**
|
|
10
|
+
* Core generation logic for a new project.
|
|
11
|
+
* Responsible only for file system operations.
|
|
12
|
+
*/
|
|
13
|
+
function generateProject(targetPath, templateName = "default") {
|
|
14
|
+
const templatePath = (0, paths_1.getTemplatePath)(templateName);
|
|
33
15
|
if (!fs_extra_1.default.existsSync(templatePath)) {
|
|
34
|
-
throw new Error(`
|
|
16
|
+
throw new Error(`Template "${templateName}" not found.`);
|
|
17
|
+
}
|
|
18
|
+
if (fs_extra_1.default.existsSync(targetPath) && fs_extra_1.default.readdirSync(targetPath).length > 0) {
|
|
19
|
+
throw new Error(`Target directory "${targetPath}" is not empty.`);
|
|
35
20
|
}
|
|
36
21
|
fs_extra_1.default.ensureDirSync(targetPath);
|
|
37
22
|
fs_extra_1.default.copySync(templatePath, targetPath);
|
|
38
|
-
console.log("");
|
|
39
|
-
console.log(`🚀 levit-kit v${version}`);
|
|
40
|
-
console.log("");
|
|
41
|
-
console.log(" ✔ Project directory created");
|
|
42
|
-
console.log(" ✔ Template copied");
|
|
43
|
-
console.log("");
|
|
44
|
-
console.log(`✨ Project "${projectName}" initialized successfully.`);
|
|
45
|
-
console.log("");
|
|
46
|
-
console.log("Next steps:");
|
|
47
|
-
console.log(` - cd ${projectName}`);
|
|
48
|
-
console.log(" - Read SOCIAL_CONTRACT.md");
|
|
49
|
-
console.log(" - Start defining features");
|
|
50
|
-
console.log("");
|
|
51
23
|
}
|
package/dist/tests/init.test.js
CHANGED
|
@@ -8,7 +8,8 @@ const node_assert_1 = __importDefault(require("node:assert"));
|
|
|
8
8
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
const node_os_1 = __importDefault(require("node:os"));
|
|
11
|
-
const
|
|
11
|
+
const node_child_process_1 = require("node:child_process");
|
|
12
|
+
const init_1 = require("../src/commands/init");
|
|
12
13
|
function exists(p) {
|
|
13
14
|
return node_fs_1.default.existsSync(p);
|
|
14
15
|
}
|
|
@@ -26,8 +27,32 @@ function exists(p) {
|
|
|
26
27
|
node_assert_1.default.ok(exists(node_path_1.default.join(projectPath, "roles")));
|
|
27
28
|
node_assert_1.default.ok(exists(node_path_1.default.join(projectPath, "pipelines")));
|
|
28
29
|
node_assert_1.default.ok(exists(node_path_1.default.join(projectPath, "docs")));
|
|
30
|
+
node_assert_1.default.ok(exists(node_path_1.default.join(projectPath, "roles", "README.md")), "Roles README should exist");
|
|
31
|
+
// New files assertions
|
|
32
|
+
node_assert_1.default.ok(exists(node_path_1.default.join(projectPath, ".gitignore")), ".gitignore should exist");
|
|
33
|
+
node_assert_1.default.ok(exists(node_path_1.default.join(projectPath, "package.json")), "package.json should exist");
|
|
29
34
|
// Agent boundaries
|
|
30
35
|
node_assert_1.default.ok(exists(node_path_1.default.join(projectPath, "agents", "AGENTS.md")), "Agent guidelines should exist");
|
|
31
36
|
// Feature contract
|
|
32
37
|
node_assert_1.default.ok(exists(node_path_1.default.join(projectPath, "features", "README.md")), "Feature README should exist");
|
|
38
|
+
// Clean up
|
|
39
|
+
node_fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
40
|
+
});
|
|
41
|
+
(0, node_test_1.default)("CLI --help works", () => {
|
|
42
|
+
const output = (0, node_child_process_1.execSync)("node dist/bin/cli.js --help").toString();
|
|
43
|
+
node_assert_1.default.ok(output.includes("Usage: levit [command] [options]"));
|
|
44
|
+
node_assert_1.default.ok(output.includes("init <project-name>"));
|
|
45
|
+
});
|
|
46
|
+
(0, node_test_1.default)("CLI --version works", () => {
|
|
47
|
+
const output = (0, node_child_process_1.execSync)("node dist/bin/cli.js --version").toString();
|
|
48
|
+
node_assert_1.default.ok(output.startsWith("levit-kit v"));
|
|
49
|
+
});
|
|
50
|
+
(0, node_test_1.default)("CLI name validation works", () => {
|
|
51
|
+
try {
|
|
52
|
+
(0, node_child_process_1.execSync)("node dist/bin/cli.js init invalid/name");
|
|
53
|
+
node_assert_1.default.fail("Should have failed with invalid name");
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
node_assert_1.default.ok(error.stderr.toString().includes("Error: Invalid project name"));
|
|
57
|
+
}
|
|
33
58
|
});
|
package/package.json
CHANGED
|
@@ -10,4 +10,11 @@ Agents are not allowed to:
|
|
|
10
10
|
- restructure the repository
|
|
11
11
|
- introduce implicit behavior
|
|
12
12
|
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Related Resources
|
|
16
|
+
|
|
17
|
+
- [Project Roles](../roles/README.md): Understand the specific responsibilities within this project.
|
|
18
|
+
- [Feature Contracts](../features/README.md): High-level intents and constraints for new developments.
|
|
19
|
+
|
|
13
20
|
When unsure, agents must ask for human validation.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Project Roles
|
|
2
|
+
|
|
3
|
+
This directory contains the definitions of human and agent roles within this project.
|
|
4
|
+
|
|
5
|
+
## Available Roles
|
|
6
|
+
|
|
7
|
+
- [DevOps](devops.md): Infrastructure, deployment, and operational requirements.
|
|
8
|
+
- [QA](qa.md): Quality standards, testing expectations, and validation criteria.
|
|
9
|
+
- [Security](security.md): Threat assumptions and security constraints.
|
|
10
|
+
|
|
11
|
+
## Goal
|
|
12
|
+
|
|
13
|
+
The goal of defining roles is to **reduce ambiguity**. Each role document should clearly state its boundaries and responsibilities to facilitate collaboration between humans and AI agents.
|