uniweb 0.13.16 → 0.14.0
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/README.md +1 -1
- package/package.json +7 -7
- package/partials/agents.md +51 -0
- package/src/backend/client.js +173 -40
- package/src/backend/data-bundle.js +15 -3
- package/src/backend/foundation-bring-along.js +76 -21
- package/src/backend/payment-handoff.js +28 -9
- package/src/backend/site-media.js +147 -19
- package/src/backend/site-sync.js +362 -40
- package/src/commands/add.js +575 -273
- package/src/commands/build.js +160 -57
- package/src/commands/clone.js +79 -26
- package/src/commands/content.js +11 -7
- package/src/commands/deploy.js +80 -32
- package/src/commands/dev.js +39 -17
- package/src/commands/docs.js +44 -16
- package/src/commands/doctor.js +338 -82
- package/src/commands/export.js +15 -7
- package/src/commands/handoff.js +6 -2
- package/src/commands/i18n.js +248 -99
- package/src/commands/inspect.js +48 -19
- package/src/commands/invite.js +9 -3
- package/src/commands/org.js +19 -5
- package/src/commands/publish.js +229 -60
- package/src/commands/pull.js +157 -48
- package/src/commands/push.js +144 -42
- package/src/commands/refresh.js +37 -10
- package/src/commands/register.js +235 -64
- package/src/commands/rename.js +126 -46
- package/src/commands/runtime.js +74 -24
- package/src/commands/status.js +48 -15
- package/src/commands/sync.js +7 -2
- package/src/commands/template.js +12 -4
- package/src/commands/update.js +263 -87
- package/src/commands/validate.js +115 -32
- package/src/framework-index.json +16 -14
- package/src/index.js +298 -145
- package/src/templates/fetchers/github.js +7 -7
- package/src/templates/fetchers/npm.js +3 -3
- package/src/templates/fetchers/release.js +21 -18
- package/src/templates/index.js +34 -12
- package/src/templates/processor.js +44 -12
- package/src/templates/resolver.js +42 -15
- package/src/templates/validator.js +14 -7
- package/src/utils/asset-upload.js +90 -22
- package/src/utils/code-upload.js +62 -37
- package/src/utils/config.js +31 -10
- package/src/utils/dep-survey.js +33 -7
- package/src/utils/destination-prompt.js +27 -17
- package/src/utils/git.js +66 -22
- package/src/utils/host-prompt.js +4 -3
- package/src/utils/install-integrity.js +8 -4
- package/src/utils/interactive.js +3 -3
- package/src/utils/json-file.js +6 -2
- package/src/utils/names.js +15 -6
- package/src/utils/placement.js +16 -8
- package/src/utils/registry-auth.js +185 -57
- package/src/utils/registry-orgs.js +142 -53
- package/src/utils/runtime-upload.js +52 -14
- package/src/utils/scaffold.js +55 -14
- package/src/utils/site-content-refs.js +3 -1
- package/src/utils/update-check.js +43 -17
- package/src/utils/workspace.js +13 -7
- package/src/versions.js +18 -7
- package/templates/site/_gitignore +5 -0
package/src/commands/validate.js
CHANGED
|
@@ -28,7 +28,7 @@ const colors = {
|
|
|
28
28
|
red: '\x1b[31m',
|
|
29
29
|
green: '\x1b[32m',
|
|
30
30
|
yellow: '\x1b[33m',
|
|
31
|
-
blue: '\x1b[36m'
|
|
31
|
+
blue: '\x1b[36m'
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const log = console.log
|
|
@@ -44,7 +44,8 @@ function flagValue(args, name) {
|
|
|
44
44
|
const eq = args.find((a) => a.startsWith(`${name}=`))
|
|
45
45
|
if (eq) return eq.slice(name.length + 1)
|
|
46
46
|
const idx = args.indexOf(name)
|
|
47
|
-
if (idx !== -1 && args[idx + 1] && !args[idx + 1].startsWith('--'))
|
|
47
|
+
if (idx !== -1 && args[idx + 1] && !args[idx + 1].startsWith('--'))
|
|
48
|
+
return args[idx + 1]
|
|
48
49
|
return null
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -76,19 +77,28 @@ async function validateSite(site, foundations, workspaceDir) {
|
|
|
76
77
|
// No local foundation to check against → out of static scope (the schemas
|
|
77
78
|
// live in the foundation; a registry-ref / URL foundation isn't on disk).
|
|
78
79
|
if (!foundationName) {
|
|
79
|
-
return {
|
|
80
|
+
return {
|
|
81
|
+
site: site.name,
|
|
82
|
+
status: 'skipped',
|
|
83
|
+
reason: 'no foundation declared in site.yml (runtime-loaded?)'
|
|
84
|
+
}
|
|
80
85
|
}
|
|
81
|
-
const match = foundations.find(
|
|
86
|
+
const match = foundations.find(
|
|
87
|
+
(f) => f.name === foundationName || basename(f.path) === foundationName
|
|
88
|
+
)
|
|
82
89
|
if (!match) {
|
|
83
90
|
return {
|
|
84
91
|
site: site.name,
|
|
85
92
|
status: 'skipped',
|
|
86
|
-
reason: `foundation "${foundationName}" is not a local workspace foundation — its schemas aren't on disk to check against
|
|
93
|
+
reason: `foundation "${foundationName}" is not a local workspace foundation — its schemas aren't on disk to check against`
|
|
87
94
|
}
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
const foundationPath = join(workspaceDir, match.path)
|
|
91
|
-
const report = await validateDataInputs({
|
|
98
|
+
const report = await validateDataInputs({
|
|
99
|
+
siteRoot: sitePath,
|
|
100
|
+
foundationPath
|
|
101
|
+
})
|
|
92
102
|
return { site: site.name, foundation: match.name, status: 'checked', report }
|
|
93
103
|
}
|
|
94
104
|
|
|
@@ -101,7 +111,9 @@ async function validateSite(site, foundations, workspaceDir) {
|
|
|
101
111
|
function printSiteHuman(result) {
|
|
102
112
|
log('')
|
|
103
113
|
if (result.status === 'skipped') {
|
|
104
|
-
warn(
|
|
114
|
+
warn(
|
|
115
|
+
`${colors.bright}${result.site}${colors.reset} — skipped: ${result.reason}`
|
|
116
|
+
)
|
|
105
117
|
return
|
|
106
118
|
}
|
|
107
119
|
|
|
@@ -110,7 +122,9 @@ function printSiteHuman(result) {
|
|
|
110
122
|
const header = `${colors.bright}${result.site}${colors.reset} ${colors.dim}(foundation: ${foundation})${colors.reset}`
|
|
111
123
|
|
|
112
124
|
if (violations.length === 0 && setupErrors.length === 0) {
|
|
113
|
-
success(
|
|
125
|
+
success(
|
|
126
|
+
`${header} — ${summary.records} record(s) / ${summary.schemas} schema(s) conform`
|
|
127
|
+
)
|
|
114
128
|
} else {
|
|
115
129
|
info(header)
|
|
116
130
|
}
|
|
@@ -119,31 +133,51 @@ function printSiteHuman(result) {
|
|
|
119
133
|
const groups = new Map()
|
|
120
134
|
for (const v of violations) {
|
|
121
135
|
const key = `${v.file} ${v.schema}`
|
|
122
|
-
if (!groups.has(key))
|
|
136
|
+
if (!groups.has(key))
|
|
137
|
+
groups.set(key, {
|
|
138
|
+
file: v.file,
|
|
139
|
+
schema: v.schema,
|
|
140
|
+
users: v.users,
|
|
141
|
+
findings: []
|
|
142
|
+
})
|
|
123
143
|
groups.get(key).findings.push(v)
|
|
124
144
|
}
|
|
125
145
|
for (const g of groups.values()) {
|
|
126
|
-
log(
|
|
146
|
+
log(
|
|
147
|
+
` ${colors.red}✗${colors.reset} ${g.file} ${colors.dim}· schema ${g.schema}${colors.reset}`
|
|
148
|
+
)
|
|
127
149
|
for (const u of dedupeUsers(g.users)) {
|
|
128
|
-
log(
|
|
150
|
+
log(
|
|
151
|
+
` ${colors.dim}used by${colors.reset} ${u.route} › ${u.section} › data.${u.key}`
|
|
152
|
+
)
|
|
129
153
|
}
|
|
130
154
|
for (const f of g.findings) {
|
|
131
|
-
log(
|
|
155
|
+
log(
|
|
156
|
+
` ${colors.yellow}•${colors.reset} item ${colors.bright}"${f.item}"${colors.reset} › ${f.field} — ${f.message}`
|
|
157
|
+
)
|
|
132
158
|
}
|
|
133
159
|
}
|
|
134
160
|
|
|
135
161
|
for (const e of setupErrors) {
|
|
136
162
|
log(` ${colors.red}✗${colors.reset} ${e.file} — ${e.message}`)
|
|
137
163
|
for (const u of dedupeUsers(e.users)) {
|
|
138
|
-
log(
|
|
164
|
+
log(
|
|
165
|
+
` ${colors.dim}used by${colors.reset} ${u.route} › ${u.section} › data.${u.key}`
|
|
166
|
+
)
|
|
139
167
|
}
|
|
140
168
|
}
|
|
141
169
|
|
|
142
170
|
if (deferred.length > 0) {
|
|
143
171
|
log(` ${colors.dim}↪ deferred (not statically checkable):${colors.reset}`)
|
|
144
172
|
for (const d of deferred) {
|
|
145
|
-
const extra = d.url
|
|
146
|
-
|
|
173
|
+
const extra = d.url
|
|
174
|
+
? ` ${colors.dim}(${d.url})${colors.reset}`
|
|
175
|
+
: d.ref
|
|
176
|
+
? ` ${colors.dim}(${d.ref})${colors.reset}`
|
|
177
|
+
: ''
|
|
178
|
+
log(
|
|
179
|
+
` ${colors.dim}•${colors.reset} ${d.route} › ${d.section} › data.${d.key} — ${d.reason}${extra}`
|
|
180
|
+
)
|
|
147
181
|
}
|
|
148
182
|
}
|
|
149
183
|
|
|
@@ -169,27 +203,55 @@ export async function validate(args = []) {
|
|
|
169
203
|
const asJson = args.includes('--json')
|
|
170
204
|
const strict = args.includes('--strict')
|
|
171
205
|
const siteFilter = flagValue(args, '--site')
|
|
172
|
-
const positional = args.find(
|
|
206
|
+
const positional = args.find(
|
|
207
|
+
(a, i) => !a.startsWith('--') && args[i - 1] !== '--site'
|
|
208
|
+
)
|
|
173
209
|
|
|
174
210
|
const target = positional ? resolve(process.cwd(), positional) : process.cwd()
|
|
175
211
|
const workspaceDir = findWorkspaceRoot(target)
|
|
176
212
|
|
|
177
213
|
if (!workspaceDir) {
|
|
178
|
-
if (asJson)
|
|
179
|
-
|
|
214
|
+
if (asJson)
|
|
215
|
+
log(
|
|
216
|
+
JSON.stringify(
|
|
217
|
+
{ ok: false, error: 'not in a Uniweb workspace' },
|
|
218
|
+
null,
|
|
219
|
+
2
|
|
220
|
+
)
|
|
221
|
+
)
|
|
222
|
+
else
|
|
223
|
+
error(
|
|
224
|
+
'Not in a Uniweb workspace. Run this from a project root or a site directory.'
|
|
225
|
+
)
|
|
180
226
|
return { exitCode: 2 }
|
|
181
227
|
}
|
|
182
228
|
|
|
183
|
-
const [sites, foundations] = await Promise.all([
|
|
229
|
+
const [sites, foundations] = await Promise.all([
|
|
230
|
+
discoverSites(workspaceDir),
|
|
231
|
+
discoverFoundations(workspaceDir)
|
|
232
|
+
])
|
|
184
233
|
|
|
185
234
|
// Select which sites to check: --site filter, an explicitly targeted site
|
|
186
235
|
// directory, or all sites in the workspace.
|
|
187
236
|
let selected = sites
|
|
188
237
|
if (siteFilter) {
|
|
189
|
-
selected = sites.filter(
|
|
238
|
+
selected = sites.filter(
|
|
239
|
+
(s) => s.name === siteFilter || basename(s.path) === siteFilter
|
|
240
|
+
)
|
|
190
241
|
if (selected.length === 0) {
|
|
191
242
|
const names = sites.map((s) => s.name).join(', ') || '(none)'
|
|
192
|
-
if (asJson)
|
|
243
|
+
if (asJson)
|
|
244
|
+
log(
|
|
245
|
+
JSON.stringify(
|
|
246
|
+
{
|
|
247
|
+
ok: false,
|
|
248
|
+
error: `site "${siteFilter}" not found`,
|
|
249
|
+
sites: sites.map((s) => s.name)
|
|
250
|
+
},
|
|
251
|
+
null,
|
|
252
|
+
2
|
|
253
|
+
)
|
|
254
|
+
)
|
|
193
255
|
else error(`Site "${siteFilter}" not found. Available: ${names}`)
|
|
194
256
|
return { exitCode: 2 }
|
|
195
257
|
}
|
|
@@ -199,7 +261,10 @@ export async function validate(args = []) {
|
|
|
199
261
|
}
|
|
200
262
|
|
|
201
263
|
if (selected.length === 0) {
|
|
202
|
-
if (asJson)
|
|
264
|
+
if (asJson)
|
|
265
|
+
log(
|
|
266
|
+
JSON.stringify({ ok: true, sites: [], note: 'no sites found' }, null, 2)
|
|
267
|
+
)
|
|
203
268
|
else warn('No sites found in this workspace.')
|
|
204
269
|
return { exitCode: 0 }
|
|
205
270
|
}
|
|
@@ -223,8 +288,14 @@ export async function validate(args = []) {
|
|
|
223
288
|
console.log = origConsoleLog
|
|
224
289
|
}
|
|
225
290
|
|
|
226
|
-
const totalViolations = results.reduce(
|
|
227
|
-
|
|
291
|
+
const totalViolations = results.reduce(
|
|
292
|
+
(n, r) => n + (r.report?.violations.length || 0),
|
|
293
|
+
0
|
|
294
|
+
)
|
|
295
|
+
const totalSetupErrors = results.reduce(
|
|
296
|
+
(n, r) => n + (r.report?.setupErrors.length || 0),
|
|
297
|
+
0
|
|
298
|
+
)
|
|
228
299
|
const hadError = results.some((r) => r.status === 'error')
|
|
229
300
|
|
|
230
301
|
if (asJson) {
|
|
@@ -236,24 +307,31 @@ export async function validate(args = []) {
|
|
|
236
307
|
foundation: r.foundation || null,
|
|
237
308
|
status: r.status,
|
|
238
309
|
reason: r.reason || null,
|
|
239
|
-
...(r.report || {})
|
|
310
|
+
...(r.report || {})
|
|
240
311
|
})),
|
|
241
312
|
summary: {
|
|
242
313
|
sites: results.length,
|
|
243
314
|
violations: totalViolations,
|
|
244
315
|
setupErrors: totalSetupErrors,
|
|
245
|
-
deferred: results.reduce(
|
|
246
|
-
|
|
316
|
+
deferred: results.reduce(
|
|
317
|
+
(n, r) => n + (r.report?.deferred.length || 0),
|
|
318
|
+
0
|
|
319
|
+
)
|
|
320
|
+
}
|
|
247
321
|
}
|
|
248
322
|
log(JSON.stringify(payload, null, 2))
|
|
249
323
|
} else {
|
|
250
324
|
log('')
|
|
251
325
|
log(`${colors.blue}${colors.bright}Uniweb Validate${colors.reset}`)
|
|
252
|
-
log(
|
|
326
|
+
log(
|
|
327
|
+
`${colors.dim}Checking content against the data schemas your foundation declares…${colors.reset}`
|
|
328
|
+
)
|
|
253
329
|
for (const r of results) {
|
|
254
330
|
if (r.status === 'error') {
|
|
255
331
|
log('')
|
|
256
|
-
error(
|
|
332
|
+
error(
|
|
333
|
+
`${colors.bright}${r.site}${colors.reset} — could not check: ${r.reason}`
|
|
334
|
+
)
|
|
257
335
|
} else {
|
|
258
336
|
printSiteHuman(r)
|
|
259
337
|
}
|
|
@@ -271,10 +349,15 @@ export async function validate(args = []) {
|
|
|
271
349
|
} else {
|
|
272
350
|
log('')
|
|
273
351
|
if (totalViolations > 0) {
|
|
274
|
-
const mode = strict
|
|
275
|
-
|
|
352
|
+
const mode = strict
|
|
353
|
+
? `${colors.red}error${colors.reset}`
|
|
354
|
+
: `${colors.yellow}warning${colors.reset}`
|
|
355
|
+
log(
|
|
356
|
+
`${totalViolations} violation(s) — reported as ${mode}${strict ? '' : ` ${colors.dim}(pass --strict to fail CI)${colors.reset}`}`
|
|
357
|
+
)
|
|
276
358
|
}
|
|
277
|
-
if (hadError)
|
|
359
|
+
if (hadError)
|
|
360
|
+
log(`${colors.red}Some sites could not be checked.${colors.reset}`)
|
|
278
361
|
log('')
|
|
279
362
|
}
|
|
280
363
|
}
|
package/src/framework-index.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-07-
|
|
3
|
+
"generatedAt": "2026-07-30T18:57:10.510Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/build": {
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.16.0",
|
|
7
7
|
"path": "framework/build",
|
|
8
8
|
"deps": [
|
|
9
9
|
"@uniweb/content-reader",
|
|
@@ -12,21 +12,22 @@
|
|
|
12
12
|
"@uniweb/projections",
|
|
13
13
|
"@uniweb/runtime",
|
|
14
14
|
"@uniweb/schemas",
|
|
15
|
+
"@uniweb/semantic-parser",
|
|
15
16
|
"@uniweb/theming"
|
|
16
17
|
]
|
|
17
18
|
},
|
|
18
19
|
"@uniweb/content-reader": {
|
|
19
|
-
"version": "1.
|
|
20
|
+
"version": "1.2.0",
|
|
20
21
|
"path": "framework/content-reader",
|
|
21
22
|
"deps": []
|
|
22
23
|
},
|
|
23
24
|
"@uniweb/content-writer": {
|
|
24
|
-
"version": "0.
|
|
25
|
+
"version": "0.3.0",
|
|
25
26
|
"path": "framework/content-writer",
|
|
26
27
|
"deps": []
|
|
27
28
|
},
|
|
28
29
|
"@uniweb/core": {
|
|
29
|
-
"version": "0.
|
|
30
|
+
"version": "0.8.0",
|
|
30
31
|
"path": "framework/core",
|
|
31
32
|
"deps": [
|
|
32
33
|
"@uniweb/semantic-parser",
|
|
@@ -39,16 +40,17 @@
|
|
|
39
40
|
"deps": []
|
|
40
41
|
},
|
|
41
42
|
"@uniweb/icons": {
|
|
42
|
-
"version": "0.
|
|
43
|
+
"version": "0.4.0",
|
|
43
44
|
"path": "framework/icons",
|
|
44
45
|
"deps": []
|
|
45
46
|
},
|
|
46
47
|
"@uniweb/kit": {
|
|
47
|
-
"version": "0.
|
|
48
|
+
"version": "0.10.0",
|
|
48
49
|
"path": "framework/kit",
|
|
49
50
|
"deps": [
|
|
50
51
|
"@uniweb/core",
|
|
51
|
-
"@uniweb/scene"
|
|
52
|
+
"@uniweb/scene",
|
|
53
|
+
"@uniweb/semantic-parser"
|
|
52
54
|
]
|
|
53
55
|
},
|
|
54
56
|
"@uniweb/loom": {
|
|
@@ -62,7 +64,7 @@
|
|
|
62
64
|
"deps": []
|
|
63
65
|
},
|
|
64
66
|
"@uniweb/projections": {
|
|
65
|
-
"version": "0.
|
|
67
|
+
"version": "0.2.0",
|
|
66
68
|
"path": "framework/projections",
|
|
67
69
|
"deps": [
|
|
68
70
|
"@uniweb/content-writer",
|
|
@@ -70,7 +72,7 @@
|
|
|
70
72
|
]
|
|
71
73
|
},
|
|
72
74
|
"@uniweb/runtime": {
|
|
73
|
-
"version": "0.
|
|
75
|
+
"version": "0.9.0",
|
|
74
76
|
"path": "framework/runtime",
|
|
75
77
|
"deps": [
|
|
76
78
|
"@uniweb/core",
|
|
@@ -93,22 +95,22 @@
|
|
|
93
95
|
"deps": []
|
|
94
96
|
},
|
|
95
97
|
"@uniweb/semantic-parser": {
|
|
96
|
-
"version": "1.
|
|
98
|
+
"version": "1.2.0",
|
|
97
99
|
"path": "framework/semantic-parser",
|
|
98
100
|
"deps": []
|
|
99
101
|
},
|
|
100
102
|
"@uniweb/templates": {
|
|
101
|
-
"version": "0.7.
|
|
103
|
+
"version": "0.7.46",
|
|
102
104
|
"path": "framework/templates",
|
|
103
105
|
"deps": []
|
|
104
106
|
},
|
|
105
107
|
"@uniweb/theming": {
|
|
106
|
-
"version": "0.1.
|
|
108
|
+
"version": "0.1.15",
|
|
107
109
|
"path": "framework/theming",
|
|
108
110
|
"deps": []
|
|
109
111
|
},
|
|
110
112
|
"@uniweb/unipress": {
|
|
111
|
-
"version": "0.5.
|
|
113
|
+
"version": "0.5.14",
|
|
112
114
|
"path": "framework/unipress",
|
|
113
115
|
"deps": [
|
|
114
116
|
"@uniweb/build",
|