uniweb 1.0.0 → 1.0.2
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/LICENSE +201 -0
- package/README.md +532 -3
- package/package.json +60 -11
- package/partials/adding-pages.hbs +77 -0
- package/partials/agents.md +3000 -0
- package/partials/ai-assistance.hbs +28 -0
- package/partials/components-docs.hbs +13 -0
- package/partials/config-reference.hbs +66 -0
- package/partials/deployment.hbs +13 -0
- package/partials/learn-more.hbs +6 -0
- package/partials/quick-start.hbs +8 -0
- package/partials/search-docs.hbs +110 -0
- package/src/backend/asset-download.js +222 -0
- package/src/backend/client.js +986 -0
- package/src/backend/foundation-bring-along.js +692 -0
- package/src/backend/payment-handoff.js +362 -0
- package/src/backend/service-request.js +210 -0
- package/src/backend/site-media.js +255 -0
- package/src/backend/site-preview.js +77 -0
- package/src/backend/site-sync.js +2515 -0
- package/src/backend/workspace.js +234 -0
- package/src/commands/add.js +1900 -0
- package/src/commands/build.js +1214 -0
- package/src/commands/clone.js +466 -0
- package/src/commands/content.js +202 -0
- package/src/commands/deploy.js +537 -0
- package/src/commands/dev.js +202 -0
- package/src/commands/docs.js +530 -0
- package/src/commands/doctor.js +1982 -0
- package/src/commands/export.js +116 -0
- package/src/commands/families.js +82 -0
- package/src/commands/forget.js +197 -0
- package/src/commands/handoff.js +21 -0
- package/src/commands/i18n.js +1707 -0
- package/src/commands/inspect.js +375 -0
- package/src/commands/invite.js +24 -0
- package/src/commands/org.js +96 -0
- package/src/commands/publish.js +1087 -0
- package/src/commands/pull.js +1257 -0
- package/src/commands/push.js +663 -0
- package/src/commands/refresh.js +212 -0
- package/src/commands/register.js +1092 -0
- package/src/commands/rename.js +647 -0
- package/src/commands/site.js +358 -0
- package/src/commands/snapshot.js +461 -0
- package/src/commands/starter.js +206 -0
- package/src/commands/status.js +302 -0
- package/src/commands/sync.js +93 -0
- package/src/commands/template.js +107 -0
- package/src/commands/update.js +887 -0
- package/src/commands/validate.js +376 -0
- package/src/framework-index.json +248 -0
- package/src/index.js +2241 -0
- package/src/templates/fetchers/github.js +113 -0
- package/src/templates/fetchers/npm.js +85 -0
- package/src/templates/fetchers/release.js +92 -0
- package/src/templates/index.js +190 -0
- package/src/templates/processor.js +333 -0
- package/src/templates/resolver.js +232 -0
- package/src/templates/validator.js +155 -0
- package/src/utils/agents-stamp.js +110 -0
- package/src/utils/args.js +126 -0
- package/src/utils/asset-upload.js +270 -0
- package/src/utils/bytes.js +30 -0
- package/src/utils/code-upload.js +394 -0
- package/src/utils/config.js +417 -0
- package/src/utils/conformance.js +274 -0
- package/src/utils/dep-survey.js +176 -0
- package/src/utils/destination-prompt.js +146 -0
- package/src/utils/discover.js +75 -0
- package/src/utils/env.js +22 -0
- package/src/utils/exit.js +30 -0
- package/src/utils/fetch-retry.js +109 -0
- package/src/utils/flag-guard.js +246 -0
- package/src/utils/foundation-name.js +179 -0
- package/src/utils/git.js +342 -0
- package/src/utils/host-prompt.js +51 -0
- package/src/utils/install-integrity.js +210 -0
- package/src/utils/interactive.js +118 -0
- package/src/utils/json-file.js +72 -0
- package/src/utils/names.js +91 -0
- package/src/utils/placement.js +151 -0
- package/src/utils/pm.js +165 -0
- package/src/utils/preview.js +20 -0
- package/src/utils/pull-written.js +132 -0
- package/src/utils/records-guard.js +88 -0
- package/src/utils/registry-auth.js +994 -0
- package/src/utils/registry-orgs.js +290 -0
- package/src/utils/scaffold.js +483 -0
- package/src/utils/schemaless-report.js +30 -0
- package/src/utils/semver-precedence.js +80 -0
- package/src/utils/session-file.js +95 -0
- package/src/utils/site-content-refs.js +23 -0
- package/src/utils/site-copies.js +123 -0
- package/src/utils/site-data-upload.js +302 -0
- package/src/utils/site-identity.js +137 -0
- package/src/utils/snapshot-settings.js +112 -0
- package/src/utils/update-check.js +302 -0
- package/src/utils/uwx-read.js +157 -0
- package/src/utils/workspace.js +223 -0
- package/src/versions.js +467 -0
- package/starter/foundation/main.js +50 -0
- package/starter/foundation/sections/Section/index.jsx +95 -0
- package/starter/foundation/sections/Section/meta.js +44 -0
- package/starter/site/pages/about/1-about.md.hbs +13 -0
- package/starter/site/pages/about/page.yml +3 -0
- package/starter/site/pages/home/1-welcome.md.hbs +14 -0
- package/starter/site/pages/home/page.yml +3 -0
- package/templates/foundation/_gitignore +5 -0
- package/templates/foundation/components/.gitkeep +0 -0
- package/templates/foundation/main.js.hbs +33 -0
- package/templates/foundation/package.json.hbs +51 -0
- package/templates/foundation/sections/.gitkeep +0 -0
- package/templates/foundation/styles.css +6 -0
- package/templates/foundation/vite.config.js +3 -0
- package/templates/site/_gitignore +12 -0
- package/templates/site/entry.js +7 -0
- package/templates/site/index.html.hbs +13 -0
- package/templates/site/package.json.hbs +27 -0
- package/templates/site/public/favicon.svg +7 -0
- package/templates/site/site.yml.hbs +91 -0
- package/templates/site/theme.yml +99 -0
- package/templates/site/vite.config.js +7 -0
- package/templates/workspace/AGENTS.md.hbs +2 -0
- package/templates/workspace/README.md.hbs +87 -0
- package/templates/workspace/_gitignore +29 -0
- package/templates/workspace/_vscode/settings.json +6 -0
- package/templates/workspace/package.json.hbs +20 -0
- package/templates/workspace/pnpm-workspace.yaml.hbs +26 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev Command
|
|
3
|
+
*
|
|
4
|
+
* Starts a dev server for a site in the current workspace. Wraps the
|
|
5
|
+
* project's `dev` script (set up by `uniweb create` to filter to the
|
|
6
|
+
* appropriate site package). Provides discoverability and consistency
|
|
7
|
+
* with `uniweb build` / `uniweb deploy` — users shouldn't have to know
|
|
8
|
+
* whether to type `pnpm dev` or `npm run dev` when the rest of the CLI
|
|
9
|
+
* is verb-shaped.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* uniweb dev Start dev server for the (single) site
|
|
13
|
+
* uniweb dev <site> Start dev server for a specific site
|
|
14
|
+
* uniweb dev --site <name> Same, with explicit flag form
|
|
15
|
+
*
|
|
16
|
+
* Resolution order for which site to launch:
|
|
17
|
+
* 1. --site <name> (if passed)
|
|
18
|
+
* 2. Positional <site> arg
|
|
19
|
+
* 3. The single site in the workspace (if exactly one)
|
|
20
|
+
* 4. The first site in the workspace, with a "multiple sites" notice
|
|
21
|
+
* pointing at --site for explicit selection
|
|
22
|
+
*
|
|
23
|
+
* Multi-site workspaces with no positional / flag will run the first
|
|
24
|
+
* site by default (mirrors the `pnpm dev` shortcut `uniweb create` writes).
|
|
25
|
+
* Use `--site` to pick a different one without editing the root scripts.
|
|
26
|
+
*
|
|
27
|
+
* A site whose foundation is a catalog ref — every clone — has no build of it, and
|
|
28
|
+
* only the backend the site is on can say where that version is served. So `dev`
|
|
29
|
+
* asks it, through the site, and hands the answer to the dev server it starts in its
|
|
30
|
+
* environment (`UNIWEB_PREVIEW`), with the backend it asked, which is also where the
|
|
31
|
+
* site's kept media URLs are fetched from. Nothing is written: `site.yml` keeps the
|
|
32
|
+
* ref and the round trip never sees the URL. A backend that does not say is an
|
|
33
|
+
* ordinary answer — `dev` says so and starts nothing (`backend/site-preview.js`).
|
|
34
|
+
*
|
|
35
|
+
* Implementation: shells out to the package manager that invoked the CLI
|
|
36
|
+
* (detected via npm_config_user_agent), running the workspace-filtered
|
|
37
|
+
* dev command (`pnpm --filter <name> dev` or `npm -w <name> run dev`).
|
|
38
|
+
* No special handling of vite directly — the site package already owns
|
|
39
|
+
* its dev script, and shelling through pnpm/npm respects whatever the
|
|
40
|
+
* site has configured (Vite plugins, env vars, port overrides, etc.).
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
import { spawn } from 'node:child_process'
|
|
44
|
+
import { join } from 'node:path'
|
|
45
|
+
|
|
46
|
+
import { detectPackageManager, filterCmd } from '../utils/pm.js'
|
|
47
|
+
import { readWorkspaceConfig } from '../utils/config.js'
|
|
48
|
+
import { discoverSites } from '../utils/discover.js'
|
|
49
|
+
import { findWorkspaceRoot } from '../utils/workspace.js'
|
|
50
|
+
import { readFlagValue } from '../utils/args.js'
|
|
51
|
+
import {
|
|
52
|
+
checkSiteInstall,
|
|
53
|
+
readDeclaredFoundation
|
|
54
|
+
} from '../utils/install-integrity.js'
|
|
55
|
+
import { discoverFoundations } from '../utils/discover.js'
|
|
56
|
+
|
|
57
|
+
const RED = '\x1b[31m'
|
|
58
|
+
const YELLOW = '\x1b[33m'
|
|
59
|
+
const DIM = '\x1b[2m'
|
|
60
|
+
const CYAN = '\x1b[36m'
|
|
61
|
+
const RESET = '\x1b[0m'
|
|
62
|
+
|
|
63
|
+
export async function dev(args = []) {
|
|
64
|
+
const cwd = process.cwd()
|
|
65
|
+
const rootDir = findWorkspaceRoot(cwd) || cwd
|
|
66
|
+
|
|
67
|
+
// Verify we're in a Uniweb workspace (has pnpm-workspace.yaml or
|
|
68
|
+
// package.json::workspaces). discoverSites already handles both.
|
|
69
|
+
let workspaceConfig
|
|
70
|
+
try {
|
|
71
|
+
workspaceConfig = await readWorkspaceConfig(rootDir)
|
|
72
|
+
} catch {
|
|
73
|
+
workspaceConfig = { packages: [] }
|
|
74
|
+
}
|
|
75
|
+
if (workspaceConfig.packages.length === 0) {
|
|
76
|
+
console.error(
|
|
77
|
+
`${RED}✗${RESET} Not in a Uniweb workspace (no pnpm-workspace.yaml or package.json::workspaces).`
|
|
78
|
+
)
|
|
79
|
+
console.error(
|
|
80
|
+
` Run \`uniweb create <name>\` to scaffold a project, or cd into an existing one.`
|
|
81
|
+
)
|
|
82
|
+
process.exit(1)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const sites = await discoverSites(rootDir)
|
|
86
|
+
if (sites.length === 0) {
|
|
87
|
+
console.error(`${RED}✗${RESET} No sites found in this workspace.`)
|
|
88
|
+
console.error(` Add one with \`uniweb add site <name>\`.`)
|
|
89
|
+
process.exit(1)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Pick the site
|
|
93
|
+
const siteFlag = readFlagValue(args, '--site')
|
|
94
|
+
const positional = args.find((a) => !a.startsWith('-'))
|
|
95
|
+
const requested =
|
|
96
|
+
(typeof siteFlag === 'string' ? siteFlag : null) || positional || null
|
|
97
|
+
|
|
98
|
+
let site
|
|
99
|
+
if (requested) {
|
|
100
|
+
site =
|
|
101
|
+
sites.find((s) => s.name === requested) ||
|
|
102
|
+
sites.find((s) => s.path === requested)
|
|
103
|
+
if (!site) {
|
|
104
|
+
console.error(`${RED}✗${RESET} Site "${requested}" not found.`)
|
|
105
|
+
console.error(` Available: ${sites.map((s) => s.name).join(', ')}`)
|
|
106
|
+
process.exit(1)
|
|
107
|
+
}
|
|
108
|
+
} else if (sites.length === 1) {
|
|
109
|
+
site = sites[0]
|
|
110
|
+
} else {
|
|
111
|
+
site = sites[0]
|
|
112
|
+
console.error(
|
|
113
|
+
`${YELLOW}⚠${RESET} Multiple sites found; using ${CYAN}${site.name}${RESET}.`
|
|
114
|
+
)
|
|
115
|
+
console.error(` Pick a different one with \`uniweb dev --site <name>\`.`)
|
|
116
|
+
console.error(` Available: ${sites.map((s) => s.name).join(', ')}`)
|
|
117
|
+
console.error('')
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// A `file:` foundation dependency can be satisfied by a link or by a copy,
|
|
121
|
+
// and a copy is a snapshot: the dev server serves it while builds read the
|
|
122
|
+
// workspace source, so the two disagree and only the browser shows it. The
|
|
123
|
+
// check is a few stats and package.json reads, so it runs every time rather
|
|
124
|
+
// than waiting for someone to suspect it.
|
|
125
|
+
await warnOnStaleInstall(rootDir, site)
|
|
126
|
+
|
|
127
|
+
const pm = detectPackageManager()
|
|
128
|
+
const command = filterCmd(pm, site.name, 'dev')
|
|
129
|
+
const [bin, ...rest] = command.split(' ')
|
|
130
|
+
const sitePath = join(rootDir, site.path)
|
|
131
|
+
|
|
132
|
+
// ⭐ A SITE WHOSE FOUNDATION IS A CATALOG REF — a clone — is previewed with what the backend
|
|
133
|
+
// it is on says: where that version is served. Asked here, for this dev server alone, and
|
|
134
|
+
// handed to it in its environment; nothing is written (`backend/site-preview.js`). Any other
|
|
135
|
+
// site needs nothing from a backend, and this asks nothing.
|
|
136
|
+
const { readSitePreview } = await import('../backend/site-preview.js')
|
|
137
|
+
const asked = await readSitePreview({ siteDir: sitePath, args })
|
|
138
|
+
if (asked?.refused) {
|
|
139
|
+
console.error(`${RED}✗${RESET} ${asked.refused[0]}`)
|
|
140
|
+
for (const line of asked.refused.slice(1)) console.error(` ${line}`)
|
|
141
|
+
process.exit(1)
|
|
142
|
+
}
|
|
143
|
+
let env = process.env
|
|
144
|
+
if (asked?.preview) {
|
|
145
|
+
const { PREVIEW_ENV, encodePreview } = await import('@uniweb/build/site')
|
|
146
|
+
env = { ...process.env, [PREVIEW_ENV]: encodePreview(asked.preview) }
|
|
147
|
+
console.error(
|
|
148
|
+
`${DIM}→ Previewing with ${asked.preview.foundation.ref}, served by ${asked.preview.backend}${RESET}`
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.error(
|
|
153
|
+
`${DIM}→ ${command}${RESET} ${DIM}(site: ${site.name}, dir: ${sitePath})${RESET}`
|
|
154
|
+
)
|
|
155
|
+
console.error('')
|
|
156
|
+
|
|
157
|
+
const child = spawn(bin, rest, { cwd: rootDir, stdio: 'inherit', env })
|
|
158
|
+
child.on('close', (code) => process.exit(code ?? 0))
|
|
159
|
+
child.on('error', (err) => {
|
|
160
|
+
console.error(`${RED}✗${RESET} Failed to start dev server: ${err.message}`)
|
|
161
|
+
process.exit(1)
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Say so if the site is about to be served from an install that no longer
|
|
167
|
+
* matches the workspace. Warns rather than exits — the server may still be
|
|
168
|
+
* useful, and the author is the one who knows whether it is.
|
|
169
|
+
*/
|
|
170
|
+
async function warnOnStaleInstall(rootDir, site) {
|
|
171
|
+
try {
|
|
172
|
+
const sitePath = join(rootDir, site.path)
|
|
173
|
+
const foundationName = readDeclaredFoundation(sitePath)
|
|
174
|
+
if (!foundationName) return
|
|
175
|
+
|
|
176
|
+
const foundations = await discoverFoundations(rootDir)
|
|
177
|
+
const foundation = foundations
|
|
178
|
+
.map((f) => ({ ...f, path: join(rootDir, f.path) }))
|
|
179
|
+
.find((f) => f.name === foundationName)
|
|
180
|
+
if (!foundation) return
|
|
181
|
+
|
|
182
|
+
const findings = checkSiteInstall(
|
|
183
|
+
{ name: site.name, path: sitePath },
|
|
184
|
+
foundation,
|
|
185
|
+
rootDir
|
|
186
|
+
)
|
|
187
|
+
if (!findings.length) return
|
|
188
|
+
|
|
189
|
+
console.error(
|
|
190
|
+
`${YELLOW}⚠${RESET} Dev will not build against your workspace foundation:`
|
|
191
|
+
)
|
|
192
|
+
for (const finding of findings) {
|
|
193
|
+
console.error(` ${finding.message}`)
|
|
194
|
+
}
|
|
195
|
+
console.error(
|
|
196
|
+
` ${findings[0].remedy}. \`uniweb doctor\` explains in full.`
|
|
197
|
+
)
|
|
198
|
+
console.error('')
|
|
199
|
+
} catch {
|
|
200
|
+
// A diagnostic must never be the reason dev fails to start.
|
|
201
|
+
}
|
|
202
|
+
}
|