uniweb 0.12.26 → 0.12.27
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 +6 -6
- package/partials/agents.md +3 -0
- package/src/backend/client.js +339 -0
- package/src/commands/clone.js +18 -32
- package/src/commands/deploy.js +218 -1783
- package/src/commands/handoff.js +9 -246
- package/src/commands/invite.js +10 -318
- package/src/commands/org.js +6 -8
- package/src/commands/publish.js +128 -1153
- package/src/commands/pull.js +22 -36
- package/src/commands/push.js +43 -101
- package/src/commands/register.js +184 -39
- package/src/commands/runtime.js +141 -0
- package/src/commands/template.js +13 -221
- package/src/framework-index.json +17 -6
- package/src/index.js +74 -100
- package/src/utils/asset-upload.js +162 -0
- package/src/utils/code-upload.js +245 -0
- package/src/utils/config.js +11 -44
- package/src/utils/registry-auth.js +35 -1
- package/src/utils/registry-orgs.js +141 -73
- package/src/utils/runtime-upload.js +163 -0
- package/src/commands/login.js +0 -230
- package/src/utils/auth.js +0 -212
- package/src/utils/registry.js +0 -466
package/src/commands/template.js
CHANGED
|
@@ -1,230 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* template — RESERVED (not available on the new backend yet).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* `uniweb template publish` submitted a site as a cloud template to the legacy
|
|
5
|
+
* registry (the PHP backend + Cloudflare Worker) the CLI no longer talks to. A
|
|
6
|
+
* new-backend equivalent isn't built; when it is, a template is REGISTERED (like
|
|
7
|
+
* a foundation or a schemas package) — the verb will be `register`, not `publish`
|
|
8
|
+
* (`publish` is for SITES only). The command name is kept reserved.
|
|
5
9
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* uniweb template publish --name my-tpl # Override template name
|
|
9
|
-
* uniweb template publish --title "My Tpl" # Display title
|
|
10
|
-
* uniweb template publish --description "A starter template"
|
|
11
|
-
* uniweb template publish --registry <url> # Publish to a specific registry URL
|
|
10
|
+
* (Unrelated: scaffolding FROM a template — `uniweb create --template <name>` —
|
|
11
|
+
* is a separate path and is unaffected.)
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
import { ensureAuth } from '../utils/auth.js'
|
|
20
|
-
import { findWorkspaceRoot, findSites, classifyPackage } from '../utils/workspace.js'
|
|
21
|
-
import { isNonInteractive, getCliPrefix } from '../utils/interactive.js'
|
|
22
|
-
|
|
23
|
-
const colors = {
|
|
24
|
-
reset: '\x1b[0m',
|
|
25
|
-
bright: '\x1b[1m',
|
|
26
|
-
dim: '\x1b[2m',
|
|
27
|
-
cyan: '\x1b[36m',
|
|
28
|
-
green: '\x1b[32m',
|
|
29
|
-
yellow: '\x1b[33m',
|
|
30
|
-
red: '\x1b[31m',
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function success(message) {
|
|
34
|
-
console.log(`${colors.green}✓${colors.reset} ${message}`)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function error(message) {
|
|
38
|
-
console.error(`${colors.red}✗${colors.reset} ${message}`)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function info(message) {
|
|
42
|
-
console.log(`${colors.cyan}→${colors.reset} ${message}`)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Parse a named flag from args.
|
|
47
|
-
* @param {string[]} args
|
|
48
|
-
* @param {string} flag - e.g. '--name'
|
|
49
|
-
* @returns {string|null}
|
|
50
|
-
*/
|
|
51
|
-
function parseFlag(args, flag) {
|
|
52
|
-
const idx = args.indexOf(flag)
|
|
53
|
-
if (idx === -1 || !args[idx + 1]) return null
|
|
54
|
-
return args[idx + 1]
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Build infrastructure files to exclude from templates
|
|
58
|
-
const EXCLUDED_FILES = new Set([
|
|
59
|
-
'package.json', 'package-lock.json', 'pnpm-lock.yaml',
|
|
60
|
-
'vite.config.js', 'vite.config.ts',
|
|
61
|
-
'index.html', 'main.js', 'main.ts',
|
|
62
|
-
])
|
|
63
|
-
const EXCLUDED_DIRS = new Set([
|
|
64
|
-
'node_modules', 'dist', '.git', '.vite',
|
|
65
|
-
])
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Resolve the site directory to publish as a template.
|
|
69
|
-
*
|
|
70
|
-
* Priority:
|
|
71
|
-
* 1. In a site directory → use it
|
|
72
|
-
* 2. site.yml in cwd (non-package site, e.g. cloud site) → use it
|
|
73
|
-
* 3. At workspace root, one site → use it
|
|
74
|
-
* 4. At workspace root, multiple → error
|
|
75
|
-
* 5. No site → educational error
|
|
76
|
-
*/
|
|
77
|
-
async function resolveSiteDir() {
|
|
78
|
-
const cwd = process.cwd()
|
|
79
|
-
|
|
80
|
-
// Check if current directory is a site package
|
|
81
|
-
const type = await classifyPackage(cwd)
|
|
82
|
-
if (type === 'site') return cwd
|
|
83
|
-
|
|
84
|
-
// Check for site.yml directly (non-package site, e.g. cloud site)
|
|
85
|
-
if (existsSync(join(cwd, 'site.yml'))) return cwd
|
|
86
|
-
|
|
87
|
-
// Check workspace
|
|
88
|
-
const workspaceRoot = findWorkspaceRoot(cwd)
|
|
89
|
-
if (workspaceRoot) {
|
|
90
|
-
const sites = await findSites(workspaceRoot)
|
|
91
|
-
if (sites.length === 1) return resolve(workspaceRoot, sites[0])
|
|
92
|
-
if (sites.length > 1) {
|
|
93
|
-
error('Multiple sites found. Run this command from inside the site directory.')
|
|
94
|
-
process.exit(1)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
error('No site found. Run this command from a site directory (must contain site.yml).')
|
|
99
|
-
process.exit(1)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Recursively read all files in a directory, returning { relativePath: base64Content }.
|
|
104
|
-
* Skips build infrastructure files and directories.
|
|
105
|
-
*/
|
|
106
|
-
async function readAllFiles(dir, baseDir = dir) {
|
|
107
|
-
const files = {}
|
|
108
|
-
const entries = await readdir(dir, { withFileTypes: true })
|
|
109
|
-
|
|
110
|
-
for (const entry of entries) {
|
|
111
|
-
const fullPath = join(dir, entry.name)
|
|
112
|
-
if (entry.isDirectory()) {
|
|
113
|
-
if (EXCLUDED_DIRS.has(entry.name)) continue
|
|
114
|
-
Object.assign(files, await readAllFiles(fullPath, baseDir))
|
|
115
|
-
} else if (entry.isFile()) {
|
|
116
|
-
if (EXCLUDED_FILES.has(entry.name)) continue
|
|
117
|
-
const relPath = relative(baseDir, fullPath)
|
|
118
|
-
const content = await readFile(fullPath)
|
|
119
|
-
files[relPath] = content.toString('base64')
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return files
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Main template command dispatcher.
|
|
128
|
-
*/
|
|
129
|
-
export async function template(args = []) {
|
|
130
|
-
const subcommand = args[0]
|
|
131
|
-
|
|
132
|
-
if (subcommand === 'publish') {
|
|
133
|
-
await templatePublish(args.slice(1))
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const prefix = getCliPrefix()
|
|
138
|
-
error(subcommand ? `Unknown subcommand: template ${subcommand}` : 'Missing subcommand')
|
|
139
|
-
console.log('')
|
|
140
|
-
console.log(`${colors.bright}Usage:${colors.reset}`)
|
|
141
|
-
console.log(` ${prefix} template publish Publish a site as a cloud template`)
|
|
142
|
-
console.log('')
|
|
143
|
-
console.log(`${colors.bright}Options:${colors.reset}`)
|
|
144
|
-
console.log(` --name <name> Template registry name (overrides site.yml \`template:\` field)`)
|
|
145
|
-
console.log(` --title <title> Display title (overrides site.yml \`name:\` field)`)
|
|
146
|
-
console.log(` --description <txt> Description`)
|
|
147
|
-
console.log(` --registry <url> Registry URL (default: http://localhost:4001)`)
|
|
14
|
+
export async function template() {
|
|
15
|
+
console.error("\x1b[31m✗\x1b[0m `uniweb template register` isn't available on the new backend yet.")
|
|
16
|
+
console.error(' Submitting a site as a cloud template was retired with the PHP backend.')
|
|
17
|
+
console.error(' A template is REGISTERED, like a foundation — `publish` is for sites only.')
|
|
18
|
+
console.error(' (Scaffolding FROM a template still works: `uniweb create --template <name>`.)')
|
|
148
19
|
process.exit(1)
|
|
149
20
|
}
|
|
150
21
|
|
|
151
|
-
/**
|
|
152
|
-
* Publish a site directory as a cloud template.
|
|
153
|
-
*/
|
|
154
|
-
async function templatePublish(args) {
|
|
155
|
-
const registryUrl = parseFlag(args, '--registry')
|
|
156
|
-
const nameOverride = parseFlag(args, '--name')
|
|
157
|
-
const titleOverride = parseFlag(args, '--title')
|
|
158
|
-
const descOverride = parseFlag(args, '--description')
|
|
159
|
-
|
|
160
|
-
// 1. Resolve site directory
|
|
161
|
-
const siteDir = await resolveSiteDir()
|
|
162
|
-
|
|
163
|
-
// 2. Read and parse site.yml
|
|
164
|
-
const siteYmlPath = join(siteDir, 'site.yml')
|
|
165
|
-
if (!existsSync(siteYmlPath)) {
|
|
166
|
-
error('No site.yml found in this directory')
|
|
167
|
-
process.exit(1)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const siteYmlContent = await readFile(siteYmlPath, 'utf8')
|
|
171
|
-
const siteConfig = yaml.load(siteYmlContent) || {}
|
|
172
|
-
|
|
173
|
-
// 3. Determine template name: --name flag > site.yml `template:` field > directory name
|
|
174
|
-
const templateName = nameOverride || siteConfig.template || siteDir.split('/').pop()
|
|
175
|
-
|
|
176
|
-
if (!siteConfig.foundation) {
|
|
177
|
-
error('site.yml must declare a foundation')
|
|
178
|
-
process.exit(1)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// 4. Collect all content files (skip build infrastructure)
|
|
182
|
-
info(`Collecting files from ${colors.dim}${siteDir}${colors.reset}`)
|
|
183
|
-
const files = await readAllFiles(siteDir)
|
|
184
|
-
const fileCount = Object.keys(files).length
|
|
185
|
-
|
|
186
|
-
if (fileCount === 0) {
|
|
187
|
-
error('No files found to publish')
|
|
188
|
-
process.exit(1)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
console.log(` ${colors.dim}${fileCount} files${colors.reset}`)
|
|
192
|
-
|
|
193
|
-
// 5. Authenticate
|
|
194
|
-
const token = await ensureAuth({ command: 'Publishing template', args })
|
|
195
|
-
|
|
196
|
-
// 6. Build payload
|
|
197
|
-
const url = registryUrl || process.env.UNIWEB_REGISTRY_URL || 'http://localhost:4001'
|
|
198
|
-
|
|
199
|
-
const payload = { name: templateName, files }
|
|
200
|
-
if (titleOverride || siteConfig.name) {
|
|
201
|
-
payload.title = titleOverride || siteConfig.name
|
|
202
|
-
}
|
|
203
|
-
if (descOverride) payload.description = descOverride
|
|
204
|
-
|
|
205
|
-
// 7. Publish via API
|
|
206
|
-
info(`Publishing template ${colors.bright}${templateName}${colors.reset} to ${url}`)
|
|
207
|
-
|
|
208
|
-
const headers = { 'Content-Type': 'application/json' }
|
|
209
|
-
if (token) headers['Authorization'] = `Bearer ${token}`
|
|
210
|
-
|
|
211
|
-
const res = await fetch(`${url}/api/templates`, {
|
|
212
|
-
method: 'POST',
|
|
213
|
-
headers,
|
|
214
|
-
body: JSON.stringify(payload),
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
const body = await res.json()
|
|
218
|
-
|
|
219
|
-
if (!res.ok) {
|
|
220
|
-
error(body.error || `Server error (${res.status})`)
|
|
221
|
-
process.exit(1)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
console.log('')
|
|
225
|
-
success(`Published template ${colors.bright}${templateName}${colors.reset}`)
|
|
226
|
-
console.log(` ${colors.dim}Foundation: ${body.foundation}${colors.reset}`)
|
|
227
|
-
console.log(` ${colors.dim}Files: ${body.filesCount}${colors.reset}`)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
22
|
export default template
|
package/src/framework-index.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"generatedAt": "2026-06-15T03:29:50.221Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/build": {
|
|
6
|
-
"version": "0.14.
|
|
6
|
+
"version": "0.14.11",
|
|
7
7
|
"path": "framework/build",
|
|
8
8
|
"deps": [
|
|
9
9
|
"@uniweb/content-reader",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"deps": []
|
|
44
44
|
},
|
|
45
45
|
"@uniweb/kit": {
|
|
46
|
-
"version": "0.9.
|
|
46
|
+
"version": "0.9.16",
|
|
47
47
|
"path": "framework/kit",
|
|
48
48
|
"deps": [
|
|
49
49
|
"@uniweb/core",
|
|
@@ -69,12 +69,12 @@
|
|
|
69
69
|
]
|
|
70
70
|
},
|
|
71
71
|
"@uniweb/scene": {
|
|
72
|
-
"version": "0.1.
|
|
72
|
+
"version": "0.1.2",
|
|
73
73
|
"path": "framework/scene",
|
|
74
74
|
"deps": []
|
|
75
75
|
},
|
|
76
76
|
"@uniweb/schemas": {
|
|
77
|
-
"version": "0.2.
|
|
77
|
+
"version": "0.2.3",
|
|
78
78
|
"path": "framework/schemas",
|
|
79
79
|
"deps": []
|
|
80
80
|
},
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"deps": []
|
|
100
100
|
},
|
|
101
101
|
"@uniweb/unipress": {
|
|
102
|
-
"version": "0.4.
|
|
102
|
+
"version": "0.4.15",
|
|
103
103
|
"path": "framework/unipress",
|
|
104
104
|
"deps": [
|
|
105
105
|
"@uniweb/build",
|
|
@@ -149,6 +149,17 @@
|
|
|
149
149
|
"localization"
|
|
150
150
|
]
|
|
151
151
|
},
|
|
152
|
+
"blog": {
|
|
153
|
+
"name": "Blog",
|
|
154
|
+
"description": "A blog built on the @std/article standard schema. Markdown articles render as a card grid and as full posts via dynamic [slug] routes. The first template to use a shared standard data schema — no custom schema file needed.",
|
|
155
|
+
"tags": [
|
|
156
|
+
"blog",
|
|
157
|
+
"articles",
|
|
158
|
+
"collections",
|
|
159
|
+
"standard-schema",
|
|
160
|
+
"data-schema"
|
|
161
|
+
]
|
|
162
|
+
},
|
|
152
163
|
"dynamic": {
|
|
153
164
|
"name": "Dynamic Data",
|
|
154
165
|
"description": "Live API data fetching with loading states, transforms, and the portable data pattern",
|
package/src/index.js
CHANGED
|
@@ -33,7 +33,6 @@ import prompts from 'prompts'
|
|
|
33
33
|
// Same pattern as `build` and `docs`.
|
|
34
34
|
import { i18n } from './commands/i18n.js'
|
|
35
35
|
import { inspect } from './commands/inspect.js'
|
|
36
|
-
import { login } from './commands/login.js'
|
|
37
36
|
import { invite } from './commands/invite.js'
|
|
38
37
|
import { handoff } from './commands/handoff.js'
|
|
39
38
|
import { update } from './commands/update.js'
|
|
@@ -134,7 +133,7 @@ function getCliVersion() {
|
|
|
134
133
|
// install that's the whole point; delegating to the project-local copy
|
|
135
134
|
// would align the project to the version it already has, i.e. a no-op.
|
|
136
135
|
const STANDALONE_COMMANDS = new Set([
|
|
137
|
-
'create', 'clone', '--help', '-h', '--version', '-v', 'login', 'update',
|
|
136
|
+
'create', 'clone', '--help', '-h', '--version', '-v', 'login', 'logout', 'update',
|
|
138
137
|
])
|
|
139
138
|
|
|
140
139
|
/**
|
|
@@ -664,11 +663,12 @@ async function main() {
|
|
|
664
663
|
return
|
|
665
664
|
}
|
|
666
665
|
|
|
667
|
-
// Handle publish command
|
|
666
|
+
// Handle publish command — CMS-publish a SYNCED site (POST /dev/site/publish).
|
|
667
|
+
// Distinct from `deploy` (file-built host) and `register` (foundation publishing).
|
|
668
668
|
if (command === 'publish') {
|
|
669
669
|
const { publish } = await importProjectCommand('./commands/publish.js')
|
|
670
|
-
await publish(args.slice(1))
|
|
671
|
-
|
|
670
|
+
const result = await publish(args.slice(1))
|
|
671
|
+
process.exit(result?.exitCode ?? 0)
|
|
672
672
|
}
|
|
673
673
|
|
|
674
674
|
// Handle deploy command (dynamic import — depends on @uniweb/build)
|
|
@@ -692,18 +692,27 @@ async function main() {
|
|
|
692
692
|
return
|
|
693
693
|
}
|
|
694
694
|
|
|
695
|
-
// Handle login command
|
|
696
|
-
//
|
|
697
|
-
//
|
|
695
|
+
// Handle login command — the backend (username/password · paste a token ·
|
|
696
|
+
// --token <bearer>). Origin from --backend/--registry > UNIWEB_REGISTER_URL >
|
|
697
|
+
// default, the SAME resolver register/push/pull/deploy use, so a session and
|
|
698
|
+
// the commands that reuse it always target one backend.
|
|
698
699
|
if (command === 'login') {
|
|
699
700
|
const loginArgs = args.slice(1)
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
701
|
+
const { resolveBackendOrigin } = await import('./backend/client.js')
|
|
702
|
+
const { readFlagValue } = await import('./utils/args.js')
|
|
703
|
+
const { runRegistryLogin } = await import('./utils/registry-auth.js')
|
|
704
|
+
const originFlag = readFlagValue(loginArgs, '--backend') || readFlagValue(loginArgs, '--registry')
|
|
705
|
+
await runRegistryLogin({ apiBase: resolveBackendOrigin(originFlag), args: loginArgs })
|
|
706
|
+
return
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// Handle logout command — clear the stored backend session.
|
|
710
|
+
if (command === 'logout') {
|
|
711
|
+
const { clearRegistryAuth, getRegistryAuthPath } = await import('./utils/registry-auth.js')
|
|
712
|
+
const { existsSync } = await import('node:fs')
|
|
713
|
+
const had = existsSync(getRegistryAuthPath())
|
|
714
|
+
await clearRegistryAuth()
|
|
715
|
+
console.log(had ? '\x1b[32m✓\x1b[0m Logged out (cleared the stored session).' : 'Not logged in — nothing to clear.')
|
|
707
716
|
return
|
|
708
717
|
}
|
|
709
718
|
|
|
@@ -714,6 +723,14 @@ async function main() {
|
|
|
714
723
|
return
|
|
715
724
|
}
|
|
716
725
|
|
|
726
|
+
// Handle runtime command — `runtime register` uploads a built @uniweb/runtime to
|
|
727
|
+
// the backend's runtime registry (/gateway/runtime/{version}); @std-gated.
|
|
728
|
+
if (command === 'runtime') {
|
|
729
|
+
const { runtime } = await import('./commands/runtime.js')
|
|
730
|
+
const result = await runtime(args.slice(1))
|
|
731
|
+
process.exit(result?.exitCode ?? 0)
|
|
732
|
+
}
|
|
733
|
+
|
|
717
734
|
// Handle invite command
|
|
718
735
|
if (command === 'invite') {
|
|
719
736
|
await invite(args.slice(1))
|
|
@@ -1105,24 +1122,20 @@ ${colors.bright}Examples:${colors.reset}
|
|
|
1105
1122
|
uniweb deploy --target=preview # Pick named target from deploy.yml
|
|
1106
1123
|
`,
|
|
1107
1124
|
publish: `
|
|
1108
|
-
${colors.cyan}${colors.bright}uniweb publish${colors.reset} ${colors.dim}— Publish a
|
|
1125
|
+
${colors.cyan}${colors.bright}uniweb publish${colors.reset} ${colors.dim}— Publish a synced site (make its backend state live)${colors.reset}
|
|
1109
1126
|
|
|
1110
1127
|
${colors.bright}Usage:${colors.reset}
|
|
1111
|
-
uniweb publish [
|
|
1128
|
+
uniweb publish [options]
|
|
1112
1129
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1130
|
+
Publishes a site that's synced to the backend (has site.yml::\$uuid from
|
|
1131
|
+
\`uniweb push\`) — makes its CURRENT backend state live, including edits made
|
|
1132
|
+
through the app. Run \`uniweb push\` first to include local edits. For a
|
|
1133
|
+
file-only site use \`uniweb deploy\`; to register a FOUNDATION use \`uniweb register\`.
|
|
1115
1134
|
|
|
1116
1135
|
${colors.bright}Options:${colors.reset}
|
|
1117
|
-
--
|
|
1118
|
-
--
|
|
1119
|
-
--
|
|
1120
|
-
--namespace <ns> Force org-scope namespace (overrides package.json)
|
|
1121
|
-
--local Internal: publish to the unicloud mock (see workspace root CLAUDE.md)
|
|
1122
|
-
--registry <url> Use a specific registry URL
|
|
1123
|
-
--edit-access <p> "open" or "restricted" (default: restricted)
|
|
1124
|
-
--dry-run Show what would be published without uploading
|
|
1125
|
-
--non-interactive Fail with usage info instead of prompting
|
|
1136
|
+
--backend <url> Backend origin (default: \$UNIWEB_REGISTER_URL or built-in)
|
|
1137
|
+
--token <bearer> Auth bearer (skips \`uniweb login\`)
|
|
1138
|
+
--dry-run Resolve everything; POST nothing
|
|
1126
1139
|
`,
|
|
1127
1140
|
create: `
|
|
1128
1141
|
${colors.cyan}${colors.bright}uniweb create${colors.reset} ${colors.dim}— Create a new project${colors.reset}
|
|
@@ -1262,8 +1275,9 @@ ${colors.bright}Usage:${colors.reset}
|
|
|
1262
1275
|
uniweb register [options]
|
|
1263
1276
|
|
|
1264
1277
|
Builds one \`.uwx\` document and submits it to the registry over HTTP. Run
|
|
1265
|
-
\`uniweb login\` first (or pass \`--token\`).
|
|
1266
|
-
|
|
1278
|
+
\`uniweb login\` first (or pass \`--token\`). \`register\` is for FOUNDATIONS (and
|
|
1279
|
+
schemas); \`uniweb publish\` makes a synced SITE live; \`uniweb deploy\` hosts a
|
|
1280
|
+
file-built site.
|
|
1267
1281
|
|
|
1268
1282
|
Auto-detects what you run it in:
|
|
1269
1283
|
• a foundation the foundation + the data schemas it defines/renders
|
|
@@ -1321,52 +1335,38 @@ ${colors.cyan}${colors.bright}uniweb login${colors.reset} ${colors.dim}— Log i
|
|
|
1321
1335
|
${colors.bright}Usage:${colors.reset}
|
|
1322
1336
|
uniweb login [options]
|
|
1323
1337
|
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1338
|
+
Authenticates with the backend and stores a session at
|
|
1339
|
+
~/.uniweb/registry-auth.json. Every backend command (register, push, pull,
|
|
1340
|
+
clone, deploy) reuses it. Interactively, pick username/password or paste a token.
|
|
1327
1341
|
|
|
1328
1342
|
${colors.bright}Options:${colors.reset}
|
|
1329
|
-
--backend <url>
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1343
|
+
--backend <url> Backend origin (default: \$UNIWEB_REGISTER_URL or built-in)
|
|
1344
|
+
--token <bearer> Seed + verify a session from a bearer token (non-interactive)
|
|
1345
|
+
--password Force the username/password method
|
|
1346
|
+
--token-paste Force the paste-a-token prompt
|
|
1347
|
+
|
|
1348
|
+
In non-interactive mode (CI / no TTY), pass \`--token <bearer>\`, or set
|
|
1349
|
+
\`UNIWEB_USERNAME\` + \`UNIWEB_PASSWORD\`, or set \`UNIWEB_TOKEN\` (used per-command,
|
|
1350
|
+
not stored). Run \`uniweb logout\` to clear the stored session.
|
|
1334
1351
|
`,
|
|
1335
1352
|
invite: `
|
|
1336
|
-
${colors.cyan}${colors.bright}uniweb invite${colors.reset} ${colors.dim}—
|
|
1337
|
-
|
|
1338
|
-
${colors.bright}Usage:${colors.reset}
|
|
1339
|
-
uniweb invite <email> [options]
|
|
1353
|
+
${colors.cyan}${colors.bright}uniweb invite${colors.reset} ${colors.dim}— (reserved; not available on the new backend yet)${colors.reset}
|
|
1340
1354
|
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
--expires <days> Days until expiry (default: 30)
|
|
1344
|
-
--version <n> Major version to license (default: current)
|
|
1345
|
-
--list List invites for your foundation
|
|
1346
|
-
--revoke <id> Revoke an invite
|
|
1347
|
-
--resend <id> Resend an invite
|
|
1355
|
+
The foundation client-invite flow was retired with the legacy backend.
|
|
1356
|
+
Invite clients to your foundation from the Uniweb app for now.
|
|
1348
1357
|
`,
|
|
1349
1358
|
handoff: `
|
|
1350
|
-
${colors.cyan}${colors.bright}uniweb handoff${colors.reset} ${colors.dim}—
|
|
1351
|
-
|
|
1352
|
-
${colors.bright}Usage:${colors.reset}
|
|
1353
|
-
uniweb handoff <email> [options]
|
|
1359
|
+
${colors.cyan}${colors.bright}uniweb handoff${colors.reset} ${colors.dim}— (reserved; not available on the new backend yet)${colors.reset}
|
|
1354
1360
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
--web Show web-based handoff instructions instead
|
|
1361
|
+
The site-handoff flow was retired with the legacy backend.
|
|
1362
|
+
Manage client sites from the Uniweb app for now.
|
|
1358
1363
|
`,
|
|
1359
1364
|
template: `
|
|
1360
|
-
${colors.cyan}${colors.bright}uniweb template${colors.reset} ${colors.dim}—
|
|
1361
|
-
|
|
1362
|
-
${colors.bright}Subcommands:${colors.reset}
|
|
1363
|
-
template publish Publish a site as a cloud template
|
|
1365
|
+
${colors.cyan}${colors.bright}uniweb template${colors.reset} ${colors.dim}— (reserved; not available on the new backend yet)${colors.reset}
|
|
1364
1366
|
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
--description <t> Description
|
|
1369
|
-
--registry <url> Registry URL (default: http://localhost:4001)
|
|
1367
|
+
Submitting a site as a cloud template was retired with the legacy backend.
|
|
1368
|
+
When rebuilt, a template is REGISTERED (like a foundation) — \`publish\` is for
|
|
1369
|
+
sites only. Scaffolding FROM a template still works: \`uniweb create --template <name>\`.
|
|
1370
1370
|
`,
|
|
1371
1371
|
docs: `
|
|
1372
1372
|
${colors.cyan}${colors.bright}uniweb docs${colors.reset} ${colors.dim}— Generate component documentation${colors.reset}
|
|
@@ -1465,20 +1465,19 @@ ${colors.bright}Commands:${colors.reset}
|
|
|
1465
1465
|
build Build the current project
|
|
1466
1466
|
deploy Deploy a site to Uniweb hosting
|
|
1467
1467
|
export Export a self-contained site for third-party hosting
|
|
1468
|
-
publish Publish a
|
|
1468
|
+
publish Publish a synced site (make its backend state live)
|
|
1469
1469
|
register Register a foundation + its data schemas with the backend registry
|
|
1470
|
+
runtime register Register an @uniweb/runtime version to the backend (@std only)
|
|
1470
1471
|
push Push a site's content to the backend
|
|
1471
1472
|
pull Pull a site's content from the backend
|
|
1472
|
-
invite <email> Create a foundation invite for a client
|
|
1473
|
-
handoff <email> Hand off a site to a client
|
|
1474
1473
|
inspect <path> Inspect parsed content shape of a markdown file or folder
|
|
1475
1474
|
docs Generate component documentation
|
|
1476
1475
|
doctor Diagnose project configuration issues
|
|
1477
1476
|
validate Check your content against your foundation's data schemas
|
|
1478
1477
|
update Align workspace deps + AGENTS.md to the running CLI
|
|
1479
1478
|
i18n <cmd> Internationalization (extract, sync, status)
|
|
1480
|
-
template publish Publish a site as a cloud template
|
|
1481
1479
|
login Log in to your Uniweb account
|
|
1480
|
+
logout Clear the stored session
|
|
1482
1481
|
|
|
1483
1482
|
${colors.bright}Create Options:${colors.reset}
|
|
1484
1483
|
--template <type> Project template (default: starter)
|
|
@@ -1499,37 +1498,12 @@ ${colors.bright}Global Options:${colors.reset}
|
|
|
1499
1498
|
Auto-detected when CI=true or no TTY (pipes, agents)
|
|
1500
1499
|
|
|
1501
1500
|
${colors.bright}Publish Options:${colors.reset}
|
|
1502
|
-
--
|
|
1503
|
-
--
|
|
1504
|
-
--
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
--edit-access <p> Set edit access policy: "open" or "restricted" (default: restricted)
|
|
1509
|
-
--dry-run Show what would be published without uploading
|
|
1510
|
-
|
|
1511
|
-
uniweb publish is for cataloging a foundation as a product. For
|
|
1512
|
-
site-bound foundations (one foundation, one site), use uniweb deploy
|
|
1513
|
-
instead — it auto-publishes under a site-scoped slot, no naming
|
|
1514
|
-
ceremony.
|
|
1515
|
-
|
|
1516
|
-
${colors.bright}Invite Options:${colors.reset}
|
|
1517
|
-
--uses <n> Max sites per invite (default: 1)
|
|
1518
|
-
--expires <days> Days until expiry (default: 30)
|
|
1519
|
-
--version <n> Major version to license (default: current)
|
|
1520
|
-
--list List invites for your foundation
|
|
1521
|
-
--revoke <id> Revoke an invite
|
|
1522
|
-
--resend <id> Resend an invite
|
|
1523
|
-
|
|
1524
|
-
${colors.bright}Handoff Options:${colors.reset}
|
|
1525
|
-
--site <id> Site identifier (default: auto-generated)
|
|
1526
|
-
--web Show web-based handoff instructions instead
|
|
1527
|
-
|
|
1528
|
-
${colors.bright}Template Options:${colors.reset}
|
|
1529
|
-
--name <name> Template registry name (overrides site.yml template: field)
|
|
1530
|
-
--title <title> Display title (overrides site.yml name: field)
|
|
1531
|
-
--description <t> Description
|
|
1532
|
-
--registry <url> Registry URL (default: http://localhost:4001)
|
|
1501
|
+
--backend <url> Backend origin (default: \$UNIWEB_REGISTER_URL or built-in)
|
|
1502
|
+
--token <bearer> Auth bearer (skips \`uniweb login\`)
|
|
1503
|
+
--dry-run Resolve everything; POST nothing
|
|
1504
|
+
|
|
1505
|
+
uniweb publish makes a SYNCED site live (run \`uniweb push\` first). To register
|
|
1506
|
+
a foundation use \`uniweb register\`; to host a file-built site use \`uniweb deploy\`.
|
|
1533
1507
|
|
|
1534
1508
|
${colors.bright}Deploy Options:${colors.reset}
|
|
1535
1509
|
--target <name> Pick a target from deploy.yml (default: deploy.yml's \`default:\`)
|