create-grist-widget 0.2.23 → 0.2.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-grist-widget",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "description": "Scaffold a new Grist custom widget from the grist-widget-sdk Vite template",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,10 +14,12 @@ name: Deploy widget to GitHub Pages
14
14
  # scaffold's own first `git push -u origin main` also creates that ref
15
15
  # for the first time, but is a real user's genuine first release and
16
16
  # must not be skipped -- the web-flow committer check tells the two
17
- # apart.) That skipped run still clears any foreign content the copy
18
- # brought along (stray v<version>/ dirs, a root/latest/ still pointing
19
- # at the source repo's own path) via `cleanup-foreign`, so root/latest/
20
- # aren't left blank until the widget's real first release.
17
+ # apart.) That run still clears any foreign content the copy brought
18
+ # along (stray v<version>/ dirs, a root/latest/ still pointing at the
19
+ # source repo's own path) via `cleanup-foreign`, and places the freshly
20
+ # built showcase hub at the site root via `place-root`, so the bare
21
+ # repo-root URL works immediately instead of 404ing until the widget's
22
+ # real first release. It just never creates a v<version>/ or latest/.
21
23
  # - push to dev -> dev channel: mutable /<repo>/dev/
22
24
  # with version.json + a self-reload snippet, for live review inside Grist.
23
25
  #
@@ -119,8 +121,11 @@ jobs:
119
121
  fs.appendFileSync(out, `firstRelease=${p.firstRelease ? "true" : "false"}\n`);
120
122
  ' "$PLAN"
121
123
 
124
+ # Also builds on the ref-created push (skip == 'true' there), but with
125
+ # the root base plan() hands back for that case (/<repo>/, not a
126
+ # versioned path) -- see the "landing hub" step below.
122
127
  - name: Build
123
- if: steps.plan.outputs.skip != 'true'
128
+ if: steps.plan.outputs.skip != 'true' || steps.plan.outputs.reason == 'ref-created'
124
129
  run: |
125
130
  pnpm exec tsc -b
126
131
  pnpm exec vite build --base "${{ steps.plan.outputs.base }}"
@@ -141,15 +146,24 @@ jobs:
141
146
  if: steps.plan.outputs.skip == 'true' && steps.plan.outputs.reason != 'ref-created'
142
147
  run: echo "== skip — v${{ steps.plan.outputs.version }} already published"
143
148
 
144
- # The ref-created push never reaches Build/Place, so it's the only
145
- # path where cleanupForeignVersionsIfFirstRelease (normally a side
146
- # effect of Place) needs to run standalone -- otherwise foreign
147
- # content from "Use this template" (stray v<version>/ dirs, a
148
- # root/latest/ pointing at the source repo's own path) sits untouched
149
- # until the widget's real first release.
150
- - name: Clean foreign content (ref-created push published nothing)
149
+ # The ref-created "Use this template" push publishes no versioned
150
+ # release (that would spend the first-release override on unmodified
151
+ # boilerplate -- see plan()), so it never reaches Place. But it still:
152
+ # 1. clears any foreign content the copy brought along
153
+ # (cleanupForeignVersionsIfFirstRelease, normally a side effect of
154
+ # Place) -- stray v<version>/ dirs, a root/latest/ pointing at the
155
+ # source repo's own path; then
156
+ # 2. places the freshly built showcase hub at the site root, so
157
+ # https://owner.github.io/<repo>/ isn't a bare 404 until the
158
+ # widget's first real release (the CLI path gets a working root on
159
+ # its own genuine first push; this makes the template-copy path
160
+ # match). No v<version>/ or latest/ -- those stay absent, correctly
161
+ # 404ing, until a real release exists.
162
+ - name: Clean foreign content + place landing hub (ref-created push)
151
163
  if: steps.plan.outputs.reason == 'ref-created'
152
- run: node scripts/deploy.mjs cleanup-foreign --site site --repo "$REPO_NAME"
164
+ run: |
165
+ node scripts/deploy.mjs cleanup-foreign --site site --repo "$REPO_NAME"
166
+ node scripts/deploy.mjs place-root --site site --dist dist
153
167
 
154
168
  - name: Finalize (versions.json + commit + push)
155
169
  run: |
@@ -115,14 +115,17 @@ automatically.
115
115
  > "Use this template" also immediately fires this workflow once on its own,
116
116
  > the moment the repo is created — before you've cloned it, let alone
117
117
  > changed anything. That run is recognized (GitHub's own web-flow bot
118
- > creating the `main` ref) and skipped entirely: nothing gets published,
119
- > and it doesn't count as your first release, so the `0.0.1` override above
120
- > still applies in full once you actually push real changes. If you also
121
- > checked "Include all branches", that same skipped run still clears out
122
- > whatever foreign content came along with it — stray `v<version>/` dirs,
123
- > and a root/`latest/` still pointing at the *source* repo's own path
124
- > (which would otherwise render blank until your real first release) —
125
- > without needing to publish anything of its own to do so.
118
+ > creating the `main` ref) and **publishes no versioned release**: it
119
+ > doesn't count as your first release, so the `0.0.1` override above still
120
+ > applies in full once you actually push real changes. It does two useful
121
+ > things, though: if you checked "Include all branches", it clears out
122
+ > whatever foreign content came along (stray `v<version>/` dirs, a
123
+ > root/`latest/` still pointing at the *source* repo's own path); and it
124
+ > places the landing page at your repo-root URL so
125
+ > `https://<you>.github.io/<repo>/` works right away, instead of 404ing
126
+ > until your first real release. Your `/latest/` and `/v<version>/` URLs
127
+ > stay absent (they 404) until you actually publish — there's no release to
128
+ > point them at yet.
126
129
 
127
130
  **One-time setup** (the workflow can't do this part for you):
128
131
 
@@ -40,6 +40,12 @@
40
40
  // `place` (the only other caller of this cleanup) so foreign content
41
41
  // from "Use this template" would otherwise sit untouched indefinitely.
42
42
  //
43
+ // place-root --site <dir> --dist <dir>
44
+ // Place a root-based build (built with base "/<repo>/") at the site
45
+ // root only -- the showcase hub landing page. Used on the ref-created
46
+ // push so the bare repo-root URL works before the first real release,
47
+ // without publishing a versioned release. Run after `cleanup-foreign`.
48
+ //
43
49
  // remove --site <dir>
44
50
  // Removes dev/ from the gh-pages tree (retire the dev URL when the `dev`
45
51
  // branch is deleted). Never touches a release or latest/.
@@ -143,10 +149,21 @@ export function plan(siteDir, repo, event, ref, { force = false, created = false
143
149
  // gh-pages) keeps hasGenuineRelease() false, so the override survives
144
150
  // intact for whenever a real release actually happens.
145
151
  if (created && event === "push") {
152
+ // Publish no versioned release (so the first-release override above
153
+ // survives), but the caller still builds + places the showcase hub at
154
+ // the site root -- otherwise https://owner.github.io/<repo>/ is a bare
155
+ // 404 until the widget's first real release (found live on a fresh "Use
156
+ // this template" copy). The hub renders for any URL with no channel
157
+ // suffix, the bare root included (see main.tsx), so it must be built
158
+ // based at the repo root (/<repo>/), not a versioned path -- hence the
159
+ // root base here rather than basePathFor's v<version>/. The workflow
160
+ // keys off reason === "ref-created" to build with this base and place
161
+ // root-only. `skip` stays true so the normal versioned place/finalize
162
+ // path is bypassed.
146
163
  return {
147
164
  context: "release",
148
165
  version,
149
- base: basePathFor(repo, "release", version),
166
+ base: `/${repo}/`,
150
167
  skip: true,
151
168
  reason: "ref-created",
152
169
  firstRelease,
@@ -313,6 +330,27 @@ export function placeTarget({ siteDir, channel, version, distDir, sha, ref, repo
313
330
  return { placed: `v${version}`, latest: "latest", root: true }
314
331
  }
315
332
 
333
+ /**
334
+ * Place a root-based build (built with base "/<repo>/") at the gh-pages site
335
+ * root only -- the showcase hub landing page, nothing else. Used on the
336
+ * ref-created "Use this template" push (see plan()): publishes no versioned
337
+ * release, so the first-release override survives, but keeps the bare
338
+ * repo-root URL from 404ing until that first real release (found live: a
339
+ * fresh copy's https://owner.github.io/<repo>/ was a 404, since the initial
340
+ * deploy that used to place this hub now publishes nothing). Never creates a
341
+ * v<version>/ or latest/. On the first genuine release, placeTarget's own
342
+ * cleanupForeignVersionsIfFirstRelease clears this hub (root index.html +
343
+ * assets/) before placing the release's own root copy, so nothing lingers.
344
+ * Callers run `cleanup-foreign` first, so a re-triggered ref-created run
345
+ * replaces the hub cleanly rather than layering onto stale files.
346
+ */
347
+ export function placeRootHub({ siteDir, distDir }) {
348
+ if (!existsSync(distDir)) throw new Error(`dist not found: ${distDir}`)
349
+ mkdirSync(siteDir, { recursive: true })
350
+ cpSync(distDir, siteDir, { recursive: true })
351
+ return { placed: "root" }
352
+ }
353
+
316
354
  /**
317
355
  * Remove the mutable dev dir from the gh-pages tree (retire the dev URL when
318
356
  * the `dev` branch is deleted). Only ever touches `dev/` — never a versioned
@@ -453,6 +491,11 @@ function main() {
453
491
  console.log("cleanup-foreign:", JSON.stringify(res))
454
492
  break
455
493
  }
494
+ case "place-root": {
495
+ const res = placeRootHub({ siteDir: args.site, distDir: args.dist })
496
+ console.log("place-root:", JSON.stringify(res))
497
+ break
498
+ }
456
499
  case "finalize": {
457
500
  const res = finalize({
458
501
  siteDir: args.site,