create-portfoliable 1.2.18 → 1.3.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.
@@ -16,6 +16,7 @@ import {
16
16
  readProjectUiPreferences,
17
17
  writeProjectUiPreferences
18
18
  } from '../scripts/terminal-ui.mjs';
19
+ import { findPackageUpdates } from '../scripts/package-updates.mjs';
19
20
 
20
21
  // MARK: DEFAULTS
21
22
  // Defines default target folder when no project name is provided.
@@ -385,6 +386,24 @@ async function run() {
385
386
  printRailSegment({ dot: true, label: `${color('32', 'Dependencies installed.')}` });
386
387
  console.log(color('36', 'Command guide is available after launch via interactive prompt.'));
387
388
 
389
+ const installedPackages = [
390
+ ['create-portfoliable', path.resolve(targetDir, 'node_modules', 'create-portfoliable', 'package.json')],
391
+ ['@portfoliablejs/valence', path.resolve(targetDir, 'node_modules', '@portfoliablejs', 'valence', 'package.json')]
392
+ ].flatMap(([name, packagePath]) => {
393
+ try {
394
+ return [{ name, currentVersion: JSON.parse(fs.readFileSync(packagePath, 'utf8')).version }];
395
+ } catch {
396
+ return [];
397
+ }
398
+ });
399
+ const updates = await findPackageUpdates(installedPackages);
400
+ for (const update of updates) {
401
+ const isValence = update.name === '@portfoliablejs/valence';
402
+ const label = isValence ? 'design system' : 'Portfoliable';
403
+ console.log(color('33', `A new ${label} update (${update.latestVersion}) is available.`));
404
+ console.log(`Run: ${color('32', `npm update ${update.name}`)}`);
405
+ }
406
+
388
407
  if (options.launch) {
389
408
  printRailSegment();
390
409
  printRailSegment({ dot: true, label: `${color('36', 'Preparing first build...')}` });
@@ -27,6 +27,7 @@ import {
27
27
  readProjectUiPreferences
28
28
  } from '../scripts/terminal-ui.mjs';
29
29
  import { resolveConsumerRuntimeAliases } from '../scripts/consumer-runtime-aliases.mjs';
30
+ import { findPackageUpdates } from '../scripts/package-updates.mjs';
30
31
 
31
32
  function resolveMermaidDevAliases(runtimeAliases) {
32
33
  return [
@@ -83,21 +84,6 @@ function firstNetworkAddress() {
83
84
  return null;
84
85
  }
85
86
 
86
- // Fetches latest published create-portfoliable version from npm registry.
87
- async function fetchLatestVersion() {
88
- try {
89
- // Calls npm metadata endpoint for latest dist-tag payload.
90
- const response = await fetch('https://registry.npmjs.org/create-portfoliable/latest');
91
- if (!response.ok) return null;
92
-
93
- // Parses registry response payload.
94
- const data = await response.json();
95
- return data.version || null;
96
- } catch {
97
- return null;
98
- }
99
- }
100
-
101
87
  // MARK: CLI ARGUMENT PARSING
102
88
  // Parses command and flags from argv into normalized runtime options.
103
89
  function parseCliArgs(argv) {
@@ -496,7 +482,7 @@ function createCaseContentAssetPlugin() {
496
482
  }
497
483
 
498
484
  // Prints startup summary box for dev server sessions.
499
- function printStartupBox({ localUrl, networkUrl, localVersion, latestVersion }) {
485
+ function printStartupBox({ localUrl, networkUrl, updates }) {
500
486
  const lines = [
501
487
  `${green}${bold}Portfoliable ready!${reset}`,
502
488
  `${dim}Dev server is live and ready for editing.${reset}`,
@@ -507,13 +493,20 @@ function printStartupBox({ localUrl, networkUrl, localVersion, latestVersion })
507
493
  `${bold}Next:${reset} open the local URL in your browser.`
508
494
  ];
509
495
 
510
- if (latestVersion && latestVersion !== localVersion && !latestVersion.includes('alpha')) {
496
+ for (const update of updates) {
511
497
  lines.push('');
512
- lines.push(`${yellow}A new version (${latestVersion}) is available!${reset}`);
513
- lines.push(`Upgrade now: ${green}npm update create-portfoliable${reset}`);
514
- lines.push(`If it still persists, run: ${green}npm install create-portfoliable@latest${reset}`);
498
+ const isValence = update.name === '@portfoliablejs/valence';
499
+ const packageLabel = isValence ? 'design system' : 'Portfoliable';
500
+ lines.push(`${yellow}A new ${packageLabel} update (${update.latestVersion}) is available!${reset}`);
501
+ lines.push(`Upgrade now: ${green}npm update ${update.name}${reset}`);
502
+ if (!isValence) {
503
+ lines.push(`If it still persists, run: ${green}npm install ${update.name}@latest${reset}`);
504
+ }
515
505
  lines.push('Read changelog:');
516
- lines.push(`${dim}https://github.com/portfoliablejs/portfoliable/blob/main/CHANGELOG.md${reset}`);
506
+ const changelogUrl = isValence
507
+ ? 'https://github.com/portfoliablejs/valence/blob/main/CHANGELOG.md'
508
+ : 'https://github.com/portfoliablejs/portfoliable/blob/main/CHANGELOG.md';
509
+ lines.push(`${dim}${changelogUrl}${reset}`);
517
510
  }
518
511
 
519
512
  printRailAttachedBox({ width: 96, lines });
@@ -634,15 +627,24 @@ async function runDevServer(flags, options = {}) {
634
627
 
635
628
  // Resolves currently running CLI package version.
636
629
  const localVersion = resolvePackageVersion();
637
- // Fetches latest published package version.
638
- const latestVersion = await fetchLatestVersion();
630
+ const valencePackagePath = path.resolve(process.cwd(), 'node_modules', '@portfoliablejs', 'valence', 'package.json');
631
+ let valenceVersion = null;
632
+ try {
633
+ valenceVersion = JSON.parse(fs.readFileSync(valencePackagePath, 'utf8')).version || null;
634
+ } catch {
635
+ valenceVersion = null;
636
+ }
637
+ const updates = await findPackageUpdates([
638
+ { name: 'create-portfoliable', currentVersion: localVersion },
639
+ ...(valenceVersion ? [{ name: '@portfoliablejs/valence', currentVersion: valenceVersion }] : [])
640
+ ]);
639
641
 
640
642
  if (fancyDots) {
641
643
  printRailSegment({ dot: true, label: `${cyan}${bold}Starting...${reset}` });
642
644
  printRailSpacer();
643
645
  }
644
646
 
645
- printStartupBox({ localUrl, networkUrl, localVersion, latestVersion });
647
+ printStartupBox({ localUrl, networkUrl, updates });
646
648
 
647
649
  if (isInteractiveTerminal() && flags.open !== false) {
648
650
  let showCommands = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-portfoliable",
3
- "version": "1.2.18",
3
+ "version": "1.3.0",
4
4
  "description": "Unified Portfoliable package with initializer and runtime CLI",
5
5
  "private": false,
6
6
  "type": "module",
@@ -0,0 +1,41 @@
1
+ const PACKAGE_REGISTRY_URL = 'https://registry.npmjs.org';
2
+
3
+ function parseVersion(version) {
4
+ const match = String(version || '').trim().match(/^(\d+)\.(\d+)\.(\d+)/);
5
+ return match ? match.slice(1).map(Number) : null;
6
+ }
7
+
8
+ function isNewerVersion(latestVersion, currentVersion) {
9
+ const latest = parseVersion(latestVersion);
10
+ const current = parseVersion(currentVersion);
11
+ if (!latest || !current) return false;
12
+
13
+ for (let index = 0; index < latest.length; index += 1) {
14
+ if (latest[index] !== current[index]) return latest[index] > current[index];
15
+ }
16
+
17
+ return false;
18
+ }
19
+
20
+ export async function fetchLatestPackageVersion(packageName) {
21
+ try {
22
+ const response = await fetch(`${PACKAGE_REGISTRY_URL}/${encodeURIComponent(packageName)}/latest`);
23
+ if (!response.ok) return null;
24
+
25
+ const data = await response.json();
26
+ return data.version || null;
27
+ } catch {
28
+ return null;
29
+ }
30
+ }
31
+
32
+ export async function findPackageUpdates(packages) {
33
+ const updates = await Promise.all(packages.map(async ({ name, currentVersion }) => {
34
+ const latestVersion = await fetchLatestPackageVersion(name);
35
+ if (!latestVersion || !isNewerVersion(latestVersion, currentVersion)) return null;
36
+
37
+ return { name, currentVersion, latestVersion };
38
+ }));
39
+
40
+ return updates.filter(Boolean);
41
+ }