shiply-cli 0.26.0 → 0.26.1

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/dist/framework.js CHANGED
@@ -8,9 +8,14 @@ const SSG_SIGNATURES = [
8
8
  { files: ['mkdocs.yml', 'mkdocs.yaml'], framework: 'MkDocs', outputDir: 'site', buildCommand: 'mkdocs build' },
9
9
  ];
10
10
  async function detectStaticSiteGenerator(dir) {
11
+ // Check every signature file in parallel, then pick the first match in the
12
+ // original priority order — same result as the serial version, faster I/O.
13
+ const flatFiles = SSG_SIGNATURES.flatMap((sig) => sig.files);
14
+ const hits = await Promise.all(flatFiles.map((f) => exists(join(dir, f))));
15
+ let i = 0;
11
16
  for (const sig of SSG_SIGNATURES) {
12
17
  for (const f of sig.files) {
13
- if (await exists(join(dir, f))) {
18
+ if (hits[i++]) {
14
19
  return { framework: sig.framework, outputDir: sig.outputDir, spa: false, buildCommand: sig.buildCommand };
15
20
  }
16
21
  }
package/dist/publish.js CHANGED
@@ -132,8 +132,14 @@ async function uploadAll(dir, targets) {
132
132
  const t = targets[next++];
133
133
  const body = await readFile(join(dir, t.path));
134
134
  const res = await fetchWithRetry(t.url, { method: t.method, headers: t.headers, body }, { label: `upload ${t.path}` });
135
- if (!res.ok)
135
+ if (!res.ok) {
136
+ if (res.status === 403) {
137
+ throw new Error(`upload failed for ${t.path}: HTTP 403 — presigned URLs likely expired ` +
138
+ `(they're short-lived). Re-run \`shiply publish\` to mint fresh ones — ` +
139
+ `unchanged files are hash-skipped, so the retry is cheap.`);
140
+ }
136
141
  throw new Error(`upload failed for ${t.path}: HTTP ${res.status}`);
142
+ }
137
143
  }
138
144
  };
139
145
  await Promise.all(Array.from({ length: Math.min(CONCURRENCY, targets.length) }, worker));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shiply-cli",
3
- "version": "0.26.0",
3
+ "version": "0.26.1",
4
4
  "description": "Publish static sites to shiply.now from the command line \u00e2\u20ac\u201d instant web hosting for agents.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -6,6 +6,17 @@ entry here, that capability may be missing from your copy — re-install with
6
6
  (This is the agent-facing capability log; the CLI's own release notes live in
7
7
  the npm package changelog.)
8
8
 
9
+ ## 2026-07-08
10
+
11
+ - **Fix** — re-publishing an unchanged large SSR site (e.g. a 171-file
12
+ Next.js build) used to take 6+ minutes (serial hash-skip HEAD checks, a
13
+ serial worker-bundle re-read/re-upload even with no changes, plus a
14
+ finalize retry after a client-side timeout). Finalize is now: concurrent
15
+ hash-skip checks, a fingerprinted worker-bundle deploy that's skipped
16
+ entirely when nothing changed, and an idempotent replay on retry. A
17
+ zero-change publish now finishes in seconds. No action needed — always
18
+ re-publish to the same site (slug/claimToken); it's cheap.
19
+
9
20
  ## 2026-07-07
10
21
 
11
22
  - **Fix** — custom domains attached to SSR/function sites no longer 404: the
package/skill/SKILL.md CHANGED
@@ -13,7 +13,7 @@ description: "shiply is the production backend for anything an agent builds —
13
13
  > the npm package name.
14
14
 
15
15
  > **Skill freshness check.** Shiply ships new capabilities weekly.
16
- > **This skill: version 0.25.0, last updated 2026-07-04.**
16
+ > **This skill: version 0.25.0, last updated 2026-07-08.**
17
17
  > To see what changed since your copy was written, fetch
18
18
  > `https://shiply.now/changelog.md` (date-grouped, newest first) — if it lists
19
19
  > capabilities newer than the date above, re-install with
@@ -31,7 +31,14 @@ description: "shiply is the production backend for anything an agent builds —
31
31
  **How (quickstart).** `shiply publish ./dir` (CLI) — or POST /api/v1/publish → PUT each file → POST finalize — returns a live URL + claimToken.
32
32
 
33
33
  **NEVER create a new site to update an existing one. Always re-publish to the
34
- same site** — otherwise you litter subdomains and lose the user's URL.
34
+ same site** (same slug/claimToken) — otherwise you litter subdomains and lose
35
+ the user's URL.
36
+
37
+ **Re-publishing the same site is cheap — always prefer it over a new site.**
38
+ Unchanged files are hash-skipped, and an unchanged SSR worker bundle skips
39
+ redeploy entirely (fingerprinted against what's already live). A zero-change
40
+ `shiply publish` on the same site completes in seconds, even for large SSR
41
+ apps — so iterate freely by re-publishing, never by spinning up a fresh site.
35
42
 
36
43
  This file covers the core path: publish → authorize → update → claim → verify.
37
44
  Everything else (databases, domains, SSR, email, functions, client work) lives