@postxl/cli 1.0.13 → 1.1.1
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.
|
@@ -38,44 +38,19 @@ const fs = __importStar(require("node:fs/promises"));
|
|
|
38
38
|
const path = __importStar(require("node:path"));
|
|
39
39
|
const Generator = __importStar(require("@postxl/generator"));
|
|
40
40
|
const generator_1 = require("@postxl/generator");
|
|
41
|
-
const
|
|
41
|
+
const devDependencies = [
|
|
42
|
+
{ packageName: Generator.toPostXlPackageName('@postxl/cli') },
|
|
42
43
|
{ packageName: Generator.toPostXlPackageName('@postxl/generator') },
|
|
43
44
|
{ packageName: Generator.toPostXlPackageName('@postxl/generators') },
|
|
44
45
|
{ packageName: Generator.toPostXlPackageName('@postxl/schema') },
|
|
45
|
-
{ packageName: '
|
|
46
|
-
{ packageName: '
|
|
47
|
-
{ packageName: 'commander', version: '12.1.0' },
|
|
46
|
+
{ packageName: 'prettier', version: '3.7.4' },
|
|
47
|
+
{ packageName: 'eslint', version: '9.39.2' },
|
|
48
48
|
];
|
|
49
|
-
const
|
|
50
|
-
{ packageName: '@prisma/client', version: '6.19.0' },
|
|
51
|
-
{ packageName: 'chokidar-cli', version: '3.0.0' },
|
|
52
|
-
{ packageName: 'eslint', version: '9.39.1' },
|
|
53
|
-
{ packageName: 'eslint-plugin-simple-import-sort', version: '12.1.1' },
|
|
54
|
-
{ packageName: 'jest', version: '29.7.0' },
|
|
55
|
-
{ packageName: 'prettier', version: '3.4.2' },
|
|
56
|
-
{ packageName: 'prisma', version: '6.19.0' },
|
|
57
|
-
{ packageName: 'rimraf', version: '6.1.0' },
|
|
58
|
-
];
|
|
59
|
-
const baseScripts = [
|
|
60
|
-
{ name: 'prettier:check', command: 'prettier --check "**/*.{ts,tsx}" --config ../../prettier.config.js' },
|
|
61
|
-
{ name: 'pxl', command: 'node ../../packages/cli/dist/index.js' },
|
|
62
|
-
];
|
|
63
|
-
const getWorkspaceScripts = (slug) => [
|
|
64
|
-
{ name: 'docker', command: './scripts/docker.sh' },
|
|
49
|
+
const scripts = [
|
|
65
50
|
{ name: 'generate', command: 'pnpm run generate:project && pnpm run generate:prisma' },
|
|
51
|
+
{ name: 'generate:project', command: 'pnpm run generate:project:pxl' },
|
|
52
|
+
{ name: 'generate:project:pxl', command: 'pnpm pxl generate' },
|
|
66
53
|
{ name: 'generate:prisma', command: 'prisma generate' },
|
|
67
|
-
{ name: 'generate:project', command: 'pnpm run generate:project:pxl && pnpm run generate:project:tsr' },
|
|
68
|
-
{ name: 'generate:project:pxl', command: 'node ../../packages/cli/dist/index.js generate' },
|
|
69
|
-
{ name: 'generate:project:tsr', command: `pnpm --filter @postxl/${slug}-frontend exec tsr generate` },
|
|
70
|
-
{
|
|
71
|
-
name: 'generate:watch',
|
|
72
|
-
command: "chokidar '../../packages/**/dist/**' '../../generators/**/dist/**' '../../generators/**/template/**' './generate.ts' './postxl-schema.json' -c 'pnpm run generate:project:pxl -f -i && pnpm run generate:project:tsr'",
|
|
73
|
-
},
|
|
74
|
-
{ name: 'setup', command: './scripts/setup.sh' },
|
|
75
|
-
];
|
|
76
|
-
// TODO: Adjust this for standalone projects once full standalone generation is implemented!
|
|
77
|
-
const standaloneScripts = [
|
|
78
|
-
{ name: 'generate', command: 'node ../../packages/cli/dist/index.js generate' },
|
|
79
54
|
];
|
|
80
55
|
const tsConfig = {
|
|
81
56
|
compilerOptions: {
|
|
@@ -114,9 +89,9 @@ const generators = [
|
|
|
114
89
|
'e2eGenerator',
|
|
115
90
|
'frontendAdminGenerator',
|
|
116
91
|
{ imports: 'Frontend', code: 'Frontend.configureFrontendGenerator(Frontend.all)' },
|
|
117
|
-
'frontendFormsGenerator',
|
|
118
92
|
'frontendTablesGenerator',
|
|
119
93
|
'frontendTrpcClientGenerator',
|
|
94
|
+
'frontendFormsGenerator',
|
|
120
95
|
'mockDataGenerator',
|
|
121
96
|
'seedDataGenerator',
|
|
122
97
|
'typesGenerator',
|
|
@@ -127,7 +102,7 @@ const generators = [
|
|
|
127
102
|
*/
|
|
128
103
|
async function createProject(options) {
|
|
129
104
|
const { projectPath, name, slug, schema } = options;
|
|
130
|
-
const targetPath = projectPath
|
|
105
|
+
const targetPath = projectPath;
|
|
131
106
|
// Create target directory if it doesn't exist
|
|
132
107
|
await fs.mkdir(targetPath, { recursive: true });
|
|
133
108
|
// Update schema with new name and slug
|
|
@@ -136,7 +111,7 @@ async function createProject(options) {
|
|
|
136
111
|
...schema,
|
|
137
112
|
name,
|
|
138
113
|
slug,
|
|
139
|
-
projectType:
|
|
114
|
+
projectType: 'standalone',
|
|
140
115
|
};
|
|
141
116
|
// Write source files directly to disk (not tracked as generated files)
|
|
142
117
|
// These are the files that define the project, not generated output
|
|
@@ -148,14 +123,12 @@ async function createProject(options) {
|
|
|
148
123
|
name: Generator.toPostXlPackageName(`@postxl/${slug}`),
|
|
149
124
|
description: `A PostXL project for ${name}.`,
|
|
150
125
|
dependencies: [],
|
|
151
|
-
devDependencies
|
|
152
|
-
scripts
|
|
126
|
+
devDependencies,
|
|
127
|
+
scripts,
|
|
128
|
+
isInPostXlWorkspace: false,
|
|
153
129
|
};
|
|
154
130
|
await fs.writeFile(path.join(targetPath, 'package.json'), await (0, generator_1.format)({ path: 'package.json', content: Generator.generatePackageJson(packageJsonConfig) }));
|
|
155
|
-
|
|
156
|
-
const relativeGenerationPath = path.relative(targetPath, projectPath.projectGenerationPath) || '.';
|
|
157
|
-
const envContent = `DATABASE_CONNECTION=postgresql://postgres:postgres@localhost:5432/${slug}\n` +
|
|
158
|
-
`PXL_PROJECT_PATH=${relativeGenerationPath}\n`;
|
|
131
|
+
const envContent = `DATABASE_CONNECTION=postgresql://postgres:postgres@localhost:5432/${slug}`;
|
|
159
132
|
await fs.writeFile(path.join(targetPath, '.env.example'), envContent);
|
|
160
133
|
await fs.writeFile(path.join(targetPath, '.env'), envContent);
|
|
161
134
|
}
|
|
@@ -1,13 +1,3 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
export declare function register(program: Command): void;
|
|
3
|
-
export type ProjectPath =
|
|
4
|
-
type ProjectPath_Standalone = {
|
|
5
|
-
kind: 'standalone';
|
|
6
|
-
workspaceProjectPath: string;
|
|
7
|
-
projectGenerationPath: string;
|
|
8
|
-
};
|
|
9
|
-
type ProjectPath_Workspace = {
|
|
10
|
-
kind: 'workspace';
|
|
11
|
-
projectGenerationPath: string;
|
|
12
|
-
};
|
|
13
|
-
export {};
|
|
3
|
+
export type ProjectPath = string;
|
|
@@ -43,6 +43,15 @@ 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
45
|
const execAsync = (0, node_util_1.promisify)(node_child_process_1.exec);
|
|
46
|
+
async function run(command, options) {
|
|
47
|
+
const { stdout, stderr } = await execAsync(command, options);
|
|
48
|
+
if (stdout) {
|
|
49
|
+
console.log(stdout);
|
|
50
|
+
}
|
|
51
|
+
if (stderr) {
|
|
52
|
+
console.error(stderr);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
46
55
|
function register(program) {
|
|
47
56
|
program
|
|
48
57
|
.command('create-project')
|
|
@@ -51,12 +60,14 @@ function register(program) {
|
|
|
51
60
|
.description('Creates a new PostXL project with the simple schema template.')
|
|
52
61
|
.option('-n, --name <name>', 'Project name')
|
|
53
62
|
.option('-s, --slug <slug>', 'Project slug')
|
|
54
|
-
.option('-p, --project-path <path>', 'Path where the generated project should be written. If not specified,
|
|
63
|
+
.option('-p, --project-path <path>', 'Path where the generated project should be written. If not specified, user will be prompted')
|
|
55
64
|
.option('--skip-git', 'Skip initialing a git repository in the generated project directory')
|
|
56
65
|
.option('--skip-generate', 'Skip running the initial project generation')
|
|
66
|
+
.option('-l, --link-postxl', 'Link project to local PostXL monorepo packages (for development purposes)')
|
|
57
67
|
.action(async (options) => {
|
|
58
68
|
try {
|
|
59
69
|
await checkNodeVersion();
|
|
70
|
+
const link = options.linkPostxl === true;
|
|
60
71
|
const name = await getProjectName(options.name);
|
|
61
72
|
const slug = await getProjectSlug(options.slug, name);
|
|
62
73
|
const schema = getProjectSchema();
|
|
@@ -68,18 +79,24 @@ function register(program) {
|
|
|
68
79
|
projectPath,
|
|
69
80
|
});
|
|
70
81
|
// In case it is a workspace project, we install dependencies in the workspace part - else in the project
|
|
71
|
-
await installDependencies(
|
|
82
|
+
await installDependencies({ targetPath: projectPath, link });
|
|
72
83
|
if (!options.skipGenerate) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
await
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
// We initially only install the PostXL generator - without prettier, eslint and eslint rules. Hence, we run the first generation
|
|
85
|
+
// without transformations. This generates the full package.json with all scripts and dependencies.
|
|
86
|
+
await runGenerate({ projectPath, transform: false });
|
|
87
|
+
// After the generation, we now have the full package.json including devDependencies for prettier, eslint, etc.
|
|
88
|
+
// So we install dependencies again to get those.
|
|
89
|
+
await installDependencies({ targetPath: projectPath, link });
|
|
90
|
+
// The second generation runs with transformations - setting up prettier, eslint, etc.
|
|
91
|
+
await runGenerate({ projectPath, transform: true });
|
|
92
|
+
await generatePrismaClient(projectPath);
|
|
93
|
+
if (!options.skipInitGit) {
|
|
94
|
+
await initializeGitRepository(projectPath);
|
|
78
95
|
}
|
|
79
96
|
}
|
|
80
|
-
console.log(`\n✓ Project "${name}" created successfully at ${projectPath
|
|
97
|
+
console.log(`\n✓ Project "${name}" created successfully at ${projectPath}`);
|
|
81
98
|
console.log('\nNext steps:');
|
|
82
|
-
console.log(` cd ${path.relative(process.cwd(), projectPath
|
|
99
|
+
console.log(` cd ${path.relative(process.cwd(), projectPath)}`);
|
|
83
100
|
console.log(' pnpm run generate # generates the project to your configured path');
|
|
84
101
|
console.log(' pnpm run dev # in backend/');
|
|
85
102
|
console.log(' pnpm run dev # in frontend/');
|
|
@@ -117,53 +134,30 @@ function getProjectSchema() {
|
|
|
117
134
|
return schema_1.sampleSchemas.simple;
|
|
118
135
|
}
|
|
119
136
|
/**
|
|
120
|
-
* If projectPath is provided:
|
|
121
|
-
* - if it is local within projects, check if it exists, if yes, throw error. if not, create it and return workspace project
|
|
122
|
-
* - if it is outside of the cwd (regardless of local or absolute), check if exists. if so, throw error, if not create and return standalone project
|
|
123
137
|
* If projectPath is not provided:
|
|
124
|
-
* -
|
|
125
|
-
*
|
|
138
|
+
* - Prompt user for path if it should be standalone (in ../{slug}) or workspace (in ./projects/{slug}). Default is standalone.
|
|
139
|
+
* With projectPath:
|
|
140
|
+
* - if it is local within projects, throw error as we do not support workspace project anymore.
|
|
141
|
+
* - if it is outside of the cwd (regardless of local or absolute), check if exists. if so, throw error, if not create and return-
|
|
126
142
|
*/
|
|
127
143
|
async function resolveProjectPath({ slug, projectPath, }) {
|
|
128
144
|
const repositoryRoot = process.cwd();
|
|
129
|
-
const projectsFolder = path.join(repositoryRoot, 'projects');
|
|
130
145
|
const defaultStandalonePath = path.resolve(repositoryRoot, '..', slug);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const projectGenerationPath = path.isAbsolute(projectPath) ? projectPath : path.resolve(process.cwd(), projectPath);
|
|
134
|
-
await createFolderOrThrow(projectGenerationPath);
|
|
135
|
-
const isInProjectsFolder = projectGenerationPath.startsWith(projectsFolder + path.sep);
|
|
136
|
-
if (isInProjectsFolder) {
|
|
137
|
-
return { kind: 'workspace', projectGenerationPath };
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
await createFolderOrThrow(workspaceProjectPath);
|
|
141
|
-
return {
|
|
142
|
-
kind: 'standalone',
|
|
143
|
-
workspaceProjectPath,
|
|
144
|
-
projectGenerationPath,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
146
|
+
if (!projectPath) {
|
|
147
|
+
projectPath = await prompt('Project path', defaultStandalonePath);
|
|
147
148
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (useWorkspace) {
|
|
152
|
-
await createFolderOrThrow(workspaceProjectPath);
|
|
153
|
-
return {
|
|
154
|
-
kind: 'workspace',
|
|
155
|
-
projectGenerationPath: workspaceProjectPath,
|
|
156
|
-
};
|
|
149
|
+
if (!projectPath) {
|
|
150
|
+
console.error('Project path is required!');
|
|
151
|
+
process.exit(1);
|
|
157
152
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
workspaceProjectPath,
|
|
164
|
-
projectGenerationPath: defaultStandalonePath,
|
|
165
|
-
};
|
|
153
|
+
const projectGenerationPath = path.isAbsolute(projectPath) ? projectPath : path.resolve(repositoryRoot, projectPath);
|
|
154
|
+
const projectsFolder = path.join(repositoryRoot, 'projects');
|
|
155
|
+
const isInProjectsFolder = projectGenerationPath.startsWith(projectsFolder + path.sep);
|
|
156
|
+
if (isInProjectsFolder) {
|
|
157
|
+
throw new Error('Creating workspace projects is no longer supported. Please provide a different path outside of the "postxl" repo folder!');
|
|
166
158
|
}
|
|
159
|
+
await createFolderOrThrow(projectGenerationPath);
|
|
160
|
+
return projectGenerationPath;
|
|
167
161
|
}
|
|
168
162
|
async function createFolderOrThrow(targetPath) {
|
|
169
163
|
try {
|
|
@@ -177,7 +171,7 @@ async function createFolderOrThrow(targetPath) {
|
|
|
177
171
|
}
|
|
178
172
|
}
|
|
179
173
|
async function createProjectStructure({ name, slug, schema, projectPath, }) {
|
|
180
|
-
console.log(`\nCreating project "${name}" at ${projectPath
|
|
174
|
+
console.log(`\nCreating project "${name}" at ${projectPath}...`);
|
|
181
175
|
await (0, create_project_generator_1.createProject)({
|
|
182
176
|
name: (0, schema_1.toProjectSchemaName)(name),
|
|
183
177
|
slug: (0, schema_1.toProjectSlug)(slug),
|
|
@@ -186,16 +180,13 @@ async function createProjectStructure({ name, slug, schema, projectPath, }) {
|
|
|
186
180
|
});
|
|
187
181
|
console.log('Project files created successfully!');
|
|
188
182
|
}
|
|
189
|
-
async function installDependencies(
|
|
183
|
+
async function installDependencies({ targetPath, link }) {
|
|
190
184
|
console.log('\nInstalling dependencies...');
|
|
191
185
|
try {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
console.log(stdout);
|
|
195
|
-
}
|
|
196
|
-
if (stderr) {
|
|
197
|
-
console.error(stderr);
|
|
186
|
+
if (link) {
|
|
187
|
+
await linkPostXlPackages(targetPath);
|
|
198
188
|
}
|
|
189
|
+
await run('pnpm install', { cwd: targetPath });
|
|
199
190
|
console.log('Dependencies installed successfully!');
|
|
200
191
|
}
|
|
201
192
|
catch (error) {
|
|
@@ -203,20 +194,94 @@ async function installDependencies(path) {
|
|
|
203
194
|
console.log('You can manually run "pnpm install" in the project directory.');
|
|
204
195
|
}
|
|
205
196
|
}
|
|
206
|
-
async function
|
|
207
|
-
|
|
197
|
+
async function fileExists(filePath) {
|
|
198
|
+
return fs
|
|
199
|
+
.access(filePath)
|
|
200
|
+
.then(() => true)
|
|
201
|
+
.catch(() => false);
|
|
202
|
+
}
|
|
203
|
+
async function readPackageJson(packageJsonPath) {
|
|
204
|
+
if (!(await fileExists(packageJsonPath))) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const content = await fs.readFile(packageJsonPath, 'utf-8');
|
|
208
|
+
return JSON.parse(content);
|
|
209
|
+
}
|
|
210
|
+
function extractPostXlPackages(packageJson) {
|
|
211
|
+
const filterPostXl = (deps) => Object.keys(deps ?? {}).filter((pkg) => pkg.startsWith('@postxl/'));
|
|
212
|
+
return {
|
|
213
|
+
deps: filterPostXl(packageJson.dependencies),
|
|
214
|
+
devDeps: filterPostXl(packageJson.devDependencies),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function toLocalPackagePaths(packages, relativePathToMonorepo) {
|
|
218
|
+
return packages.map((pkg) => {
|
|
219
|
+
const packageName = pkg.replace('@postxl/', '');
|
|
220
|
+
return path.join(relativePathToMonorepo, 'packages', packageName);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
async function linkPackagesInDir(dir, packages, relativePathToMonorepo, workspaceFlag) {
|
|
224
|
+
const { deps, devDeps } = packages;
|
|
225
|
+
if (deps.length === 0 && devDeps.length === 0) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
console.log(` Linking in ${dir}...`);
|
|
229
|
+
// Link regular dependencies
|
|
230
|
+
if (deps.length > 0) {
|
|
231
|
+
const localPaths = toLocalPackagePaths(deps, relativePathToMonorepo);
|
|
232
|
+
await run(`pnpm add ${localPaths.join(' ')}${workspaceFlag}`, { cwd: dir });
|
|
233
|
+
}
|
|
234
|
+
// Link devDependencies
|
|
235
|
+
if (devDeps.length > 0) {
|
|
236
|
+
const localPaths = toLocalPackagePaths(devDeps, relativePathToMonorepo);
|
|
237
|
+
await run(`pnpm add -D ${localPaths.join(' ')}${workspaceFlag}`, { cwd: dir });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async function linkPostXlPackages(targetPath) {
|
|
241
|
+
console.log('\nLinking PostXL packages...');
|
|
208
242
|
try {
|
|
209
|
-
const
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
243
|
+
const isWorkspace = await fileExists(path.join(targetPath, 'pnpm-workspace.yaml'));
|
|
244
|
+
const workspaceFlag = isWorkspace ? ' -w' : '';
|
|
245
|
+
const packageJsonPaths = [
|
|
246
|
+
{ dir: targetPath, packageJson: path.join(targetPath, 'package.json') },
|
|
247
|
+
{ dir: path.join(targetPath, 'frontend'), packageJson: path.join(targetPath, 'frontend', 'package.json') },
|
|
248
|
+
{ dir: path.join(targetPath, 'backend'), packageJson: path.join(targetPath, 'backend', 'package.json') },
|
|
249
|
+
];
|
|
250
|
+
let totalLinked = 0;
|
|
251
|
+
for (const { dir, packageJson: packageJsonPath } of packageJsonPaths) {
|
|
252
|
+
const packageJson = await readPackageJson(packageJsonPath);
|
|
253
|
+
if (!packageJson) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
const packages = extractPostXlPackages(packageJson);
|
|
257
|
+
const count = packages.deps.length + packages.devDeps.length;
|
|
258
|
+
if (count === 0) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
totalLinked += count;
|
|
262
|
+
const relPath = path.relative(dir, process.cwd()).replaceAll('\\', '/');
|
|
263
|
+
// For subdirs (frontend/backend), don't use workspace flag
|
|
264
|
+
const flag = dir === targetPath ? workspaceFlag : '';
|
|
265
|
+
await linkPackagesInDir(dir, packages, relPath, flag);
|
|
216
266
|
}
|
|
217
|
-
if (
|
|
218
|
-
console.
|
|
267
|
+
if (totalLinked === 0) {
|
|
268
|
+
console.log('No @postxl/* packages found.');
|
|
269
|
+
return;
|
|
219
270
|
}
|
|
271
|
+
console.log('PostXL packages linked successfully!');
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
console.error('Failed to link PostXL packages:', error);
|
|
275
|
+
console.log('You can manually run the linking commands in the project directory.');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async function runGenerate({ projectPath, transform, }) {
|
|
279
|
+
console.log('\nGenerating project code...');
|
|
280
|
+
try {
|
|
281
|
+
await run(`pnpm run generate:project:pxl -f${transform ? '' : ' -t'}`, {
|
|
282
|
+
cwd: projectPath,
|
|
283
|
+
env: { ...process.env, PXL_PROJECT_PATH: projectPath },
|
|
284
|
+
});
|
|
220
285
|
console.log('Project code generated successfully!');
|
|
221
286
|
}
|
|
222
287
|
catch (error) {
|
|
@@ -224,17 +289,10 @@ async function runGenerate(projectPath) {
|
|
|
224
289
|
console.log('You can manually run "pnpm run generate" in the project directory.');
|
|
225
290
|
}
|
|
226
291
|
}
|
|
227
|
-
async function generatePrismaClient(
|
|
228
|
-
// 9. Generate Prisma
|
|
292
|
+
async function generatePrismaClient(targetPath) {
|
|
229
293
|
console.log('\nGenerating Prisma client...');
|
|
230
294
|
try {
|
|
231
|
-
|
|
232
|
-
if (stdout) {
|
|
233
|
-
console.log(stdout);
|
|
234
|
-
}
|
|
235
|
-
if (stderr) {
|
|
236
|
-
console.error(stderr);
|
|
237
|
-
}
|
|
295
|
+
await run('pnpm run generate:prisma', { cwd: targetPath });
|
|
238
296
|
console.log('Prisma client generated successfully!');
|
|
239
297
|
}
|
|
240
298
|
catch (error) {
|
|
@@ -242,10 +300,10 @@ async function generatePrismaClient(path) {
|
|
|
242
300
|
console.log('You can manually run "pnpm run generate:prisma" in the project directory.');
|
|
243
301
|
}
|
|
244
302
|
}
|
|
245
|
-
async function initializeGitRepository(
|
|
303
|
+
async function initializeGitRepository(targetPath) {
|
|
246
304
|
console.log('\nInitializing git repository...');
|
|
247
305
|
try {
|
|
248
|
-
await
|
|
306
|
+
await run('git init -b main', { cwd: targetPath });
|
|
249
307
|
console.log('Git repository initialized successfully!');
|
|
250
308
|
}
|
|
251
309
|
catch (error) {
|
|
@@ -253,15 +311,20 @@ async function initializeGitRepository(path) {
|
|
|
253
311
|
}
|
|
254
312
|
}
|
|
255
313
|
/**
|
|
256
|
-
* Throws if is less than what .
|
|
314
|
+
* Throws if Node.js version is less than what package.json devEngines.runtime requires
|
|
257
315
|
*/
|
|
258
316
|
async function checkNodeVersion() {
|
|
259
317
|
try {
|
|
260
318
|
const repositoryRoot = process.cwd();
|
|
261
|
-
const
|
|
262
|
-
// Read the required version from .
|
|
263
|
-
const
|
|
264
|
-
const
|
|
319
|
+
const packageJsonPath = path.join(repositoryRoot, 'package.json');
|
|
320
|
+
// Read the required version from package.json devEngines.runtime
|
|
321
|
+
const packageJsonContent = await fs.readFile(packageJsonPath, 'utf-8');
|
|
322
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
323
|
+
const requiredVersion = packageJson.devEngines?.runtime?.version;
|
|
324
|
+
if (!requiredVersion) {
|
|
325
|
+
// No devEngines.runtime.version specified, skip check
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
265
328
|
// Get current Node.js version
|
|
266
329
|
const currentVersion = process.version.replace(/^v/, '');
|
|
267
330
|
// Compare major versions
|
|
@@ -273,7 +336,7 @@ async function checkNodeVersion() {
|
|
|
273
336
|
}
|
|
274
337
|
catch (error) {
|
|
275
338
|
if (error.code === 'ENOENT') {
|
|
276
|
-
// .
|
|
339
|
+
// package.json not found, skip check
|
|
277
340
|
return;
|
|
278
341
|
}
|
|
279
342
|
throw error;
|
|
@@ -293,41 +356,3 @@ async function prompt(question, defaultValue) {
|
|
|
293
356
|
});
|
|
294
357
|
});
|
|
295
358
|
}
|
|
296
|
-
// Helper to select from a list
|
|
297
|
-
async function select(question, choices, defaultIndex = 0) {
|
|
298
|
-
if (choices.length === 0) {
|
|
299
|
-
throw new Error('No choices available');
|
|
300
|
-
}
|
|
301
|
-
if (defaultIndex < 0 || defaultIndex >= choices.length) {
|
|
302
|
-
defaultIndex = 0;
|
|
303
|
-
}
|
|
304
|
-
console.log(`\n${question}`);
|
|
305
|
-
for (const [index, choice] of choices.entries()) {
|
|
306
|
-
const num = index + 1;
|
|
307
|
-
const marker = index === defaultIndex ? ' (default)' : '';
|
|
308
|
-
console.log(` ${num}. ${choice}${marker}`);
|
|
309
|
-
}
|
|
310
|
-
const rl = readline.createInterface({
|
|
311
|
-
input: process.stdin,
|
|
312
|
-
output: process.stdout,
|
|
313
|
-
});
|
|
314
|
-
return new Promise((resolve) => {
|
|
315
|
-
const promptText = `\nEnter your choice (number) [default ${defaultIndex + 1}]: `;
|
|
316
|
-
rl.question(promptText, (answer) => {
|
|
317
|
-
rl.close();
|
|
318
|
-
const trimmed = answer.trim();
|
|
319
|
-
if (!trimmed) {
|
|
320
|
-
resolve(defaultIndex);
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
const index = Number.parseInt(trimmed, 10) - 1;
|
|
324
|
-
if (index >= 0 && index < choices.length) {
|
|
325
|
-
resolve(index);
|
|
326
|
-
}
|
|
327
|
-
else {
|
|
328
|
-
console.log('Invalid choice, using default option.');
|
|
329
|
-
resolve(defaultIndex);
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
});
|
|
333
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postxl/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Command-line interface for PostXL code generation framework",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"commander": "14.0.2",
|
|
45
45
|
"dotenv": "17.2.3",
|
|
46
46
|
"zod-validation-error": "3.4.0",
|
|
47
|
-
"@postxl/generator": "^1.0.
|
|
48
|
-
"@postxl/generators": "^1.2.
|
|
47
|
+
"@postxl/generator": "^1.0.11",
|
|
48
|
+
"@postxl/generators": "^1.2.3",
|
|
49
49
|
"@postxl/schema": "^1.0.3",
|
|
50
50
|
"@postxl/utils": "^1.0.1"
|
|
51
51
|
},
|