@postxl/cli 1.4.4 → 1.5.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/dist/create-project.command.js +74 -3
- package/dist/index.js +7 -1
- package/package.json +3 -3
|
@@ -42,6 +42,7 @@ const node_util_1 = require("node:util");
|
|
|
42
42
|
const schema_1 = require("@postxl/schema");
|
|
43
43
|
const utils_1 = require("@postxl/utils");
|
|
44
44
|
const create_project_generator_1 = require("./create-project/create-project.generator");
|
|
45
|
+
const log_schema_error_1 = require("./helpers/log-schema-error");
|
|
45
46
|
const execAsync = (0, node_util_1.promisify)(node_child_process_1.exec);
|
|
46
47
|
async function run(command, options) {
|
|
47
48
|
const { stdout, stderr } = await execAsync(command, options);
|
|
@@ -57,10 +58,25 @@ function register(program) {
|
|
|
57
58
|
.command('create-project')
|
|
58
59
|
.alias('new')
|
|
59
60
|
.summary('Creates a new PostXL project.')
|
|
60
|
-
.description(
|
|
61
|
+
.description(`Creates a new PostXL project.
|
|
62
|
+
|
|
63
|
+
Installation flow:
|
|
64
|
+
1. Prompts for project name, slug, path, and schema (if not provided via options)
|
|
65
|
+
2. Writes initial project files (schema, generate.ts, tsconfig, package.json, .env)
|
|
66
|
+
Uses the simple schema for the first pass even if a custom schema is provided
|
|
67
|
+
3. Runs pnpm install to fetch initial dependencies
|
|
68
|
+
4. Runs first code generation without formatting (as prettier/eslint not yet installed)
|
|
69
|
+
5. Runs pnpm install again to fetch devDependencies added by the generated package.json
|
|
70
|
+
6. Swaps in the custom schema (if provided) before the final generation
|
|
71
|
+
7. Runs second code generation with full formatting (prettier, eslint)
|
|
72
|
+
8. Generates Prisma client
|
|
73
|
+
9. Initializes a git repository (unless --skip-git)
|
|
74
|
+
|
|
75
|
+
If --skip-generate is used with a custom schema, the custom schema is written directly.`)
|
|
61
76
|
.option('-n, --name <name>', 'Project name')
|
|
62
77
|
.option('-s, --slug <slug>', 'Project slug')
|
|
63
78
|
.option('-p, --project-path <path>', 'Path where the generated project should be written. If not specified, user will be prompted')
|
|
79
|
+
.option('-S, --schema <path>', 'Path to an existing postxl-schema.json to use instead of the default simple schema')
|
|
64
80
|
.option('--skip-git', 'Skip initialing a git repository in the generated project directory')
|
|
65
81
|
.option('--skip-generate', 'Skip running the initial project generation')
|
|
66
82
|
.option('-l, --link-postxl', 'Link project to local PostXL monorepo packages (for development purposes)')
|
|
@@ -70,12 +86,16 @@ function register(program) {
|
|
|
70
86
|
const link = options.linkPostxl === true;
|
|
71
87
|
const name = await getProjectName(options.name);
|
|
72
88
|
const slug = await getProjectSlug(options.slug, name);
|
|
73
|
-
const
|
|
89
|
+
const customSchema = await loadCustomSchema(options.schema);
|
|
90
|
+
const schema = customSchema ?? getProjectSchema();
|
|
74
91
|
const projectPath = await resolveProjectPath({ slug, projectPath: options.projectPath });
|
|
92
|
+
// For the first generator pass, use the simple schema (faster, result gets overwritten by second pass anyway).
|
|
93
|
+
// If --skip-generate is active, use the custom schema directly since there won't be a second pass.
|
|
94
|
+
const initialSchema = customSchema && !options.skipGenerate ? getProjectSchema() : schema;
|
|
75
95
|
await createProjectStructure({
|
|
76
96
|
name,
|
|
77
97
|
slug,
|
|
78
|
-
schema,
|
|
98
|
+
schema: initialSchema,
|
|
79
99
|
projectPath,
|
|
80
100
|
});
|
|
81
101
|
// In case it is a workspace project, we install dependencies in the workspace part - else in the project
|
|
@@ -87,6 +107,10 @@ function register(program) {
|
|
|
87
107
|
// After the generation, we now have the full package.json including devDependencies for prettier, eslint, etc.
|
|
88
108
|
// So we install dependencies again to get those.
|
|
89
109
|
await installDependencies({ targetPath: projectPath, link });
|
|
110
|
+
// If a custom schema was provided, write it now before the second (final) generation pass.
|
|
111
|
+
if (customSchema) {
|
|
112
|
+
await writeSchema({ name, slug, schema: customSchema, projectPath });
|
|
113
|
+
}
|
|
90
114
|
// The second generation runs with transformations - setting up prettier, eslint, etc.
|
|
91
115
|
await runGenerate({ projectPath, transform: true });
|
|
92
116
|
await generatePrismaClient(projectPath);
|
|
@@ -94,6 +118,11 @@ function register(program) {
|
|
|
94
118
|
await initializeGitRepository(projectPath);
|
|
95
119
|
}
|
|
96
120
|
}
|
|
121
|
+
else if (customSchema) {
|
|
122
|
+
// With --skip-generate, createProjectStructure already wrote the custom schema,
|
|
123
|
+
// but we still need to apply name/slug/projectType overrides.
|
|
124
|
+
await writeSchema({ name, slug, schema: customSchema, projectPath });
|
|
125
|
+
}
|
|
97
126
|
console.log(`\n✓ Project "${name}" created successfully at ${projectPath}`);
|
|
98
127
|
console.log('\nNext steps:');
|
|
99
128
|
console.log(` cd ${path.relative(process.cwd(), projectPath)}`);
|
|
@@ -133,6 +162,48 @@ async function getProjectSlug(providedSlug, projectName) {
|
|
|
133
162
|
function getProjectSchema() {
|
|
134
163
|
return schema_1.sampleSchemas.simple;
|
|
135
164
|
}
|
|
165
|
+
async function loadCustomSchema(providedPath) {
|
|
166
|
+
if (!providedPath) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const resolvedPath = path.resolve(providedPath);
|
|
170
|
+
let content;
|
|
171
|
+
try {
|
|
172
|
+
content = await fs.readFile(resolvedPath, 'utf-8');
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
176
|
+
console.error(`Schema file not found: ${resolvedPath}`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
console.error(`Failed to read schema file: ${error instanceof Error ? error.message : error}`);
|
|
180
|
+
}
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
let json;
|
|
184
|
+
try {
|
|
185
|
+
json = JSON.parse(content);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
console.error(`Schema file is not valid JSON: ${resolvedPath}`);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
const result = schema_1.zProjectSchema.safeParse(json);
|
|
192
|
+
if (!result.success) {
|
|
193
|
+
(0, log_schema_error_1.logSchemaValidationError)(result.error);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
return json;
|
|
197
|
+
}
|
|
198
|
+
async function writeSchema({ name, slug, schema, projectPath, }) {
|
|
199
|
+
const updatedSchema = {
|
|
200
|
+
...schema,
|
|
201
|
+
name: (0, schema_1.toProjectSchemaName)(name),
|
|
202
|
+
slug: (0, schema_1.toProjectSlug)(slug),
|
|
203
|
+
projectType: 'standalone',
|
|
204
|
+
};
|
|
205
|
+
await fs.writeFile(path.join(projectPath, 'postxl-schema.json'), JSON.stringify(updatedSchema, null, 2) + '\n');
|
|
206
|
+
}
|
|
136
207
|
/**
|
|
137
208
|
* If projectPath is not provided:
|
|
138
209
|
* - Prompt user for path if it should be standalone (in ../{slug}) or workspace (in ./projects/{slug}). Default is standalone.
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
3
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
7
|
const commander_1 = require("commander");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
5
9
|
const create_project_command_1 = require("./create-project.command");
|
|
6
10
|
const generate_command_1 = require("./generate.command");
|
|
7
11
|
const validate_command_1 = require("./validate.command");
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
|
+
const { version } = require(node_path_1.default.join(__dirname, '..', 'package.json'));
|
|
8
14
|
const program = new commander_1.Command();
|
|
9
15
|
program
|
|
10
16
|
//
|
|
11
17
|
.name('pxl')
|
|
12
18
|
.description('CLI for PostXL')
|
|
13
|
-
.version(
|
|
19
|
+
.version(version);
|
|
14
20
|
// Adding all the commands
|
|
15
21
|
(0, generate_command_1.register)(program);
|
|
16
22
|
(0, create_project_command_1.register)(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postxl/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Command-line interface for PostXL code generation framework",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"dotenv": "17.3.1",
|
|
46
46
|
"zod-validation-error": "5.0.0",
|
|
47
47
|
"@postxl/generator": "^1.3.7",
|
|
48
|
-
"@postxl/generators": "^1.
|
|
49
|
-
"@postxl/schema": "^1.8.
|
|
48
|
+
"@postxl/generators": "^1.23.0",
|
|
49
|
+
"@postxl/schema": "^1.8.2",
|
|
50
50
|
"@postxl/utils": "^1.4.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {},
|