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/build.js
CHANGED
|
@@ -58,9 +58,12 @@ import {
|
|
|
58
58
|
discoverComponents,
|
|
59
59
|
resolveFoundationSrcPath,
|
|
60
60
|
classifyPackage,
|
|
61
|
-
isExtensionPackage
|
|
61
|
+
isExtensionPackage
|
|
62
62
|
} from '@uniweb/build'
|
|
63
|
-
import {
|
|
63
|
+
import {
|
|
64
|
+
resolveDefaultLocale,
|
|
65
|
+
normalizeLanguageList
|
|
66
|
+
} from '@uniweb/core/locale-config'
|
|
64
67
|
import { readSiteConfig } from '@uniweb/build/site'
|
|
65
68
|
import { readWorkspaceConfig, resolveGlob } from '../utils/config.js'
|
|
66
69
|
|
|
@@ -72,7 +75,7 @@ const colors = {
|
|
|
72
75
|
cyan: '\x1b[36m',
|
|
73
76
|
green: '\x1b[32m',
|
|
74
77
|
yellow: '\x1b[33m',
|
|
75
|
-
red: '\x1b[31m'
|
|
78
|
+
red: '\x1b[31m'
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
function log(message) {
|
|
@@ -138,7 +141,7 @@ function runCommand(command, args, cwd) {
|
|
|
138
141
|
const proc = spawn(command, args, {
|
|
139
142
|
cwd,
|
|
140
143
|
stdio: 'inherit',
|
|
141
|
-
shell: true
|
|
144
|
+
shell: true
|
|
142
145
|
})
|
|
143
146
|
|
|
144
147
|
proc.on('close', (code) => {
|
|
@@ -172,7 +175,7 @@ function resolveLocalVite(projectDir) {
|
|
|
172
175
|
} catch {
|
|
173
176
|
throw new Error(
|
|
174
177
|
`Vite is not installed in ${projectDir}.\n` +
|
|
175
|
-
|
|
178
|
+
`Run \`pnpm install\` (or npm/yarn install) in the project before building.`
|
|
176
179
|
)
|
|
177
180
|
}
|
|
178
181
|
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
|
|
@@ -209,11 +212,15 @@ async function buildFoundation(projectDir, options = {}) {
|
|
|
209
212
|
|
|
210
213
|
if (componentNames.length === 0) {
|
|
211
214
|
error('No components found with meta.js files')
|
|
212
|
-
error(
|
|
215
|
+
error(
|
|
216
|
+
`Make sure components are in ${srcDir}/components/[Name]/ with a meta.js file`
|
|
217
|
+
)
|
|
213
218
|
process.exit(1)
|
|
214
219
|
}
|
|
215
220
|
|
|
216
|
-
success(
|
|
221
|
+
success(
|
|
222
|
+
`Found ${componentNames.length} components: ${componentNames.join(', ')}`
|
|
223
|
+
)
|
|
217
224
|
|
|
218
225
|
// 2. Generate entry point
|
|
219
226
|
log('')
|
|
@@ -241,8 +248,12 @@ async function buildFoundation(projectDir, options = {}) {
|
|
|
241
248
|
|
|
242
249
|
log('')
|
|
243
250
|
log(`${colors.bright}Share with clients:${colors.reset}`)
|
|
244
|
-
log(
|
|
245
|
-
|
|
251
|
+
log(
|
|
252
|
+
` ${colors.bright}uniweb publish${colors.reset} Register your foundation (one-time setup)`
|
|
253
|
+
)
|
|
254
|
+
log(
|
|
255
|
+
` ${colors.bright}uniweb handoff <email>${colors.reset} Hand off a site to a client`
|
|
256
|
+
)
|
|
246
257
|
}
|
|
247
258
|
|
|
248
259
|
/**
|
|
@@ -283,7 +294,9 @@ async function ensureFoundationFresh(foundationDir, label = 'foundation') {
|
|
|
283
294
|
const distArtifact = findFoundationDistArtifact(foundationDir)
|
|
284
295
|
|
|
285
296
|
if (!distArtifact) {
|
|
286
|
-
info(
|
|
297
|
+
info(
|
|
298
|
+
`Local ${label} not built yet — building ${basename(foundationDir)} first`
|
|
299
|
+
)
|
|
287
300
|
log('')
|
|
288
301
|
await buildFoundation(foundationDir)
|
|
289
302
|
log('')
|
|
@@ -294,7 +307,9 @@ async function ensureFoundationFresh(foundationDir, label = 'foundation') {
|
|
|
294
307
|
const stale = isFoundationSourceNewerThan(foundationDir, distMtime)
|
|
295
308
|
|
|
296
309
|
if (stale) {
|
|
297
|
-
info(
|
|
310
|
+
info(
|
|
311
|
+
`Local ${label} sources changed — rebuilding ${basename(foundationDir)}`
|
|
312
|
+
)
|
|
298
313
|
log('')
|
|
299
314
|
await buildFoundation(foundationDir)
|
|
300
315
|
log('')
|
|
@@ -342,7 +357,12 @@ function isFoundationSourceNewerThan(foundationDir, referenceMtime) {
|
|
|
342
357
|
continue
|
|
343
358
|
}
|
|
344
359
|
for (const e of entries) {
|
|
345
|
-
if (
|
|
360
|
+
if (
|
|
361
|
+
e.name === 'node_modules' ||
|
|
362
|
+
e.name === 'dist' ||
|
|
363
|
+
e.name.startsWith('.')
|
|
364
|
+
)
|
|
365
|
+
continue
|
|
346
366
|
const full = join(dir, e.name)
|
|
347
367
|
if (e.isDirectory()) {
|
|
348
368
|
stack.push(full)
|
|
@@ -351,7 +371,9 @@ function isFoundationSourceNewerThan(foundationDir, referenceMtime) {
|
|
|
351
371
|
if (!e.isFile()) continue
|
|
352
372
|
try {
|
|
353
373
|
if (statSync(full).mtimeMs > referenceMtime) return true
|
|
354
|
-
} catch {
|
|
374
|
+
} catch {
|
|
375
|
+
/* ignore */
|
|
376
|
+
}
|
|
355
377
|
}
|
|
356
378
|
}
|
|
357
379
|
|
|
@@ -386,7 +408,9 @@ async function loadI18nConfig(projectDir, siteConfig = null) {
|
|
|
386
408
|
const dropped = locales.filter((l) => !publishSet.has(l))
|
|
387
409
|
locales = locales.filter((l) => publishSet.has(l))
|
|
388
410
|
if (dropped.length > 0) {
|
|
389
|
-
info(
|
|
411
|
+
info(
|
|
412
|
+
`Skipping non-publishable locale(s): ${dropped.join(', ')} (not in publishLanguages)`
|
|
413
|
+
)
|
|
390
414
|
}
|
|
391
415
|
}
|
|
392
416
|
|
|
@@ -395,7 +419,7 @@ async function loadI18nConfig(projectDir, siteConfig = null) {
|
|
|
395
419
|
return {
|
|
396
420
|
defaultLocale: resolveDefaultLocale(config),
|
|
397
421
|
locales,
|
|
398
|
-
localesDir
|
|
422
|
+
localesDir
|
|
399
423
|
}
|
|
400
424
|
}
|
|
401
425
|
|
|
@@ -409,7 +433,7 @@ async function buildLocalizedContent(projectDir, i18nConfig) {
|
|
|
409
433
|
localesDir: i18nConfig.localesDir,
|
|
410
434
|
locales: i18nConfig.locales,
|
|
411
435
|
outputDir: join(projectDir, 'dist'),
|
|
412
|
-
fallbackToSource: true
|
|
436
|
+
fallbackToSource: true
|
|
413
437
|
})
|
|
414
438
|
|
|
415
439
|
return outputs
|
|
@@ -419,7 +443,8 @@ async function buildLocalizedContent(projectDir, i18nConfig) {
|
|
|
419
443
|
* Generate index.html for each locale with hreflang tags
|
|
420
444
|
*/
|
|
421
445
|
async function generateLocalizedHtml(projectDir, i18nConfig) {
|
|
422
|
-
const { readFile, writeFile, mkdir, copyFile } =
|
|
446
|
+
const { readFile, writeFile, mkdir, copyFile } =
|
|
447
|
+
await import('node:fs/promises')
|
|
423
448
|
const distDir = join(projectDir, 'dist')
|
|
424
449
|
const baseHtmlPath = join(distDir, 'index.html')
|
|
425
450
|
|
|
@@ -430,9 +455,12 @@ async function generateLocalizedHtml(projectDir, i18nConfig) {
|
|
|
430
455
|
let baseHtml = await readFile(baseHtmlPath, 'utf-8')
|
|
431
456
|
|
|
432
457
|
// Build hreflang tags
|
|
433
|
-
const hreflangTags = i18nConfig.locales
|
|
434
|
-
|
|
435
|
-
|
|
458
|
+
const hreflangTags = i18nConfig.locales
|
|
459
|
+
.map(
|
|
460
|
+
(locale) =>
|
|
461
|
+
`<link rel="alternate" hreflang="${locale}" href="/${locale}/" />`
|
|
462
|
+
)
|
|
463
|
+
.join('\n ')
|
|
436
464
|
|
|
437
465
|
const defaultHreflang = `<link rel="alternate" hreflang="x-default" href="/" />`
|
|
438
466
|
const allHreflangTags = `${hreflangTags}\n ${defaultHreflang}`
|
|
@@ -453,7 +481,10 @@ async function generateLocalizedHtml(projectDir, i18nConfig) {
|
|
|
453
481
|
let localeHtml = baseHtml
|
|
454
482
|
|
|
455
483
|
// Update html lang attribute
|
|
456
|
-
localeHtml = localeHtml.replace(
|
|
484
|
+
localeHtml = localeHtml.replace(
|
|
485
|
+
/<html[^>]*lang="[^"]*"/,
|
|
486
|
+
`<html lang="${locale}"`
|
|
487
|
+
)
|
|
457
488
|
if (!localeHtml.includes('lang=')) {
|
|
458
489
|
localeHtml = localeHtml.replace('<html', `<html lang="${locale}"`)
|
|
459
490
|
}
|
|
@@ -511,11 +542,16 @@ function resolveFoundationDir(projectDir, siteConfig) {
|
|
|
511
542
|
// Check if we're in a multi-site structure (site is under sites/)
|
|
512
543
|
const parentDir = join(projectDir, '..')
|
|
513
544
|
const grandParentDir = join(projectDir, '..', '..')
|
|
514
|
-
const isMultiSite =
|
|
545
|
+
const isMultiSite =
|
|
546
|
+
parentDir.endsWith('/sites') || parentDir.endsWith('\\sites')
|
|
515
547
|
|
|
516
548
|
if (isMultiSite && foundationName) {
|
|
517
549
|
// Multi-site: look for foundations/{name}
|
|
518
|
-
const multiFoundationDir = join(
|
|
550
|
+
const multiFoundationDir = join(
|
|
551
|
+
grandParentDir,
|
|
552
|
+
'foundations',
|
|
553
|
+
foundationName
|
|
554
|
+
)
|
|
519
555
|
if (existsSync(multiFoundationDir)) {
|
|
520
556
|
return multiFoundationDir
|
|
521
557
|
}
|
|
@@ -579,7 +615,10 @@ async function buildSiteLink(projectDir, options = {}) {
|
|
|
579
615
|
// theme variable defaults from `foundation.js::theme.vars`. When the
|
|
580
616
|
// foundation is purely a registry ref (no local sibling), this stays
|
|
581
617
|
// null and theme defaults come from theme.yml only.
|
|
582
|
-
const foundationDir = await resolveFoundationDirForSite(
|
|
618
|
+
const foundationDir = await resolveFoundationDirForSite(
|
|
619
|
+
projectDir,
|
|
620
|
+
siteConfig
|
|
621
|
+
).catch(() => null)
|
|
583
622
|
|
|
584
623
|
// Link mode does NOT (re)build the foundation. It reads only the
|
|
585
624
|
// foundation's SOURCE config (foundation.js::theme.vars, passed as
|
|
@@ -592,7 +631,7 @@ async function buildSiteLink(projectDir, options = {}) {
|
|
|
592
631
|
siteRoot: projectDir,
|
|
593
632
|
distDir,
|
|
594
633
|
foundationPath: foundationDir,
|
|
595
|
-
assets: siteConfig?.build?.assets || {}
|
|
634
|
+
assets: siteConfig?.build?.assets || {}
|
|
596
635
|
})
|
|
597
636
|
success(`Wrote ${join('dist', 'site-content.json')}`)
|
|
598
637
|
|
|
@@ -617,17 +656,24 @@ async function buildSiteLink(projectDir, options = {}) {
|
|
|
617
656
|
const collectionOutputs = await buildLocalizedCollections(projectDir, {
|
|
618
657
|
locales: i18nConfig.locales,
|
|
619
658
|
outputDir: distDir,
|
|
620
|
-
collectionsLocalesDir: join(
|
|
659
|
+
collectionsLocalesDir: join(
|
|
660
|
+
projectDir,
|
|
661
|
+
i18nConfig.localesDir,
|
|
662
|
+
'collections'
|
|
663
|
+
)
|
|
621
664
|
})
|
|
622
665
|
const collectionCount = Object.values(collectionOutputs).reduce(
|
|
623
666
|
(sum, localeOutputs) => sum + Object.keys(localeOutputs).length,
|
|
624
667
|
0
|
|
625
668
|
)
|
|
626
669
|
if (collectionCount > 0) {
|
|
627
|
-
success(
|
|
670
|
+
success(
|
|
671
|
+
`Translated collections for ${Object.keys(collectionOutputs).length} locale(s)`
|
|
672
|
+
)
|
|
628
673
|
}
|
|
629
674
|
} catch (err) {
|
|
630
|
-
if (process.env.UNIWEB_DEBUG)
|
|
675
|
+
if (process.env.UNIWEB_DEBUG)
|
|
676
|
+
console.error('Collection translation:', err.message)
|
|
631
677
|
}
|
|
632
678
|
} catch (err) {
|
|
633
679
|
error(`i18n build failed: ${err.message}`)
|
|
@@ -637,7 +683,9 @@ async function buildSiteLink(projectDir, options = {}) {
|
|
|
637
683
|
}
|
|
638
684
|
|
|
639
685
|
log('')
|
|
640
|
-
log(
|
|
686
|
+
log(
|
|
687
|
+
`${colors.green}${colors.bright}Build complete (link mode)${colors.reset}`
|
|
688
|
+
)
|
|
641
689
|
}
|
|
642
690
|
|
|
643
691
|
/**
|
|
@@ -656,7 +704,8 @@ async function resolveFoundationDirForSite(siteDir, siteConfig) {
|
|
|
656
704
|
if (!foundation || typeof foundation !== 'string') return null
|
|
657
705
|
// Registry ref or URL — no local foundation.
|
|
658
706
|
if (/^@[a-z0-9_-]+\/[a-z0-9_-]+@/.test(foundation)) return null
|
|
659
|
-
if (foundation.startsWith('http://') || foundation.startsWith('https://'))
|
|
707
|
+
if (foundation.startsWith('http://') || foundation.startsWith('https://'))
|
|
708
|
+
return null
|
|
660
709
|
|
|
661
710
|
// Workspace sibling.
|
|
662
711
|
const sibling = resolve(siteDir, '..', foundation)
|
|
@@ -670,7 +719,9 @@ async function resolveFoundationDirForSite(siteDir, siteConfig) {
|
|
|
670
719
|
const filePath = resolve(siteDir, dep.slice(5))
|
|
671
720
|
if (existsSync(filePath)) return filePath
|
|
672
721
|
}
|
|
673
|
-
} catch {
|
|
722
|
+
} catch {
|
|
723
|
+
/* no package.json or malformed — fall through */
|
|
724
|
+
}
|
|
674
725
|
|
|
675
726
|
return null
|
|
676
727
|
}
|
|
@@ -679,7 +730,12 @@ async function resolveFoundationDirForSite(siteDir, siteConfig) {
|
|
|
679
730
|
* Build a site
|
|
680
731
|
*/
|
|
681
732
|
async function buildSite(projectDir, options = {}) {
|
|
682
|
-
const {
|
|
733
|
+
const {
|
|
734
|
+
prerender = false,
|
|
735
|
+
foundationDir,
|
|
736
|
+
siteConfig = null,
|
|
737
|
+
host = null
|
|
738
|
+
} = options
|
|
683
739
|
|
|
684
740
|
info('Building site...')
|
|
685
741
|
|
|
@@ -721,16 +777,23 @@ async function buildSite(projectDir, options = {}) {
|
|
|
721
777
|
const collectionOutputs = await buildLocalizedCollections(projectDir, {
|
|
722
778
|
locales: i18nConfig.locales,
|
|
723
779
|
outputDir: join(projectDir, 'dist'),
|
|
724
|
-
collectionsLocalesDir: join(
|
|
780
|
+
collectionsLocalesDir: join(
|
|
781
|
+
projectDir,
|
|
782
|
+
i18nConfig.localesDir,
|
|
783
|
+
'collections'
|
|
784
|
+
)
|
|
725
785
|
})
|
|
726
786
|
|
|
727
787
|
// Count collections translated
|
|
728
788
|
const collectionCount = Object.values(collectionOutputs).reduce(
|
|
729
|
-
(sum, localeOutputs) => sum + Object.keys(localeOutputs).length,
|
|
789
|
+
(sum, localeOutputs) => sum + Object.keys(localeOutputs).length,
|
|
790
|
+
0
|
|
730
791
|
)
|
|
731
792
|
|
|
732
793
|
if (collectionCount > 0) {
|
|
733
|
-
success(
|
|
794
|
+
success(
|
|
795
|
+
`Translated collections for ${Object.keys(collectionOutputs).length} locale(s)`
|
|
796
|
+
)
|
|
734
797
|
}
|
|
735
798
|
} catch (err) {
|
|
736
799
|
// Collection translation is optional, don't fail build
|
|
@@ -757,12 +820,15 @@ async function buildSite(projectDir, options = {}) {
|
|
|
757
820
|
const { prerenderSite } = await import('@uniweb/build/prerender')
|
|
758
821
|
|
|
759
822
|
const result = await prerenderSite(projectDir, {
|
|
760
|
-
foundationDir:
|
|
823
|
+
foundationDir:
|
|
824
|
+
foundationDir || resolveFoundationDir(projectDir, siteConfig),
|
|
761
825
|
host,
|
|
762
826
|
onProgress: (msg) => log(` ${colors.dim}${msg}${colors.reset}`)
|
|
763
827
|
})
|
|
764
828
|
|
|
765
|
-
success(
|
|
829
|
+
success(
|
|
830
|
+
`Pre-rendered ${result.pages} page${result.pages !== 1 ? 's' : ''} to static HTML`
|
|
831
|
+
)
|
|
766
832
|
|
|
767
833
|
// Summary
|
|
768
834
|
log('')
|
|
@@ -780,13 +846,21 @@ async function buildSite(projectDir, options = {}) {
|
|
|
780
846
|
if (err.message.includes('Foundation not found')) {
|
|
781
847
|
log('')
|
|
782
848
|
log(`${colors.yellow}This usually means:${colors.reset}`)
|
|
783
|
-
log(
|
|
849
|
+
log(
|
|
850
|
+
` 1. The foundation hasn't been built yet (run foundation build first)`
|
|
851
|
+
)
|
|
784
852
|
log(` 2. The foundation name in site.yml doesn't match your setup`)
|
|
785
853
|
log('')
|
|
786
854
|
log(`${colors.dim}Check that:${colors.reset}`)
|
|
787
|
-
log(
|
|
788
|
-
|
|
789
|
-
|
|
855
|
+
log(
|
|
856
|
+
` • site.yml 'foundation:' matches the package name in your foundation's package.json`
|
|
857
|
+
)
|
|
858
|
+
log(
|
|
859
|
+
` • site's package.json has a dependency pointing to the correct foundation path`
|
|
860
|
+
)
|
|
861
|
+
log(
|
|
862
|
+
` • The foundation's dist/entry.js exists (build the foundation first)`
|
|
863
|
+
)
|
|
790
864
|
}
|
|
791
865
|
|
|
792
866
|
if (process.env.UNIWEB_DEBUG) {
|
|
@@ -861,9 +935,14 @@ async function buildWorkspace(workspaceDir, options = {}) {
|
|
|
861
935
|
log(`${colors.cyan}${colors.bright}Building workspace...${colors.reset}`)
|
|
862
936
|
log('')
|
|
863
937
|
|
|
864
|
-
const { foundations, extensions, sites } =
|
|
938
|
+
const { foundations, extensions, sites } =
|
|
939
|
+
await discoverWorkspacePackages(workspaceDir)
|
|
865
940
|
|
|
866
|
-
if (
|
|
941
|
+
if (
|
|
942
|
+
foundations.length === 0 &&
|
|
943
|
+
extensions.length === 0 &&
|
|
944
|
+
sites.length === 0
|
|
945
|
+
) {
|
|
867
946
|
error('No foundations, extensions, or sites found in workspace')
|
|
868
947
|
log('')
|
|
869
948
|
log('Expected structure (matching pnpm-workspace.yaml globs):')
|
|
@@ -884,7 +963,9 @@ async function buildWorkspace(workspaceDir, options = {}) {
|
|
|
884
963
|
// Build extensions (they are foundations, but logged distinctly)
|
|
885
964
|
for (const extension of extensions) {
|
|
886
965
|
const label = isExtensionDir(extension.path) ? 'extension' : 'foundation'
|
|
887
|
-
log(
|
|
966
|
+
log(
|
|
967
|
+
`${colors.bright}[${extension.name}]${colors.reset} ${colors.dim}(${label})${colors.reset}`
|
|
968
|
+
)
|
|
888
969
|
await buildFoundation(extension.path)
|
|
889
970
|
log('')
|
|
890
971
|
}
|
|
@@ -928,16 +1009,28 @@ function showNextSteps(hasFoundations, hasSites) {
|
|
|
928
1009
|
if (hasFoundations) {
|
|
929
1010
|
log('')
|
|
930
1011
|
log(`${colors.bright}Share with clients:${colors.reset}`)
|
|
931
|
-
log(
|
|
932
|
-
|
|
1012
|
+
log(
|
|
1013
|
+
` ${colors.bright}uniweb register${colors.reset} Release your foundation to the catalog (alias: uniweb release)`
|
|
1014
|
+
)
|
|
1015
|
+
log(
|
|
1016
|
+
` ${colors.bright}uniweb handoff <email>${colors.reset} Hand off a site to a client`
|
|
1017
|
+
)
|
|
933
1018
|
}
|
|
934
1019
|
if (hasSites) {
|
|
935
1020
|
log('')
|
|
936
1021
|
log(`${colors.bright}Ship a site:${colors.reset}`)
|
|
937
|
-
log(
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
log(
|
|
1022
|
+
log(
|
|
1023
|
+
` ${colors.bright}uniweb deploy${colors.reset} Pick a host and ship (asks where, then remembers)`
|
|
1024
|
+
)
|
|
1025
|
+
log(
|
|
1026
|
+
` ${colors.bright}uniweb add ci --host${colors.reset}=… Deploy on every push (free hosts; adds PR previews)`
|
|
1027
|
+
)
|
|
1028
|
+
log(
|
|
1029
|
+
` ${colors.bright}uniweb publish${colors.reset} Uniweb Cloud (brings the foundation along)`
|
|
1030
|
+
)
|
|
1031
|
+
log(
|
|
1032
|
+
` Or upload ${colors.cyan}dist/${colors.reset} (\`uniweb export\`) to any static host`
|
|
1033
|
+
)
|
|
941
1034
|
}
|
|
942
1035
|
}
|
|
943
1036
|
|
|
@@ -972,7 +1065,9 @@ export async function build(args = []) {
|
|
|
972
1065
|
const linkFlag = args.includes('--link')
|
|
973
1066
|
const bundleFlag = args.includes('--bundle')
|
|
974
1067
|
if (linkFlag && bundleFlag) {
|
|
975
|
-
error(
|
|
1068
|
+
error(
|
|
1069
|
+
'Cannot pass both --link and --bundle (they select different build pipelines)'
|
|
1070
|
+
)
|
|
976
1071
|
process.exit(1)
|
|
977
1072
|
}
|
|
978
1073
|
|
|
@@ -1010,7 +1105,9 @@ export async function build(args = []) {
|
|
|
1010
1105
|
|
|
1011
1106
|
if (!targetType) {
|
|
1012
1107
|
error('Could not detect project type')
|
|
1013
|
-
log(
|
|
1108
|
+
log(
|
|
1109
|
+
'Use --target foundation or --target site, or run from workspace root'
|
|
1110
|
+
)
|
|
1014
1111
|
process.exit(1)
|
|
1015
1112
|
}
|
|
1016
1113
|
|
|
@@ -1021,7 +1118,9 @@ export async function build(args = []) {
|
|
|
1021
1118
|
|
|
1022
1119
|
// Validate prerender flags are only used with site/workspace target
|
|
1023
1120
|
if ((prerenderFlag || noPrerenderFlag) && targetType === 'foundation') {
|
|
1024
|
-
error(
|
|
1121
|
+
error(
|
|
1122
|
+
'--prerender/--no-prerender can only be used with site or workspace builds'
|
|
1123
|
+
)
|
|
1025
1124
|
process.exit(1)
|
|
1026
1125
|
}
|
|
1027
1126
|
|
|
@@ -1052,7 +1151,9 @@ export async function build(args = []) {
|
|
|
1052
1151
|
// emitted (and what doesn't).
|
|
1053
1152
|
if (linkFlag) {
|
|
1054
1153
|
if (prerenderFlag) {
|
|
1055
|
-
error(
|
|
1154
|
+
error(
|
|
1155
|
+
'--prerender does not apply to link mode (no static HTML is produced)'
|
|
1156
|
+
)
|
|
1056
1157
|
process.exit(1)
|
|
1057
1158
|
}
|
|
1058
1159
|
await buildSiteLink(projectDir, { siteConfig })
|
|
@@ -1072,14 +1173,16 @@ export async function build(args = []) {
|
|
|
1072
1173
|
// to the local foundation when the user runs `uniweb build` from a
|
|
1073
1174
|
// site dir on a fresh checkout where dist/ doesn't exist yet.
|
|
1074
1175
|
const resolvedFoundationDir =
|
|
1075
|
-
foundationDir
|
|
1076
|
-
|
|
1176
|
+
foundationDir ||
|
|
1177
|
+
(await resolveFoundationDirForSite(projectDir, siteConfig).catch(
|
|
1178
|
+
() => null
|
|
1179
|
+
))
|
|
1077
1180
|
|
|
1078
1181
|
await buildSite(projectDir, {
|
|
1079
1182
|
prerender,
|
|
1080
1183
|
foundationDir: resolvedFoundationDir,
|
|
1081
1184
|
siteConfig,
|
|
1082
|
-
host
|
|
1185
|
+
host
|
|
1083
1186
|
})
|
|
1084
1187
|
}
|
|
1085
1188
|
} catch (err) {
|