create-projx 1.5.3 → 1.5.5

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.
Files changed (2) hide show
  1. package/dist/index.js +44 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -501,6 +501,33 @@ function generateVscodeSettings(vars) {
501
501
 
502
502
  // src/baseline.ts
503
503
  var BASELINE_REF = "refs/projx/baseline";
504
+ async function writeManagedProjx(cwd, version, vars, components) {
505
+ const projxPath = join3(cwd, ".projx");
506
+ let existing = {};
507
+ if (existsSync2(projxPath)) {
508
+ try {
509
+ existing = JSON.parse(await readFile3(projxPath, "utf-8"));
510
+ } catch (err) {
511
+ const msg = err instanceof Error ? err.message : String(err);
512
+ console.warn(`projx: existing .projx is unreadable (${msg}); writing fresh.`);
513
+ }
514
+ }
515
+ const merged = {
516
+ ...existing,
517
+ version
518
+ };
519
+ if (components !== void 0) {
520
+ merged.components = components;
521
+ }
522
+ if (typeof merged.createdAt !== "string") {
523
+ merged.createdAt = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
524
+ }
525
+ const pmObj = vars.pm;
526
+ if (pmObj?.name && !merged.packageManager) {
527
+ merged.packageManager = pmObj.name;
528
+ }
529
+ await writeFile2(projxPath, JSON.stringify(merged, null, 2) + "\n");
530
+ }
504
531
  function matchesSkip(filePath, patterns) {
505
532
  for (const pattern of patterns) {
506
533
  if (pattern === "**") return true;
@@ -558,7 +585,10 @@ function mergeFileThreeWay(oursPath, baseContent, theirsContent) {
558
585
  try {
559
586
  writeFileSync(baseTmp, baseContent);
560
587
  writeFileSync(theirsTmp, theirsContent);
561
- execSync2(`git merge-file "${oursPath}" "${baseTmp}" "${theirsTmp}"`, { stdio: "pipe" });
588
+ execSync2(
589
+ `git merge-file -L "your changes" -L "previous projx baseline" -L "new projx template" "${oursPath}" "${baseTmp}" "${theirsTmp}"`,
590
+ { stdio: "pipe" }
591
+ );
562
592
  return true;
563
593
  } catch {
564
594
  return false;
@@ -595,6 +625,7 @@ async function tryThreeWayMerge(cwd, templateDir, baselineRef) {
595
625
  const merged = [];
596
626
  const conflicted = [];
597
627
  for (const file of templateFiles) {
628
+ if (file === ".projx") continue;
598
629
  const oursPath = join3(cwd, file);
599
630
  if (!existsSync2(oursPath)) continue;
600
631
  const baseContent = getFileAtRef(cwd, baselineRef, file);
@@ -606,8 +637,13 @@ async function tryThreeWayMerge(cwd, templateDir, baselineRef) {
606
637
  continue;
607
638
  }
608
639
  const oursContent = await readFile3(oursPath, "utf-8");
609
- if (oursContent === baseContent) continue;
610
640
  if (theirsContent === baseContent) continue;
641
+ if (oursContent === baseContent) {
642
+ await writeFile2(oursPath, theirsContent);
643
+ merged.push(file);
644
+ continue;
645
+ }
646
+ if (oursContent === theirsContent) continue;
611
647
  const clean = mergeFileThreeWay(oursPath, baseContent, theirsContent);
612
648
  if (clean) {
613
649
  merged.push(file);
@@ -714,14 +750,7 @@ async function writeTemplateToDir(dest, repoDir, components, componentPaths, var
714
750
  await mkdir2(join3(dest, ".vscode"), { recursive: true });
715
751
  await writeFile2(join3(dest, ".vscode/settings.json"), generateVscodeSettings(vars));
716
752
  }
717
- const projxConfig = {
718
- version,
719
- components,
720
- createdAt: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
721
- };
722
- const pmObj = vars.pm;
723
- if (pmObj?.name) projxConfig.packageManager = pmObj.name;
724
- await writeFile2(join3(dest, ".projx"), JSON.stringify(projxConfig, null, 2) + "\n");
753
+ await writeManagedProjx(dest, version, vars, components);
725
754
  }
726
755
  async function substituteNames(dest, components, paths, name, nameSnake) {
727
756
  if (components.includes("fastapi")) {
@@ -804,15 +833,8 @@ async function applyTemplate(cwd, repoDir, components, componentPaths, vars, ver
804
833
  await writeTemplateToDir(tmpTemplate, repoDir, components, componentPaths, vars, version, origin, componentSkips, rootSkip);
805
834
  const result = await tryThreeWayMerge(cwd, tmpTemplate, baselineRef);
806
835
  await rm2(tmpTemplate, { recursive: true, force: true });
807
- const projxConfig = {
808
- version,
809
- components,
810
- createdAt: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
811
- };
812
- const pmObj = vars.pm;
813
- if (pmObj?.name) projxConfig.packageManager = pmObj.name;
814
- await writeFile2(join3(cwd, ".projx"), JSON.stringify(projxConfig, null, 2) + "\n");
815
836
  if (result.conflicted.length === 0) {
837
+ await writeManagedProjx(cwd, version, vars);
816
838
  execSync2("git add -A", { cwd, stdio: "pipe" });
817
839
  const staged = execSync2("git diff --cached --stat", { cwd, stdio: "pipe" }).toString().trim();
818
840
  if (staged) {
@@ -824,12 +846,7 @@ async function applyTemplate(cwd, repoDir, components, componentPaths, vars, ver
824
846
  saveBaselineRef(cwd);
825
847
  return result.merged.length > 0 ? { status: "merged", mergedFiles: result.merged } : { status: "clean" };
826
848
  }
827
- for (const f of result.conflicted) {
828
- try {
829
- execSync2(`git checkout -- "${f}"`, { cwd, stdio: "pipe" });
830
- } catch {
831
- }
832
- }
849
+ await writeManagedProjx(cwd, version, vars);
833
850
  for (const f of result.merged) {
834
851
  try {
835
852
  execSync2(`git add "${f}"`, { cwd, stdio: "pipe" });
@@ -2766,7 +2783,7 @@ function generateFastapiTest(config) {
2766
2783
  lines.push(`from datetime import ${dateImports.join(", ")}`);
2767
2784
  lines.push("");
2768
2785
  }
2769
- lines.push(`from src.entities.${snake}._model import ${className}`);
2786
+ lines.push(`from src.entities.${snake} import ${className}`);
2770
2787
  lines.push(`from tests.base_entity_api_test import BaseEntityApiTest`);
2771
2788
  lines.push("");
2772
2789
  lines.push("");
@@ -2902,7 +2919,9 @@ async function gen(cwd, entityName, fieldsFlag, backendFlag) {
2902
2919
  } else {
2903
2920
  await mkdir5(entityDir, { recursive: true });
2904
2921
  await writeFile5(join12(entityDir, "_model.py"), generateFastAPIModel(config));
2922
+ await writeFile5(join12(entityDir, "__init__.py"), "from ._model import *\n");
2905
2923
  generated.push(`${dir}/src/entities/${toSnake(config.name)}/_model.py`);
2924
+ generated.push(`${dir}/src/entities/${toSnake(config.name)}/__init__.py`);
2906
2925
  const testsDir = join12(cwd, dir, "tests");
2907
2926
  const testFile = join12(testsDir, `test_${toSnake(config.name)}_entity.py`);
2908
2927
  if (existsSync11(testsDir) && !existsSync11(testFile)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-projx",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
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": {