@postxl/cli 1.0.12 → 1.1.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.
|
@@ -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,13 @@ 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,
|
|
129
|
+
packageManager: 'pnpm@10.26.1',
|
|
153
130
|
};
|
|
154
131
|
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`;
|
|
132
|
+
const envContent = `DATABASE_CONNECTION=postgresql://postgres:postgres@localhost:5432/${slug}`;
|
|
159
133
|
await fs.writeFile(path.join(targetPath, '.env.example'), envContent);
|
|
160
134
|
await fs.writeFile(path.join(targetPath, '.env'), envContent);
|
|
161
135
|
}
|
|
@@ -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) {
|
|
@@ -293,41 +351,3 @@ async function prompt(question, defaultValue) {
|
|
|
293
351
|
});
|
|
294
352
|
});
|
|
295
353
|
}
|
|
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/dist/generate.command.js
CHANGED
|
@@ -64,6 +64,7 @@ This reads the schema from ${(0, utils_1.yellow)('schema.json')} and runs the ge
|
|
|
64
64
|
.option('-p, --pattern <glob>', 'filters files by glob pattern (e.g., "**/*.ts" or "backend/libs/**")')
|
|
65
65
|
.option('-q, --quiet', 'does not print errors')
|
|
66
66
|
.option('-s, --skip-lint', 'skips linting')
|
|
67
|
+
.option('-t, --skip-transform', 'skips linting and formatting')
|
|
67
68
|
.option('-v, --verbose', 'shows verbose linting messages')
|
|
68
69
|
.action(async (projectPath, targetPath, options) => {
|
|
69
70
|
if (projectPath.startsWith('.')) {
|
|
@@ -104,20 +105,22 @@ This reads the schema from ${(0, utils_1.yellow)('schema.json')} and runs the ge
|
|
|
104
105
|
.generate((g) => g)
|
|
105
106
|
//
|
|
106
107
|
.then(async (g) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
(
|
|
108
|
+
if (!options.skipTransform) {
|
|
109
|
+
const lintResult = await (0, generator_1.lint)(g.context.vfs, options);
|
|
110
|
+
if (!options.quiet) {
|
|
111
|
+
(0, generator_1.logLintResults)(lintResult, options);
|
|
112
|
+
}
|
|
113
|
+
await g.context.vfs.transform(generator_1.format, {
|
|
114
|
+
onError: ({ path, error }) => {
|
|
115
|
+
if (options.ignoreErrors) {
|
|
116
|
+
console.error(`Error formatting ${path}:`, error);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
});
|
|
110
123
|
}
|
|
111
|
-
await g.context.vfs.transform(generator_1.format, {
|
|
112
|
-
onError: ({ path, error }) => {
|
|
113
|
-
if (options.ignoreErrors) {
|
|
114
|
-
console.error(`Error formatting ${path}:`, error);
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
throw error;
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
124
|
const result = await (0, generator_1.sync)({
|
|
122
125
|
vfs: g.context.vfs,
|
|
123
126
|
lockFilePath: path.join(targetPath, 'postxl-lock.json'),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postxl/cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
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.
|
|
47
|
+
"@postxl/generator": "^1.0.9",
|
|
48
|
+
"@postxl/generators": "^1.2.1",
|
|
49
49
|
"@postxl/schema": "^1.0.3",
|
|
50
50
|
"@postxl/utils": "^1.0.1"
|
|
51
51
|
},
|