@clubedge/create-clubedge-app 0.42.1 → 0.43.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/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to `create-clubedge-app` are documented here.
4
4
 
5
+ ## 0.43.0
6
+
7
+ - **Upgrades keep each app's own version** (#134, by @ahmed-husssain):
8
+ - An app whose version the project changed in `apps/*/package.json` keeps it, without a conflict on that line.
9
+ - An app whose version the project never touched takes the new Starter's.
10
+ - This completes 0.41.0's version ownership, which covered the root `package.json`.
11
+ - **`add`, `remove`, and `upgrade` that change nothing exit before downloading the Starter** (#133, by @ahmed-husssain; issue #132):
12
+ - The cases: `upgrade` on the pinned Starter's commit or with `--ref` set to the recorded commit, `add` with options the project already uses, and `remove` of modules recorded as `none`.
13
+ - These commands now work offline. They no longer refuse a project with uncommitted changes, since they change nothing.
14
+ - `upgrade --ref <branch>` still resolves the branch, which may have moved. `remove` with an unknown module still fails with `Unknown module`.
15
+ - Still on Starter `v0.27.1`.
16
+
5
17
  ## 0.42.1
6
18
 
7
19
  - Default to Starter `v0.27.1` (#140): new projects carry the Clubedge Starter brand, and their mobile app shows it.
package/README.md CHANGED
@@ -381,7 +381,7 @@ Projects created with `--infra neon` also have `.github/workflows/preview.yml`,
381
381
  Each CLI release is tested against one specific Starter release:
382
382
 
383
383
  ```text
384
- create-clubedge-app v0.42.1
384
+ create-clubedge-app v0.43.0
385
385
  |
386
386
  v
387
387
  Clubedge Starter v0.27.1
@@ -392,7 +392,7 @@ The current relationship is:
392
392
 
393
393
  | CLI release | Default Starter release | Meaning |
394
394
  | --- | --- | --- |
395
- | `create-clubedge-app@0.42.1` | `clubedge-starter@v0.27.1` | The CLI's required, tested default |
395
+ | `create-clubedge-app@0.43.0` | `clubedge-starter@v0.27.1` | The CLI's required, tested default |
396
396
 
397
397
  This means the same CLI version always scaffolds the same Starter revision by default. The CLI does not silently follow Starter `main`.
398
398
 
@@ -509,6 +509,7 @@ Each phase ends with a Starter release and a CLI release pinned to it. The full
509
509
  | 0.40.0 | v0.26.0 | Starter v0.26.0: every module on React + Vite with FastAPI (pg-boss excepted) |
510
510
  | 0.41.0 | v0.26.0 | A conflicted package.json no longer breaks later commands (`--detailed-exit-code`); doctor finds conflict markers; projects own their version and README |
511
511
  | 0.42.0 | v0.27.0 | Starter v0.27.0: mobile apps with Capacitor (`--shell capacitor`, template schema 5); client addresses per platform; Docker Compose behind Caddy, with images on GHCR |
512
+ | 0.43.0 | v0.27.1 | Upgrades keep each app's own version; add, remove, and upgrade that change nothing skip the Starter download |
512
513
 
513
514
  ## Community
514
515
 
@@ -88,10 +88,13 @@ export function customizeLegacySource(source, { displayName }) {
88
88
  .replaceAll(">Clubedge<", `>${displayName}<`)
89
89
  .replaceAll("Starter workspace", "Application workspace");
90
90
  }
91
- /** Gives a selected stack's app the package name generated projects use. */
92
- export function customizeAppManifest(source, appPackage) {
91
+ /** Gives a selected stack's app the package name generated projects use and preserves its version. */
92
+ export function customizeAppManifest(source, appPackage, version) {
93
93
  const manifest = JSON.parse(source);
94
- manifest.name = appPackage;
94
+ if (appPackage)
95
+ manifest.name = appPackage;
96
+ if (version !== undefined)
97
+ manifest.version = version;
95
98
  return json(manifest);
96
99
  }
97
100
  /**
@@ -3,6 +3,7 @@
3
3
  // through a three-way merge, see merge.ts.
4
4
  import { mkdir, readdir, rm, rmdir, writeFile } from "node:fs/promises";
5
5
  import { dirname, join } from "node:path";
6
+ import { customizeAppManifest } from "./customize.js";
6
7
  import { updateEnvFile } from "./env.js";
7
8
  import { INCOMING_DIR, planMerge, sameContent } from "./merge.js";
8
9
  import { readProjectFiles, renderProject } from "./project.js";
@@ -35,6 +36,26 @@ export async function planUpdate(project, base, target) {
35
36
  baseFiles.delete("README.md");
36
37
  targetFiles.delete("README.md");
37
38
  }
39
+ // Workspace apps take the new Starter's version unless the project customized their version.
40
+ for (const [path, targetContent] of targetFiles) {
41
+ if (!path.startsWith("apps/") || !path.endsWith("/package.json"))
42
+ continue;
43
+ const baseContent = baseFiles.get(path);
44
+ const currentContent = current.get(path);
45
+ if (!baseContent || !currentContent)
46
+ continue;
47
+ try {
48
+ const basePkg = JSON.parse(baseContent.toString("utf8"));
49
+ const currentPkg = JSON.parse(currentContent.toString("utf8"));
50
+ if (typeof currentPkg.version === "string" && currentPkg.version !== basePkg.version) {
51
+ baseFiles.set(path, Buffer.from(customizeAppManifest(baseContent.toString("utf8"), undefined, currentPkg.version)));
52
+ targetFiles.set(path, Buffer.from(customizeAppManifest(targetContent.toString("utf8"), undefined, currentPkg.version)));
53
+ }
54
+ }
55
+ catch {
56
+ // Leave unparseable manifests untouched.
57
+ }
58
+ }
38
59
  const actions = planMerge(baseFiles, targetFiles, current);
39
60
  if (customReadme && targetReadme && !sameContent(currentReadme, targetReadme)) {
40
61
  actions.push({
package/dist/modify.js CHANGED
@@ -366,8 +366,27 @@ export async function changeProject(args) {
366
366
  throw new Error("Not a project change.");
367
367
  const interactive = Boolean(process.stdin.isTTY) && !args.yes;
368
368
  const project = await readProject(process.cwd());
369
- await assertSafeToChange(project, args, interactive);
370
369
  const upgrading = command.name === "upgrade";
370
+ if (upgrading &&
371
+ !args.templateDir &&
372
+ project.starterCommit &&
373
+ (args.ref ? args.ref === project.starterCommit : project.starterCommit === starterPin.starterCommit)) {
374
+ outro(`The project is already on Starter ${project.starterRef}.`);
375
+ return "unchanged";
376
+ }
377
+ if (command.name === "add" &&
378
+ command.changes.length > 0 &&
379
+ command.changes.every((c) => c.option && project.modules[c.module] === c.option)) {
380
+ outro("The project already uses that selection; nothing to change.");
381
+ return "unchanged";
382
+ }
383
+ if (command.name === "remove" &&
384
+ command.modules.length > 0 &&
385
+ command.modules.every((m) => project.modules[m] === "none")) {
386
+ outro("The project already uses that selection; nothing to change.");
387
+ return "unchanged";
388
+ }
389
+ await assertSafeToChange(project, args, interactive);
371
390
  const progress = spinner();
372
391
  progress.start(upgrading ? "Preparing both Starter revisions" : `Preparing Starter ${project.starterRef}`);
373
392
  const sources = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clubedge/create-clubedge-app",
3
- "version": "0.42.1",
3
+ "version": "0.43.0",
4
4
  "description": "Create React apps from Clubedge Starter with a CLI or local MCP server.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.9.0",