@clubedge/create-clubedge-app 0.1.3 → 0.1.9

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,36 @@
2
2
 
3
3
  All notable changes to `create-clubedge-app` are documented here.
4
4
 
5
+ ## 0.1.9
6
+
7
+ - Use npm Trusted Publishing with GitHub Actions OIDC for releases.
8
+ - Use an npm CLI version supported by Trusted Publishing and remove the token-based publish dependency.
9
+
10
+ ## 0.1.8
11
+
12
+ - Correct the pinned Starter commit to the commit actually resolved by the immutable `v0.1.1` tag.
13
+
14
+ ## 0.1.7
15
+
16
+ - Pin the default Starter reference to the tested `v0.1.1` release, including the corrected browser contract.
17
+
18
+ ## 0.1.6
19
+
20
+ - Move the CLI and Starter repository references to the `Clubedge` GitHub organization.
21
+ - Update package metadata, documentation, tests, and generated provenance for the organization repositories.
22
+
23
+ ## 0.1.5
24
+
25
+ - Verify the default Starter tag resolves to its expected commit and record that commit in generated metadata.
26
+ - Add a post-publish smoke-test workflow for the published npm package.
27
+
28
+ ## 0.1.4
29
+
30
+ - Pin the default Starter reference to the tested release tag `v0.1.0`.
31
+ - Record the CLI version and Starter reference in generated project metadata and documentation.
32
+ - Add scheduled compatibility verification for the latest Starter `main` branch.
33
+ - Document the CLI-to-Starter version relationship and release workflow.
34
+
5
35
  ## 0.1.3
6
36
 
7
37
  - Keep generated project-name customization aligned with the dashboard's route-local sidebar.
package/README.md CHANGED
@@ -1,11 +1,38 @@
1
1
  # create-clubedge-app
2
2
 
3
- [![CI](https://github.com/yassine-ahmed/create-clubedge-app/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/yassine-ahmed/create-clubedge-app/actions/workflows/ci.yml)
3
+ [![CI](https://github.com/Clubedge/create-clubedge-app/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Clubedge/create-clubedge-app/actions/workflows/ci.yml)
4
4
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE)
5
5
 
6
- Create a Next.js application from the [Clubedge Starter](https://github.com/yassine-ahmed/clubedge-starter) reference implementation.
6
+ Create a Next.js application from the [Clubedge Starter](https://github.com/Clubedge/clubedge-starter) reference implementation.
7
7
 
8
- The CLI downloads the starter repository, names the generated project, creates `apps/web/.env.local` from the example, initializes Git, and installs dependencies. The starter remains the source of truth for the generated architecture.
8
+ The CLI downloads a tested Starter release, names the generated project, creates `apps/web/.env.local` from the example, initializes Git, and installs dependencies. The Starter remains the source of truth for the generated architecture.
9
+
10
+ ## Version relationship
11
+
12
+ Each CLI release is tested against one specific Starter release:
13
+
14
+ ```text
15
+ create-clubedge-app v0.1.9
16
+ |
17
+ v
18
+ Clubedge Starter v0.1.1
19
+ commit 0be0c18d41f01cd011c576fb65c25711081b8ad4
20
+ ```
21
+
22
+ The current relationship is:
23
+
24
+ | CLI release | Default Starter release | Meaning |
25
+ | --- | --- | --- |
26
+ | `create-clubedge-app@0.1.9` | `clubedge-starter@v0.1.1` | The CLI's required, tested default |
27
+
28
+ This means the same CLI version always scaffolds the same Starter revision by default. The CLI does not silently follow Starter `main`.
29
+
30
+ The `v0.1.1` tag is expected to resolve to commit
31
+ `0be0c18d41f01cd011c576fb65c25711081b8ad4`. The CLI verifies this before
32
+ scaffolding with the default reference and fails rather than silently using a
33
+ moved tag.
34
+
35
+ When the Starter changes, its maintainers first publish a new versioned release, such as `v0.2.0`. The CLI is then updated to use that release, all generated-project checks must pass, and a new CLI version is published. This keeps Starter and CLI releases independently versioned while preserving a tested compatibility relationship.
9
36
 
10
37
  ## Requirements
11
38
 
@@ -46,7 +73,7 @@ pnpm dlx @clubedge/create-clubedge-app
46
73
  ```text
47
74
  Usage: pnpm dlx @clubedge/create-clubedge-app [project-directory] [options]
48
75
 
49
- --ref <branch-or-tag> Select a branch or tag from the starter repository (default: main)
76
+ --ref <ref> Select a starter tag, branch, or commit (default: v0.1.1)
50
77
  --no-install Skip pnpm install
51
78
  --no-git Skip Git initialization
52
79
  -h, --help Show help
@@ -56,15 +83,31 @@ Usage: pnpm dlx @clubedge/create-clubedge-app [project-directory] [options]
56
83
  Examples:
57
84
 
58
85
  ```sh
59
- pnpm dlx @clubedge/create-clubedge-app my-app --ref v1.0.0
86
+ pnpm dlx @clubedge/create-clubedge-app my-app --ref <starter-tag-or-commit>
60
87
  pnpm dlx @clubedge/create-clubedge-app my-app --no-install
61
88
  ```
62
89
 
63
- The target directory must be empty or not exist. The CLI will not delete or overwrite files in a non-empty target directory. The default `main` ref follows the current reference implementation; use a tag to scaffold a specific starter revision.
90
+ The target directory must be empty or not exist. The CLI will not delete or overwrite files in a non-empty target directory. The default is the tested `v0.1.1` Starter release, so the same CLI version produces the same Starter revision. Use `--ref` to explicitly select a tag, branch, or commit.
91
+
92
+ The default is the tested Starter release tag `v0.1.1`. Every generated project records its CLI version, Starter repository, exact Starter ref, and resolved Starter commit in `package.json` and `README.md`.
93
+
94
+ Use `--ref` only when you intentionally want a different Starter revision:
95
+
96
+ ```sh
97
+ # Reproduce the supported default
98
+ pnpm dlx @clubedge/create-clubedge-app my-app
99
+
100
+ # Try an unreleased Starter change
101
+ pnpm dlx @clubedge/create-clubedge-app my-app --ref main
102
+
103
+ # Reproduce a specific Starter release or commit
104
+ pnpm dlx @clubedge/create-clubedge-app my-app --ref v0.1.1
105
+ pnpm dlx @clubedge/create-clubedge-app my-app --ref <commit-sha>
106
+ ```
64
107
 
65
108
  ## How it works
66
109
 
67
- This first CLI release scaffolds the complete reference starter. It does not yet offer selectable SaaS, dashboard, or minimal feature presets; those should be added once each preset has a distinct, maintained template. This keeps CLI output aligned with the reference repo instead of creating a second, drifting copy of its source.
110
+ This CLI scaffolds the complete reference Starter. It does not yet offer selectable SaaS, dashboard, or minimal feature presets; those should be added once each preset has a distinct, maintained template. This keeps CLI output aligned with the Starter repository instead of creating a second, drifting copy of its source.
68
111
 
69
112
  ## Development
70
113
 
@@ -76,7 +119,26 @@ pnpm check
76
119
  pnpm test
77
120
  ```
78
121
 
79
- CI also scaffolds a clean project from the current starter, installs its dependencies, runs linting, typechecking, unit tests, browser checks, and a production build, then starts the generated app and checks the landing page, sign-up page, dashboard, health endpoint, logo, and favicon.
122
+ CI scaffolds a clean project from the pinned Starter release, installs its dependencies, runs linting, typechecking, unit tests, browser checks, and a production build, then starts the generated app and checks the landing page, sign-up page, dashboard, health endpoint, logo, and favicon. A scheduled, non-blocking compatibility job also checks Starter `main`.
123
+
124
+ ## Release workflow
125
+
126
+ ### Starter maintainers
127
+
128
+ 1. Make and validate changes in `clubedge-starter`.
129
+ 2. Run lint, typecheck, unit tests, browser tests, and production build.
130
+ 3. Update the Starter package versions.
131
+ 4. Commit `main`, create a release tag such as `v0.2.0`, and publish the Starter release.
132
+
133
+ ### CLI maintainers
134
+
135
+ 1. Change `defaultStarterRef` in [`bin/create.mjs`](bin/create.mjs) to the new tested Starter tag.
136
+ 2. Update the version relationship table and changelog.
137
+ 3. Generate a clean project from that exact tag.
138
+ 4. Run install, lint, typecheck, unit tests, browser tests, production build, and runtime smoke checks.
139
+ 5. Publish a new CLI version only after the generated-project verification passes.
140
+
141
+ The required CI job always tests the pinned default. The scheduled compatibility job tests Starter `main` early, but unreleased Starter changes must not change the stable CLI default.
80
142
 
81
143
  ## Contributing
82
144
 
package/bin/create.mjs CHANGED
@@ -8,8 +8,9 @@ import { basename, dirname, join, resolve } from "node:path";
8
8
  import process from "node:process";
9
9
  import { pathToFileURL } from "node:url";
10
10
 
11
- const starterRepository = "yassine-ahmed/clubedge-starter";
12
- const defaultRef = "main";
11
+ const starterRepository = "Clubedge/clubedge-starter";
12
+ const defaultStarterRef = "v0.1.1";
13
+ const defaultStarterCommit = "0be0c18d41f01cd011c576fb65c25711081b8ad4";
13
14
  const packageVersion = JSON.parse(
14
15
  await readFile(new URL("../package.json", import.meta.url), "utf8"),
15
16
  ).version;
@@ -19,12 +20,14 @@ function showHelp() {
19
20
  create-clubedge-app ${packageVersion}
20
21
 
21
22
  Create a Next.js project from the Clubedge Starter reference repository.
23
+ This CLI release uses Starter ${defaultStarterRef} by default.
24
+ Expected Starter commit: ${defaultStarterCommit}
22
25
 
23
26
  Usage:
24
27
  pnpm dlx @clubedge/create-clubedge-app [project-directory] [options]
25
28
 
26
29
  Options:
27
- --ref <branch-or-tag> Starter branch or tag to scaffold (default: ${defaultRef})
30
+ --ref <ref> Starter tag, branch, or commit to scaffold (default: ${defaultStarterRef})
28
31
  --no-install Skip dependency installation
29
32
  --no-git Skip Git repository initialization
30
33
  -h, --help Show this help
@@ -32,13 +35,16 @@ Options:
32
35
 
33
36
  Examples:
34
37
  pnpm dlx @clubedge/create-clubedge-app my-app
35
- pnpm dlx @clubedge/create-clubedge-app my-app --ref v1.0.0
38
+ pnpm dlx @clubedge/create-clubedge-app my-app --ref <starter-tag-or-commit>
36
39
  pnpm dlx @clubedge/create-clubedge-app my-app --no-install
40
+
41
+ Release model:
42
+ CLI ${packageVersion} -> Starter ${defaultStarterRef}
37
43
  `);
38
44
  }
39
45
 
40
46
  function parseArguments(args) {
41
- const options = { install: true, git: true, ref: defaultRef, projectDirectory: undefined };
47
+ const options = { install: true, git: true, ref: defaultStarterRef, projectDirectory: undefined };
42
48
 
43
49
  for (let index = 0; index < args.length; index += 1) {
44
50
  const argument = args[index];
@@ -121,6 +127,57 @@ async function run(command, args, cwd) {
121
127
  });
122
128
  }
123
129
 
130
+ async function runCapture(command, args, cwd) {
131
+ return await new Promise((resolvePromise, rejectPromise) => {
132
+ const child = spawn(command, args, {
133
+ cwd,
134
+ shell: false,
135
+ stdio: ["ignore", "pipe", "pipe"],
136
+ });
137
+ let stdout = "";
138
+ let stderr = "";
139
+ child.stdout.on("data", (chunk) => {
140
+ stdout += chunk;
141
+ });
142
+ child.stderr.on("data", (chunk) => {
143
+ stderr += chunk;
144
+ });
145
+ child.once("error", rejectPromise);
146
+ child.once("exit", (code, signal) => {
147
+ if (code === 0) {
148
+ resolvePromise(stdout.trim());
149
+ return;
150
+ }
151
+ rejectPromise(
152
+ new Error(
153
+ `${command} exited with ${signal ? `signal ${signal}` : `code ${code}`}${
154
+ stderr.trim() ? `: ${stderr.trim()}` : "."
155
+ }`,
156
+ ),
157
+ );
158
+ });
159
+ });
160
+ }
161
+
162
+ async function verifyDefaultStarterReference(starterRef) {
163
+ if (starterRef !== defaultStarterRef) {
164
+ return;
165
+ }
166
+
167
+ const remote = `https://github.com/${starterRepository}.git`;
168
+ const resolvedReference = await runCapture("git", [
169
+ "ls-remote",
170
+ remote,
171
+ `refs/tags/${starterRef}^{}`,
172
+ ]);
173
+ const resolvedCommit = resolvedReference.split(/\s+/)[0];
174
+ if (resolvedCommit !== defaultStarterCommit) {
175
+ throw new Error(
176
+ `Starter tag ${starterRef} resolved to ${resolvedCommit || "no commit"}, expected ${defaultStarterCommit}.`,
177
+ );
178
+ }
179
+ }
180
+
124
181
  async function ensureTargetIsSafe(directory) {
125
182
  await mkdir(dirname(directory), { recursive: true });
126
183
 
@@ -137,10 +194,21 @@ async function ensureTargetIsSafe(directory) {
137
194
  }
138
195
  }
139
196
 
140
- async function customizeProject(directory, packageName) {
197
+ async function customizeProject(
198
+ directory,
199
+ packageName,
200
+ starterRef = defaultStarterRef,
201
+ starterCommit = starterRef === defaultStarterRef ? defaultStarterCommit : undefined,
202
+ ) {
141
203
  const rootManifestPath = join(directory, "package.json");
142
204
  const rootManifest = JSON.parse(await readFile(rootManifestPath, "utf8"));
143
205
  rootManifest.name = packageName;
206
+ rootManifest.clubedge = {
207
+ cliVersion: packageVersion,
208
+ starterRepository,
209
+ starterRef,
210
+ ...(starterCommit ? { starterCommit } : {}),
211
+ };
144
212
 
145
213
  for (const scriptName of ["docker:build", "docker:start"]) {
146
214
  if (rootManifest.scripts?.[scriptName]) {
@@ -155,7 +223,14 @@ async function customizeProject(directory, packageName) {
155
223
  const readmePath = join(directory, "README.md");
156
224
  const readme = await readFile(readmePath, "utf8");
157
225
  const displayName = displayNameFromPackageName(packageName);
158
- await writeFile(readmePath, readme.replace(/^# Clubedge Starter$/m, `# ${displayName}`));
226
+ const starterCommitLine = starterCommit ? `\n- Starter commit: \`${starterCommit}\`` : "";
227
+ const customizedReadme = readme
228
+ .replace(/^# Clubedge Starter$/m, `# ${displayName}`)
229
+ .replace(
230
+ /^# (.+)$/m,
231
+ `$&\n\n## Generated from\n\n- Starter repository: \`${starterRepository}\`\n- Starter ref: \`${starterRef}\`${starterCommitLine}\n- CLI version: \`${packageVersion}\``,
232
+ );
233
+ await writeFile(readmePath, customizedReadme);
159
234
 
160
235
  const layoutPath = join(directory, "apps", "web", "src", "app", "layout.tsx");
161
236
  const layout = await readFile(layoutPath, "utf8");
@@ -227,12 +302,13 @@ async function createProject(options) {
227
302
  await ensureTargetIsSafe(projectDirectory);
228
303
 
229
304
  const projectName = packageNameFromDirectory(projectDirectory);
305
+ await verifyDefaultStarterReference(options.ref);
230
306
  const source = `gh:${starterRepository}#${options.ref}`;
231
307
  const downloadSpinner = spinner();
232
308
  downloadSpinner.start(`Downloading Clubedge Starter (${options.ref})`);
233
309
  try {
234
310
  await downloadTemplate(source, { dir: projectDirectory, force: true });
235
- await customizeProject(projectDirectory, projectName);
311
+ await customizeProject(projectDirectory, projectName, options.ref);
236
312
  downloadSpinner.stop("Starter files downloaded and configured");
237
313
  } catch (error) {
238
314
  downloadSpinner.stop("Project scaffold failed");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clubedge/create-clubedge-app",
3
- "version": "0.1.3",
3
+ "version": "0.1.9",
4
4
  "description": "Create a Next.js application from the Clubedge Starter reference implementation.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.9.0",
@@ -20,11 +20,11 @@
20
20
  "license": "Apache-2.0",
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "https://github.com/yassine-ahmed/create-clubedge-app.git"
23
+ "url": "https://github.com/Clubedge/create-clubedge-app.git"
24
24
  },
25
- "homepage": "https://github.com/yassine-ahmed/create-clubedge-app#readme",
25
+ "homepage": "https://github.com/Clubedge/create-clubedge-app#readme",
26
26
  "bugs": {
27
- "url": "https://github.com/yassine-ahmed/create-clubedge-app/issues"
27
+ "url": "https://github.com/Clubedge/create-clubedge-app/issues"
28
28
  },
29
29
  "keywords": [
30
30
  "create-clubedge-app",