uniweb 0.12.7 → 0.12.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniweb",
3
- "version": "0.12.7",
3
+ "version": "0.12.9",
4
4
  "description": "Create structured Vite + React sites with content/code separation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,12 +41,12 @@
41
41
  "js-yaml": "^4.1.0",
42
42
  "prompts": "^2.4.2",
43
43
  "tar": "^7.0.0",
44
- "@uniweb/core": "0.7.10",
45
44
  "@uniweb/kit": "0.9.10",
46
- "@uniweb/runtime": "0.8.11"
45
+ "@uniweb/runtime": "0.8.11",
46
+ "@uniweb/core": "0.7.10"
47
47
  },
48
48
  "peerDependencies": {
49
- "@uniweb/build": "0.13.4",
49
+ "@uniweb/build": "0.14.1",
50
50
  "@uniweb/semantic-parser": "1.1.17",
51
51
  "@uniweb/content-reader": "1.1.10"
52
52
  },
@@ -165,10 +165,15 @@ The `uniweb` block in `package.json` carries platform-specific configuration tha
165
165
 
166
166
  | Field | Where used | Default | Purpose |
167
167
  |---|---|---|---|
168
- | `id` | `uniweb publish` | (set on first publish via the prompt, or via `--name`) | The foundation's published id — the bare-name segment in `~handle/<id>` or `@org/<id>`. Decoupled from `package.json::name` (a workspace concern), so renaming the foundation on the registry doesn't ripple through site dependencies. |
168
+ | `id` | `uniweb publish` | (set via `--name` or scoped `package.json::name`) | The foundation's published id — the bare-name segment in `@org/<id>`. Decoupled from `package.json::name` (a workspace concern), so renaming the foundation on the registry doesn't ripple through site dependencies. Only relevant for catalog-published foundations; site-bound foundations skip this. |
169
169
  | `namespace` | `uniweb publish` | (none — see scope resolution) | Legacy explicit org-namespace override. Equivalent to using a scoped `package.json::name` (`"@myorg/foundation"`). Rarely needed in modern foundations. |
170
170
  | `runtimePolicy` | `dist/runtime-pin.json` (foundation build) | `"auto-minor"` | Controls how sites using this foundation receive runtime updates. Three values: `"exact"`, `"auto-patch"`, `"auto-minor"`. See "Foundation runtime policy" below. |
171
171
 
172
+ **Catalog vs site-bound foundations.** Two distribution intents share the same `dist/foundation.js` artifact:
173
+
174
+ - A **catalog foundation** is a deliberate product — named, versioned, listed in the catalog, consumable by other developers' sites. Use `uniweb publish @org/name` for these. The CLI requires an explicit name argument so you don't accidentally catalog a foundation that was meant to be site-bound.
175
+ - A **site-bound foundation** powers exactly one site. Don't run `uniweb publish` for it. Just run `uniweb deploy` from the site directory — the CLI auto-publishes your local foundation as part of the deploy, under a registry slot scoped to the site itself, with no naming ceremony. The foundation isn't visible in the catalog and isn't owned by the developer who happened to run the deploy.
176
+
172
177
  **On the split between `package.json::name` and `uniweb.id`:** the workspace name is what pnpm uses for `file:` linking and what `site.yml::foundation` references. The published id is what the registry stores. Keeping them separate means renaming on the registry (e.g. `marketing` → `marketing-pro`) is a one-shot `uniweb publish --name marketing-pro` — it persists to `uniweb.id` without touching the workspace.
173
178
 
174
179
  These are the only fields the platform consumes today. Future platform features that need static configuration will land here too.
@@ -1,33 +1,46 @@
1
1
  /**
2
2
  * Build Command
3
3
  *
4
- * Builds foundations with schema generation, or sites in either link or
5
- * bundle mode.
4
+ * Builds foundations with schema generation, or sites.
6
5
  *
7
- * Site build modes:
8
- * --bundle (default for sites)
6
+ * Two site build pipelines are available, but they're INTERNAL vocabulary
7
+ * after Phase 2 of the CLI ergonomics overhaul. Users see `uniweb deploy`
8
+ * (uniweb-edge — runtime-linked) and `uniweb export` (third-party host —
9
+ * concatenated bundle); the build command itself just dispatches to whichever
10
+ * pipeline the caller requested.
11
+ *
12
+ * --bundle (internal; called by `uniweb export`)
9
13
  * Full vite + post-vite pipeline. Produces a static-host JS bundle
10
14
  * (`dist/index.html`, `dist/entry.js`, `_importmap/*`, `_pages/*` for
11
15
  * split mode, sitemap/robots/search-index, prerendered HTML when
12
- * configured). Targets non-Uniweb hosts (Netlify, Vercel, GitHub
13
- * Pages) and the future Uniweb bundled-mode hosting.
16
+ * configured). Foundation is loaded by URL when site.yml's foundation
17
+ * is a registry ref; statically inlined when it's a workspace-local
18
+ * ref with no auto-publish (the narrow self-contained case).
14
19
  *
15
- * --link
20
+ * --link (internal; called by `uniweb deploy`)
16
21
  * Data-only pipeline. No vite. Emits ONLY what the Uniweb-edge
17
22
  * deploy needs: `dist/site-content.json` (with full sections),
18
23
  * `dist/<lang>/site-content.json` per non-default locale,
19
24
  * `dist/data/*.json` (collections), and `dist/assets/<media>` (images,
20
- * fonts, video posters). Worker generates HTML at request time using
21
- * its own runtime + the foundation served from the registry the
22
- * site's JS bundle is dead weight on this path.
25
+ * fonts, video posters). Edge stitches runtime + foundation per
26
+ * request the site's JS bundle would be dead weight.
27
+ *
28
+ * Bare `uniweb build` for a site defaults to --bundle (the historical
29
+ * behavior). This is mostly useful for inspecting the build output during
30
+ * development; for shipping, use `uniweb deploy` or `uniweb export`.
23
31
  *
24
32
  * Usage:
25
33
  * uniweb build # Build current directory (sites default to --bundle)
26
34
  * uniweb build --target foundation # Explicitly build as foundation
27
35
  * uniweb build --target site # Explicitly build as site
28
- * uniweb build --link # Site: link-mode (data only, no vite)
29
- * uniweb build --bundle # Site: bundle-mode (full pipeline, today's behavior)
30
- * uniweb build --prerender # Bundle-mode site + SSG (static HTML)
36
+ * uniweb build --prerender # Force pre-rendering
37
+ * uniweb build --no-prerender # Skip pre-rendering
38
+ * uniweb build --host <name> # Override site.yml deploy.host (e.g.
39
+ * netlify, s3-cloudfront, generic-static)
40
+ *
41
+ * Internal flags (called by `uniweb deploy` / `uniweb export`):
42
+ * --link # Data-only pipeline (Uniweb-edge)
43
+ * --bundle # Full vite pipeline (third-party hosts)
31
44
  */
32
45
 
33
46
  import { existsSync, readFileSync } from 'node:fs'
@@ -476,11 +489,11 @@ async function buildSiteLink(projectDir, options = {}) {
476
489
  success(`Translated collections for ${Object.keys(collectionOutputs).length} locale(s)`)
477
490
  }
478
491
  } catch (err) {
479
- if (process.env.DEBUG) console.error('Collection translation:', err.message)
492
+ if (process.env.UNIWEB_DEBUG) console.error('Collection translation:', err.message)
480
493
  }
481
494
  } catch (err) {
482
495
  error(`i18n build failed: ${err.message}`)
483
- if (process.env.DEBUG) console.error(err.stack)
496
+ if (process.env.UNIWEB_DEBUG) console.error(err.stack)
484
497
  log(`${colors.yellow}Continuing without localized content${colors.reset}`)
485
498
  }
486
499
  }
@@ -529,7 +542,7 @@ async function resolveFoundationDirForSite(siteDir, siteConfig) {
529
542
  * Build a site
530
543
  */
531
544
  async function buildSite(projectDir, options = {}) {
532
- const { prerender = false, foundationDir, siteConfig = null } = options
545
+ const { prerender = false, foundationDir, siteConfig = null, host = null } = options
533
546
 
534
547
  info('Building site...')
535
548
 
@@ -578,13 +591,13 @@ async function buildSite(projectDir, options = {}) {
578
591
  }
579
592
  } catch (err) {
580
593
  // Collection translation is optional, don't fail build
581
- if (process.env.DEBUG) {
594
+ if (process.env.UNIWEB_DEBUG) {
582
595
  console.error('Collection translation:', err.message)
583
596
  }
584
597
  }
585
598
  } catch (err) {
586
599
  error(`i18n build failed: ${err.message}`)
587
- if (process.env.DEBUG) {
600
+ if (process.env.UNIWEB_DEBUG) {
588
601
  console.error(err.stack)
589
602
  }
590
603
  // Don't fail the build, just warn
@@ -602,6 +615,7 @@ async function buildSite(projectDir, options = {}) {
602
615
 
603
616
  const result = await prerenderSite(projectDir, {
604
617
  foundationDir: foundationDir || resolveFoundationDir(projectDir, siteConfig),
618
+ host,
605
619
  onProgress: (msg) => log(` ${colors.dim}${msg}${colors.reset}`)
606
620
  })
607
621
 
@@ -632,7 +646,7 @@ async function buildSite(projectDir, options = {}) {
632
646
  log(` • The foundation's dist/foundation.js exists (build the foundation first)`)
633
647
  }
634
648
 
635
- if (process.env.DEBUG) {
649
+ if (process.env.UNIWEB_DEBUG) {
636
650
  console.error(err.stack)
637
651
  }
638
652
  process.exit(1)
@@ -699,7 +713,7 @@ async function discoverWorkspacePackages(workspaceDir) {
699
713
  * Build all packages in a workspace
700
714
  */
701
715
  async function buildWorkspace(workspaceDir, options = {}) {
702
- const { prerenderFlag, noPrerenderFlag } = options
716
+ const { prerenderFlag, noPrerenderFlag, host = null } = options
703
717
 
704
718
  log(`${colors.cyan}${colors.bright}Building workspace...${colors.reset}`)
705
719
  log('')
@@ -746,7 +760,7 @@ async function buildWorkspace(workspaceDir, options = {}) {
746
760
  // Resolve foundation directory for this site
747
761
  const foundationDir = resolveFoundationDir(site.path, siteConfig)
748
762
 
749
- await buildSite(site.path, { prerender, foundationDir, siteConfig })
763
+ await buildSite(site.path, { prerender, foundationDir, siteConfig, host })
750
764
  log('')
751
765
  }
752
766
 
@@ -804,13 +818,12 @@ export async function build(args = []) {
804
818
  const prerenderFlag = args.includes('--prerender')
805
819
  const noPrerenderFlag = args.includes('--no-prerender')
806
820
 
807
- // Check for --link / --bundle flags. These select between two
808
- // mutually exclusive site build pipelines:
809
- // --link: data only, no vite (for Uniweb-edge hosting)
810
- // --bundle: full vite pipeline (for static hosts; today's behavior)
811
- // Bare `uniweb build` for a site defaults to --bundle for back-compat
812
- // with users targeting static hosts. `uniweb deploy` always passes one
813
- // of the two explicitly based on the resolved deploy mode.
821
+ // Internal flags called by `uniweb deploy` (always --link) and
822
+ // `uniweb export` (always --bundle). After Phase 2 of the CLI
823
+ // ergonomics overhaul, users don't see these flags directly; they
824
+ // pick the deploy target (deploy vs export) and the corresponding
825
+ // pipeline runs. Bare `uniweb build` for a site defaults to --bundle
826
+ // (mostly used during development to inspect the vite output).
814
827
  const linkFlag = args.includes('--link')
815
828
  const bundleFlag = args.includes('--bundle')
816
829
  if (linkFlag && bundleFlag) {
@@ -825,6 +838,14 @@ export async function build(args = []) {
825
838
  foundationDir = resolve(args[foundationDirIndex + 1])
826
839
  }
827
840
 
841
+ // --host overrides site.yml's deploy.host for this build's prerender
842
+ // step. Validated lazily (inside prerender.js, via the registry).
843
+ let host = null
844
+ const hostIndex = args.indexOf('--host')
845
+ if (hostIndex !== -1 && args[hostIndex + 1]) {
846
+ host = args[hostIndex + 1]
847
+ }
848
+
828
849
  // Auto-detect project type if not specified
829
850
  if (!targetType) {
830
851
  targetType = detectProjectType(projectDir)
@@ -858,7 +879,7 @@ export async function build(args = []) {
858
879
  // Run appropriate build
859
880
  try {
860
881
  if (targetType === 'workspace') {
861
- await buildWorkspace(projectDir, { prerenderFlag, noPrerenderFlag })
882
+ await buildWorkspace(projectDir, { prerenderFlag, noPrerenderFlag, host })
862
883
  } else if (targetType === 'foundation') {
863
884
  await buildFoundation(projectDir)
864
885
  } else {
@@ -888,7 +909,7 @@ export async function build(args = []) {
888
909
  if (prerenderFlag) prerender = true
889
910
  if (noPrerenderFlag) prerender = false
890
911
 
891
- await buildSite(projectDir, { prerender, foundationDir, siteConfig })
912
+ await buildSite(projectDir, { prerender, foundationDir, siteConfig, host })
892
913
  }
893
914
  } catch (err) {
894
915
  error(err.message)