create-projx 1.4.2 → 1.4.3
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/README.md +16 -6
- package/dist/index.js +51 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/create-projx)
|
|
4
4
|
[](https://github.com/ukanhaupa/projx/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/ukanhaupa/projx)
|
|
5
6
|
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
7
8
|
Production-grade project scaffolder. Pick your stack, get a fully wired project with auth, database, CI/CD, and E2E tests — ready to deploy.
|
|
@@ -111,7 +112,7 @@ To skip root-level files (docker-compose, README), add `skip` to `.projx`:
|
|
|
111
112
|
|
|
112
113
|
```json
|
|
113
114
|
{
|
|
114
|
-
"version": "1.
|
|
115
|
+
"version": "1.4.2",
|
|
115
116
|
"components": ["fastapi", "frontend"],
|
|
116
117
|
"skip": ["docker-compose.yml", "README.md"]
|
|
117
118
|
}
|
|
@@ -131,10 +132,12 @@ npx create-projx pin <patterns...>
|
|
|
131
132
|
npx create-projx unpin <patterns...>
|
|
132
133
|
npx create-projx pin --list
|
|
133
134
|
npx create-projx doctor [--fix]
|
|
134
|
-
npx create-projx gen entity <name>
|
|
135
|
+
npx create-projx gen entity <name> [--ai | --backend]
|
|
135
136
|
npx create-projx sync [--url <url>]
|
|
136
137
|
|
|
137
138
|
--components <list> Comma-separated: fastapi,fastify,frontend,mobile,e2e,infra
|
|
139
|
+
--ai Target fastapi (AI/ML) for gen entity
|
|
140
|
+
--backend Target fastify (API backend) for gen entity
|
|
138
141
|
--no-git Skip git init
|
|
139
142
|
--no-install Skip dependency installation
|
|
140
143
|
-y, --yes Accept defaults (fastify + frontend + e2e)
|
|
@@ -178,19 +181,26 @@ Checks: config validity, component markers, baseline ref, stale worktrees, skip
|
|
|
178
181
|
|
|
179
182
|
### Generate Entities
|
|
180
183
|
|
|
181
|
-
Scaffold a new entity
|
|
184
|
+
Scaffold a new entity in your primary backend + typed models for frontend/mobile:
|
|
182
185
|
|
|
183
186
|
```bash
|
|
184
187
|
npx create-projx gen entity invoice # interactive
|
|
185
188
|
npx create-projx gen entity invoice --fields "name:string,amount:number" # non-interactive
|
|
189
|
+
npx create-projx gen entity embedding --ai --fields "name:string,vector:json" # target AI backend
|
|
186
190
|
```
|
|
187
191
|
|
|
188
|
-
|
|
192
|
+
When both `fastapi` and `fastify` exist, the entity generates in the **primary backend** only (not both). First run prompts you to choose and saves to `.projx`:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{ "primaryBackend": "fastify" }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Override with `--ai` (fastapi) or `--backend` (fastify).
|
|
189
199
|
|
|
190
200
|
| Component | Generated |
|
|
191
201
|
| --------- | --------- |
|
|
192
|
-
|
|
|
193
|
-
|
|
|
202
|
+
| Primary backend (fastapi) | `src/entities/<name>/_model.py` — auto-discovered by registry |
|
|
203
|
+
| Primary backend (fastify) | `src/modules/<name>/schemas.ts` + `index.ts` + Prisma model + app.ts import |
|
|
194
204
|
| `frontend` | `src/types/<name>.ts` — TypeScript interface + Create/Update variants |
|
|
195
205
|
| `mobile` | `lib/entities/<name>/model.dart` — Dart class with fromJson/toJson/copyWith |
|
|
196
206
|
|
package/dist/index.js
CHANGED
|
@@ -2622,7 +2622,40 @@ function generateDartModel(config) {
|
|
|
2622
2622
|
lines.push("");
|
|
2623
2623
|
return lines.join("\n");
|
|
2624
2624
|
}
|
|
2625
|
-
async function
|
|
2625
|
+
async function resolvePrimaryBackend(cwd, hasFastapi, hasFastify, backendFlag) {
|
|
2626
|
+
if (backendFlag) return backendFlag;
|
|
2627
|
+
if (hasFastapi && !hasFastify) return "fastapi";
|
|
2628
|
+
if (hasFastify && !hasFastapi) return "fastify";
|
|
2629
|
+
const configPath = join12(cwd, ".projx");
|
|
2630
|
+
if (existsSync11(configPath)) {
|
|
2631
|
+
try {
|
|
2632
|
+
const data = JSON.parse(await readFile11(configPath, "utf-8"));
|
|
2633
|
+
if (data.primaryBackend === "fastapi" || data.primaryBackend === "fastify") {
|
|
2634
|
+
return data.primaryBackend;
|
|
2635
|
+
}
|
|
2636
|
+
} catch {
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
if (!process.stdin.isTTY) return "fastify";
|
|
2640
|
+
const choice = await p9.select({
|
|
2641
|
+
message: "Both backends detected. Which is your primary?",
|
|
2642
|
+
options: [
|
|
2643
|
+
{ value: "fastify", label: "fastify (API backend)" },
|
|
2644
|
+
{ value: "fastapi", label: "fastapi (AI/ML engine)" }
|
|
2645
|
+
],
|
|
2646
|
+
initialValue: "fastify"
|
|
2647
|
+
});
|
|
2648
|
+
if (p9.isCancel(choice)) process.exit(0);
|
|
2649
|
+
try {
|
|
2650
|
+
const data = JSON.parse(await readFile11(configPath, "utf-8"));
|
|
2651
|
+
data.primaryBackend = choice;
|
|
2652
|
+
await writeFile5(configPath, JSON.stringify(data, null, 2) + "\n");
|
|
2653
|
+
p9.log.success(`Saved primaryBackend: ${choice} to .projx`);
|
|
2654
|
+
} catch {
|
|
2655
|
+
}
|
|
2656
|
+
return choice;
|
|
2657
|
+
}
|
|
2658
|
+
async function gen(cwd, entityName, fieldsFlag, backendFlag) {
|
|
2626
2659
|
p9.intro(`projx gen entity ${entityName}`);
|
|
2627
2660
|
const configPath = join12(cwd, ".projx");
|
|
2628
2661
|
if (!existsSync11(configPath)) {
|
|
@@ -2638,6 +2671,9 @@ async function gen(cwd, entityName, fieldsFlag) {
|
|
|
2638
2671
|
p9.log.error("No backend component found. Need fastapi or fastify.");
|
|
2639
2672
|
process.exit(1);
|
|
2640
2673
|
}
|
|
2674
|
+
const targetBackend = await resolvePrimaryBackend(cwd, hasFastapi, hasFastify, backendFlag);
|
|
2675
|
+
const genFastapi = targetBackend === "fastapi" && hasFastapi;
|
|
2676
|
+
const genFastify = targetBackend === "fastify" && hasFastify;
|
|
2641
2677
|
let config;
|
|
2642
2678
|
if (fieldsFlag) {
|
|
2643
2679
|
const fields = parseFieldsFlag(fieldsFlag);
|
|
@@ -2658,7 +2694,7 @@ async function gen(cwd, entityName, fieldsFlag) {
|
|
|
2658
2694
|
config = await promptEntityConfig(entityName);
|
|
2659
2695
|
}
|
|
2660
2696
|
const generated = [];
|
|
2661
|
-
if (
|
|
2697
|
+
if (genFastapi) {
|
|
2662
2698
|
const dir = componentPaths.fastapi;
|
|
2663
2699
|
const entityDir = join12(cwd, dir, "src/entities", toSnake(config.name));
|
|
2664
2700
|
if (existsSync11(entityDir)) {
|
|
@@ -2669,7 +2705,7 @@ async function gen(cwd, entityName, fieldsFlag) {
|
|
|
2669
2705
|
generated.push(`${dir}/src/entities/${toSnake(config.name)}/_model.py`);
|
|
2670
2706
|
}
|
|
2671
2707
|
}
|
|
2672
|
-
if (
|
|
2708
|
+
if (genFastify) {
|
|
2673
2709
|
const dir = componentPaths.fastify;
|
|
2674
2710
|
const moduleDir = join12(cwd, dir, "src/modules", toKebab(config.name));
|
|
2675
2711
|
if (existsSync11(moduleDir)) {
|
|
@@ -2754,13 +2790,13 @@ async function gen(cwd, entityName, fieldsFlag) {
|
|
|
2754
2790
|
p9.log.info(` ${f}`);
|
|
2755
2791
|
}
|
|
2756
2792
|
const className = toPascal(config.name);
|
|
2757
|
-
if (
|
|
2793
|
+
if (genFastapi) {
|
|
2758
2794
|
p9.log.info("");
|
|
2759
2795
|
p9.log.info("FastAPI next steps:");
|
|
2760
2796
|
p9.log.info(` alembic revision --autogenerate -m "add ${config.tableName}"`);
|
|
2761
2797
|
p9.log.info(" alembic upgrade head");
|
|
2762
2798
|
}
|
|
2763
|
-
if (
|
|
2799
|
+
if (genFastify) {
|
|
2764
2800
|
p9.log.info("");
|
|
2765
2801
|
p9.log.info("Fastify next steps:");
|
|
2766
2802
|
p9.log.info(` npx prisma migrate dev --name add_${toSnake(config.name)}`);
|
|
@@ -3146,6 +3182,14 @@ function parseArgs() {
|
|
|
3146
3182
|
flags.fix = true;
|
|
3147
3183
|
continue;
|
|
3148
3184
|
}
|
|
3185
|
+
if (arg === "--ai") {
|
|
3186
|
+
flags.ai = true;
|
|
3187
|
+
continue;
|
|
3188
|
+
}
|
|
3189
|
+
if (arg === "--backend") {
|
|
3190
|
+
flags.backend = true;
|
|
3191
|
+
continue;
|
|
3192
|
+
}
|
|
3149
3193
|
if (arg === "--url") {
|
|
3150
3194
|
const val = args[++i];
|
|
3151
3195
|
if (val) extraArgs.push(`--url=${val}`);
|
|
@@ -3266,7 +3310,8 @@ async function main() {
|
|
|
3266
3310
|
const entityName = extraArgs[1];
|
|
3267
3311
|
const fieldsArg = extraArgs.find((a) => a.startsWith("--fields="));
|
|
3268
3312
|
const fieldsFlag = fieldsArg ? fieldsArg.split("=").slice(1).join("=") : void 0;
|
|
3269
|
-
|
|
3313
|
+
const backendFlag = flags.ai ? "fastapi" : flags.backend ? "fastify" : void 0;
|
|
3314
|
+
await gen(process.cwd(), entityName, fieldsFlag, backendFlag);
|
|
3270
3315
|
return;
|
|
3271
3316
|
}
|
|
3272
3317
|
let opts;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-projx",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.3",
|
|
4
4
|
"description": "Scaffold production-grade fullstack projects in seconds. FastAPI, Fastify, React, Flutter, Terraform — with auth, database, CI/CD, E2E tests, and Docker. One command, ready to deploy.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|