create-grist-widget 0.2.13 → 0.2.14

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.13",
3
+ "version": "0.2.14",
4
4
  "description": "Scaffold a new Grist custom widget from the grist-widget-sdk Vite template",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -125,10 +125,14 @@ jobs:
125
125
  if: steps.plan.outputs.skip == 'true'
126
126
  run: echo "== skip — v${{ steps.plan.outputs.version }} already published"
127
127
 
128
- - name: Finalize (commit + push)
128
+ - name: Finalize (versions.json + commit + push)
129
129
  run: |
130
+ UPDATE_VERSIONS=""
131
+ if [ "${{ steps.plan.outputs.context }}" = "release" ]; then
132
+ UPDATE_VERSIONS="--update-versions"
133
+ fi
130
134
  node scripts/deploy.mjs finalize \
131
- --site site --push \
135
+ --site site $UPDATE_VERSIONS --push \
132
136
  --commit-message "deploy: ${{ steps.plan.outputs.context }} @ ${{ github.sha }}"
133
137
 
134
138
  cleanup:
@@ -8,6 +8,8 @@
8
8
  // release (push to main / workflow_dispatch)
9
9
  // - immutable /<repo>/v<version>/ (built once, never overwritten)
10
10
  // - mutable /<repo>/latest/ (alias to newest release)
11
+ // - /<repo>/versions.json (released-version index, newest first
12
+ // -- read by the showcase hub/notice)
11
13
  //
12
14
  // dev (push to dev)
13
15
  // - mutable /<repo>/dev/ (+ version.json + self-reload)
@@ -30,10 +32,19 @@
30
32
  // Removes dev/ from the gh-pages tree (retire the dev URL when the `dev`
31
33
  // branch is deleted). Never touches a release or latest/.
32
34
  //
33
- // finalize --site <dir> [--push] [--commit-message <msg>]
34
- // Commits + pushes the gh-pages tree with a rebase-and-retry loop.
35
+ // finalize --site <dir> [--update-versions] [--push] [--commit-message <msg>]
36
+ // Regenerates versions.json (release runs only) and commits + pushes the
37
+ // gh-pages tree with a rebase-and-retry loop.
35
38
 
36
- import { existsSync, readFileSync, writeFileSync, rmSync, mkdirSync, cpSync } from "node:fs"
39
+ import {
40
+ existsSync,
41
+ readFileSync,
42
+ readdirSync,
43
+ writeFileSync,
44
+ rmSync,
45
+ mkdirSync,
46
+ cpSync,
47
+ } from "node:fs"
37
48
  import { join, dirname } from "node:path"
38
49
  import { execFileSync } from "node:child_process"
39
50
 
@@ -107,6 +118,28 @@ export function injectSelfReload(html, sha) {
107
118
  return out + snippet
108
119
  }
109
120
 
121
+ /**
122
+ * Scan siteDir for previously-released v<version>/showcase-meta.json files
123
+ * and assemble the versions.json manifest, newest first. Read by the
124
+ * showcase hub (TemplateLanding) and per-channel notice (ChannelNotice) to
125
+ * show this widget's own release history -- not the grist-widget-sdk
126
+ * monorepo's (found live: every scaffolded widget's version index showed
127
+ * the monorepo's versions instead of its own, since showcase-versions.ts
128
+ * used to hardcode that URL).
129
+ */
130
+ export function buildVersionsManifest(siteDir) {
131
+ const entries = []
132
+ for (const name of existsSync(siteDir) ? readdirSync(siteDir) : []) {
133
+ if (!/^v\d+\.\d+\.\d+/.test(name)) continue
134
+ const metaPath = join(siteDir, name, "showcase-meta.json")
135
+ if (!existsSync(metaPath)) continue
136
+ const meta = JSON.parse(readFileSync(metaPath, "utf8"))
137
+ entries.push({ version: meta.version, publishedAt: meta.publishedAt })
138
+ }
139
+ entries.sort((a, b) => new Date(b.publishedAt) - new Date(a.publishedAt))
140
+ return entries
141
+ }
142
+
110
143
  // ----------------------------------------------------------------------------
111
144
  // Filesystem / git effects
112
145
  // ----------------------------------------------------------------------------
@@ -144,6 +177,10 @@ export function placeTarget({ siteDir, channel, version, distDir, sha, ref }) {
144
177
  // so nothing 404s.
145
178
  const versionDir = join(siteDir, `v${version}`)
146
179
  replaceDir(versionDir, distDir)
180
+ writeFileSync(
181
+ join(versionDir, "showcase-meta.json"),
182
+ JSON.stringify({ version, publishedAt: new Date().toISOString(), sha }, null, 2) + "\n",
183
+ )
147
184
  const latestDir = join(siteDir, "latest")
148
185
  replaceDir(latestDir, distDir)
149
186
  mkdirSync(siteDir, { recursive: true })
@@ -173,8 +210,12 @@ function sleep(ms) {
173
210
  while (Date.now() < end) {}
174
211
  }
175
212
 
176
- /** Commit + push the gh-pages tree with a rebase-and-retry loop. */
177
- export function finalize({ siteDir, push, commitMessage, remoteBranch = "gh-pages" }) {
213
+ /** Regenerate versions.json (release runs only), then commit + push with rebase-retry. */
214
+ export function finalize({ siteDir, updateVersions, push, commitMessage, remoteBranch = "gh-pages" }) {
215
+ if (updateVersions) {
216
+ const versions = buildVersionsManifest(siteDir)
217
+ writeFileSync(join(siteDir, "versions.json"), JSON.stringify(versions, null, 2) + "\n")
218
+ }
178
219
  git(["add", "-A"], siteDir)
179
220
  const status = git(["status", "--porcelain"], siteDir)
180
221
  if (!status) {
@@ -253,6 +294,7 @@ function main() {
253
294
  case "finalize": {
254
295
  const res = finalize({
255
296
  siteDir: args.site,
297
+ updateVersions: !!args["update-versions"],
256
298
  push: !!args.push,
257
299
  commitMessage: args["commit-message"],
258
300
  })
@@ -10,7 +10,7 @@ import {
10
10
  } from "@/components/ui/card"
11
11
  import { Input } from "@/components/ui/input"
12
12
  import { channelLabel, type Channel } from "@/lib/showcase-routing"
13
- import { DEV_URL, useVersions, versionUrl } from "@/lib/showcase-versions"
13
+ import { devUrl, useVersions, versionUrl } from "@/lib/showcase-versions"
14
14
  import { cn } from "@/lib/utils"
15
15
 
16
16
  // Shown instead of the widget tree on a specific channel build
@@ -44,7 +44,7 @@ function VersionChips({ current }: { current: Channel }) {
44
44
  latest
45
45
  </a>
46
46
  )}
47
- <a href={DEV_URL} className={chipClass(current.kind === "dev")}>
47
+ <a href={devUrl()} className={chipClass(current.kind === "dev")}>
48
48
  dev
49
49
  </a>
50
50
  {versions?.map((v) => (
@@ -2,7 +2,7 @@ import { useState } from "react"
2
2
 
3
3
  import { Button } from "@/components/ui/button"
4
4
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
5
- import { DEV_URL, formatDate, useVersions, versionUrl } from "@/lib/showcase-versions"
5
+ import { devUrl, formatDate, useVersions, versionUrl } from "@/lib/showcase-versions"
6
6
 
7
7
  // The showcase "hub" page: rendered whenever this deploy's URL has no
8
8
  // recognized channel suffix (see src/lib/showcase-routing.ts) -- this repo's
@@ -178,7 +178,7 @@ git push origin dev`}</code>
178
178
  Released template versions
179
179
  </h2>
180
180
  <a
181
- href={DEV_URL}
181
+ href={devUrl()}
182
182
  className="text-sm text-muted-foreground underline underline-offset-4 hover:text-foreground"
183
183
  >
184
184
  Live dev preview →
@@ -1,21 +1,35 @@
1
1
  import { useEffect, useState } from "react"
2
2
 
3
+ import { parseShowcasePath } from "@/lib/showcase-routing"
4
+
3
5
  // Shared by the showcase hub (TemplateLanding) and the per-channel notice
4
- // (ChannelNotice) -- both need the same released-version list, fetched from
5
- // a fixed absolute URL rather than a path relative to wherever this happens
6
- // to be deployed (see src/components/template-landing.tsx for why).
7
- export const VERSIONS_URL =
8
- "https://arthurblanchon.github.io/grist-widget-sdk/template/versions.json"
9
- export const DEV_URL = "https://arthurblanchon.github.io/grist-widget-sdk/template/dev/"
10
- export const HUB_URL = "https://arthurblanchon.github.io/grist-widget-sdk/template/"
6
+ // (ChannelNotice) -- both need the same released-version list. URLs are
7
+ // root-relative to wherever THIS deploy actually lives (derived from
8
+ // window.location.pathname via parseShowcasePath's hubPath), not hardcoded
9
+ // to the grist-widget-sdk monorepo's own showcase: a real scaffolded
10
+ // widget has its own versions.json and its own v<version>/ + dev/ dirs,
11
+ // and previously showed the monorepo's version history and links instead
12
+ // of its own (found live on a real scaffold's landing page).
13
+ function hubPath(): string {
14
+ const path = parseShowcasePath(window.location.pathname).hubPath
15
+ return path.endsWith("/") ? path : `${path}/`
16
+ }
11
17
 
12
18
  export type ReleasedVersion = {
13
19
  version: string
14
20
  publishedAt: string
15
21
  }
16
22
 
23
+ export function versionsUrl(): string {
24
+ return `${hubPath()}versions.json`
25
+ }
26
+
27
+ export function devUrl(): string {
28
+ return `${hubPath()}dev/`
29
+ }
30
+
17
31
  export function versionUrl(version: string): string {
18
- return `https://arthurblanchon.github.io/grist-widget-sdk/template/v${version}/`
32
+ return `${hubPath()}v${version}/`
19
33
  }
20
34
 
21
35
  export function useVersions() {
@@ -24,7 +38,7 @@ export function useVersions() {
24
38
 
25
39
  useEffect(() => {
26
40
  let cancelled = false
27
- fetch(VERSIONS_URL, { cache: "no-store" })
41
+ fetch(versionsUrl(), { cache: "no-store" })
28
42
  .then((res) => (res.ok ? res.json() : Promise.reject(res)))
29
43
  .then((data: ReleasedVersion[]) => {
30
44
  if (!cancelled) setVersions(data)