webspresso 0.0.11 ā 0.0.12
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 +11 -0
- package/bin/webspresso.js +61 -3
- package/package.json +5 -4
- package/src/helpers.js +162 -0
package/README.md
CHANGED
|
@@ -715,6 +715,17 @@ The `fsy` object is available in all templates:
|
|
|
715
715
|
{{ fsy.prettyBytes(1024) }}
|
|
716
716
|
{{ fsy.prettyMs(5000) }}
|
|
717
717
|
|
|
718
|
+
{# Date/Time helpers (dayjs) #}
|
|
719
|
+
{{ fsy.dateFormat(post.created_at, 'YYYY-MM-DD HH:mm') }}
|
|
720
|
+
{{ fsy.dateFromNow(post.created_at) }} {# "2 hours ago" #}
|
|
721
|
+
{{ fsy.dateAgo(post.created_at) }} {# "2 hours ago" #}
|
|
722
|
+
{{ fsy.dateUntil(event.date) }} {# "in 2 hours" #}
|
|
723
|
+
{{ fsy.date(post.created_at).format('MMMM D, YYYY') }} {# Full dayjs API #}
|
|
724
|
+
{% if fsy.dateIsBefore(post.created_at, fsy.date()) %}Published{% endif %}
|
|
725
|
+
{{ fsy.dateDiff(post.created_at, fsy.date(), 'day') }} days ago
|
|
726
|
+
{{ fsy.dateAdd(post.created_at, 7, 'day').format('YYYY-MM-DD') }}
|
|
727
|
+
{{ fsy.dateStartOf(post.created_at, 'month').format('YYYY-MM-DD') }}
|
|
728
|
+
|
|
718
729
|
{# Environment #}
|
|
719
730
|
{% if fsy.isDev() %}Dev mode{% endif %}
|
|
720
731
|
|
package/bin/webspresso.js
CHANGED
|
@@ -9,7 +9,7 @@ const { program } = require('commander');
|
|
|
9
9
|
const inquirer = require('inquirer');
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
|
-
const { spawn } = require('child_process');
|
|
12
|
+
const { spawn, execSync } = require('child_process');
|
|
13
13
|
|
|
14
14
|
program
|
|
15
15
|
.name('webspresso')
|
|
@@ -1493,8 +1493,66 @@ program
|
|
|
1493
1493
|
faker = require('@faker-js/faker');
|
|
1494
1494
|
} catch {
|
|
1495
1495
|
console.error('ā @faker-js/faker not installed.');
|
|
1496
|
-
|
|
1497
|
-
|
|
1496
|
+
|
|
1497
|
+
// Check if it's in package.json
|
|
1498
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
1499
|
+
let shouldInstall = false;
|
|
1500
|
+
|
|
1501
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
1502
|
+
try {
|
|
1503
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
1504
|
+
const hasFaker = packageJson.dependencies?.['@faker-js/faker'] ||
|
|
1505
|
+
packageJson.devDependencies?.['@faker-js/faker'];
|
|
1506
|
+
|
|
1507
|
+
if (hasFaker) {
|
|
1508
|
+
console.log(' @faker-js/faker is in package.json but not installed.');
|
|
1509
|
+
console.log(' Run: npm install');
|
|
1510
|
+
process.exit(1);
|
|
1511
|
+
} else {
|
|
1512
|
+
// Ask if user wants to install it
|
|
1513
|
+
const { install } = await inquirer.prompt([
|
|
1514
|
+
{
|
|
1515
|
+
type: 'confirm',
|
|
1516
|
+
name: 'install',
|
|
1517
|
+
message: 'Install @faker-js/faker now?',
|
|
1518
|
+
default: true
|
|
1519
|
+
}
|
|
1520
|
+
]);
|
|
1521
|
+
|
|
1522
|
+
if (install) {
|
|
1523
|
+
shouldInstall = true;
|
|
1524
|
+
} else {
|
|
1525
|
+
console.log(' Install it manually with: npm install @faker-js/faker');
|
|
1526
|
+
process.exit(1);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
} catch (err) {
|
|
1530
|
+
console.log(' Install it with: npm install @faker-js/faker');
|
|
1531
|
+
process.exit(1);
|
|
1532
|
+
}
|
|
1533
|
+
} else {
|
|
1534
|
+
console.log(' Install it with: npm install @faker-js/faker');
|
|
1535
|
+
process.exit(1);
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
// Install faker if user confirmed
|
|
1539
|
+
if (shouldInstall) {
|
|
1540
|
+
console.log('\nš¦ Installing @faker-js/faker...\n');
|
|
1541
|
+
try {
|
|
1542
|
+
execSync('npm install @faker-js/faker', {
|
|
1543
|
+
stdio: 'inherit',
|
|
1544
|
+
cwd: process.cwd()
|
|
1545
|
+
});
|
|
1546
|
+
console.log('\nā
@faker-js/faker installed successfully!\n');
|
|
1547
|
+
|
|
1548
|
+
// Try to require again
|
|
1549
|
+
faker = require('@faker-js/faker');
|
|
1550
|
+
} catch (err) {
|
|
1551
|
+
console.error('\nā Failed to install @faker-js/faker:', err.message);
|
|
1552
|
+
console.log(' Install it manually with: npm install @faker-js/faker');
|
|
1553
|
+
process.exit(1);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1498
1556
|
}
|
|
1499
1557
|
|
|
1500
1558
|
// Load database config
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webspresso",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "Minimal, production-ready SSR framework for Node.js with file-based routing, Nunjucks templating, built-in i18n, and CLI tooling",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"commander": "^11.1.0",
|
|
41
|
+
"dayjs": "^1.11.19",
|
|
41
42
|
"express": "^4.18.2",
|
|
42
43
|
"helmet": "^7.2.0",
|
|
43
44
|
"inquirer": "^8.2.6",
|
|
@@ -46,11 +47,11 @@
|
|
|
46
47
|
"zod": "^3.23.0"
|
|
47
48
|
},
|
|
48
49
|
"peerDependencies": {
|
|
50
|
+
"@faker-js/faker": "^9.0.0",
|
|
51
|
+
"better-sqlite3": "^9.0.0",
|
|
49
52
|
"dotenv": "^16.0.0",
|
|
50
|
-
"pg": "^8.0.0",
|
|
51
53
|
"mysql2": "^3.0.0",
|
|
52
|
-
"
|
|
53
|
-
"@faker-js/faker": "^9.0.0"
|
|
54
|
+
"pg": "^8.0.0"
|
|
54
55
|
},
|
|
55
56
|
"peerDependenciesMeta": {
|
|
56
57
|
"dotenv": {
|
package/src/helpers.js
CHANGED
|
@@ -6,6 +6,17 @@
|
|
|
6
6
|
const querystring = require('querystring');
|
|
7
7
|
const fs = require('fs');
|
|
8
8
|
const path = require('path');
|
|
9
|
+
const dayjs = require('dayjs');
|
|
10
|
+
const relativeTime = require('dayjs/plugin/relativeTime');
|
|
11
|
+
const utc = require('dayjs/plugin/utc');
|
|
12
|
+
const timezone = require('dayjs/plugin/timezone');
|
|
13
|
+
const customParseFormat = require('dayjs/plugin/customParseFormat');
|
|
14
|
+
|
|
15
|
+
// Extend dayjs with plugins
|
|
16
|
+
dayjs.extend(relativeTime);
|
|
17
|
+
dayjs.extend(utc);
|
|
18
|
+
dayjs.extend(timezone);
|
|
19
|
+
dayjs.extend(customParseFormat);
|
|
9
20
|
|
|
10
21
|
/**
|
|
11
22
|
* Asset Manager - handles asset paths, versioning, and manifest
|
|
@@ -419,6 +430,157 @@ function createHelpers(ctx) {
|
|
|
419
430
|
*/
|
|
420
431
|
img(src, alt = '', attrs = {}) {
|
|
421
432
|
return getAssetManager().img(src, alt, attrs);
|
|
433
|
+
},
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Date/time helpers using dayjs
|
|
437
|
+
*/
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Create a dayjs instance from a date
|
|
441
|
+
* @param {string|Date|number} date - Date to parse
|
|
442
|
+
* @param {string} format - Optional format string
|
|
443
|
+
* @returns {Object} dayjs instance
|
|
444
|
+
*/
|
|
445
|
+
date(date, format) {
|
|
446
|
+
if (!date) return dayjs();
|
|
447
|
+
if (format) {
|
|
448
|
+
return dayjs(date, format);
|
|
449
|
+
}
|
|
450
|
+
return dayjs(date);
|
|
451
|
+
},
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Format a date
|
|
455
|
+
* @param {string|Date|number} date - Date to format
|
|
456
|
+
* @param {string} format - Format string (default: 'YYYY-MM-DD')
|
|
457
|
+
* @returns {string}
|
|
458
|
+
*/
|
|
459
|
+
dateFormat(date, format = 'YYYY-MM-DD') {
|
|
460
|
+
if (!date) return '';
|
|
461
|
+
return dayjs(date).format(format);
|
|
462
|
+
},
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Get relative time (e.g., "2 hours ago")
|
|
466
|
+
* @param {string|Date|number} date - Date to format
|
|
467
|
+
* @returns {string}
|
|
468
|
+
*/
|
|
469
|
+
dateFromNow(date) {
|
|
470
|
+
if (!date) return '';
|
|
471
|
+
return dayjs(date).fromNow();
|
|
472
|
+
},
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Get time ago (e.g., "2 hours ago")
|
|
476
|
+
* @param {string|Date|number} date - Date to format
|
|
477
|
+
* @returns {string}
|
|
478
|
+
*/
|
|
479
|
+
dateAgo(date) {
|
|
480
|
+
if (!date) return '';
|
|
481
|
+
return dayjs(date).fromNow();
|
|
482
|
+
},
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Get time until (e.g., "in 2 hours")
|
|
486
|
+
* @param {string|Date|number} date - Date to format
|
|
487
|
+
* @returns {string}
|
|
488
|
+
*/
|
|
489
|
+
dateUntil(date) {
|
|
490
|
+
if (!date) return '';
|
|
491
|
+
return dayjs(date).toNow();
|
|
492
|
+
},
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Check if date is before another date
|
|
496
|
+
* @param {string|Date|number} date1 - First date
|
|
497
|
+
* @param {string|Date|number} date2 - Second date
|
|
498
|
+
* @returns {boolean}
|
|
499
|
+
*/
|
|
500
|
+
dateIsBefore(date1, date2) {
|
|
501
|
+
if (!date1 || !date2) return false;
|
|
502
|
+
return dayjs(date1).isBefore(date2);
|
|
503
|
+
},
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Check if date is after another date
|
|
507
|
+
* @param {string|Date|number} date1 - First date
|
|
508
|
+
* @param {string|Date|number} date2 - Second date
|
|
509
|
+
* @returns {boolean}
|
|
510
|
+
*/
|
|
511
|
+
dateIsAfter(date1, date2) {
|
|
512
|
+
if (!date1 || !date2) return false;
|
|
513
|
+
return dayjs(date1).isAfter(date2);
|
|
514
|
+
},
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Check if date is same as another date
|
|
518
|
+
* @param {string|Date|number} date1 - First date
|
|
519
|
+
* @param {string|Date|number} date2 - Second date
|
|
520
|
+
* @param {string} unit - Unit to compare (day, month, year, etc.)
|
|
521
|
+
* @returns {boolean}
|
|
522
|
+
*/
|
|
523
|
+
dateIsSame(date1, date2, unit = 'day') {
|
|
524
|
+
if (!date1 || !date2) return false;
|
|
525
|
+
return dayjs(date1).isSame(date2, unit);
|
|
526
|
+
},
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Get difference between two dates
|
|
530
|
+
* @param {string|Date|number} date1 - First date
|
|
531
|
+
* @param {string|Date|number} date2 - Second date
|
|
532
|
+
* @param {string} unit - Unit (day, month, year, hour, minute, second)
|
|
533
|
+
* @returns {number}
|
|
534
|
+
*/
|
|
535
|
+
dateDiff(date1, date2, unit = 'day') {
|
|
536
|
+
if (!date1 || !date2) return 0;
|
|
537
|
+
return dayjs(date1).diff(date2, unit);
|
|
538
|
+
},
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Add time to a date
|
|
542
|
+
* @param {string|Date|number} date - Date to add to
|
|
543
|
+
* @param {number} amount - Amount to add
|
|
544
|
+
* @param {string} unit - Unit (day, month, year, hour, minute, second)
|
|
545
|
+
* @returns {Object} dayjs instance
|
|
546
|
+
*/
|
|
547
|
+
dateAdd(date, amount, unit = 'day') {
|
|
548
|
+
if (!date) return dayjs();
|
|
549
|
+
return dayjs(date).add(amount, unit);
|
|
550
|
+
},
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Subtract time from a date
|
|
554
|
+
* @param {string|Date|number} date - Date to subtract from
|
|
555
|
+
* @param {number} amount - Amount to subtract
|
|
556
|
+
* @param {string} unit - Unit (day, month, year, hour, minute, second)
|
|
557
|
+
* @returns {Object} dayjs instance
|
|
558
|
+
*/
|
|
559
|
+
dateSubtract(date, amount, unit = 'day') {
|
|
560
|
+
if (!date) return dayjs();
|
|
561
|
+
return dayjs(date).subtract(amount, unit);
|
|
562
|
+
},
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Get start of a time period
|
|
566
|
+
* @param {string|Date|number} date - Date
|
|
567
|
+
* @param {string} unit - Unit (day, month, year, week)
|
|
568
|
+
* @returns {Object} dayjs instance
|
|
569
|
+
*/
|
|
570
|
+
dateStartOf(date, unit = 'day') {
|
|
571
|
+
if (!date) return dayjs();
|
|
572
|
+
return dayjs(date).startOf(unit);
|
|
573
|
+
},
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Get end of a time period
|
|
577
|
+
* @param {string|Date|number} date - Date
|
|
578
|
+
* @param {string} unit - Unit (day, month, year, week)
|
|
579
|
+
* @returns {Object} dayjs instance
|
|
580
|
+
*/
|
|
581
|
+
dateEndOf(date, unit = 'day') {
|
|
582
|
+
if (!date) return dayjs();
|
|
583
|
+
return dayjs(date).endOf(unit);
|
|
422
584
|
}
|
|
423
585
|
};
|
|
424
586
|
}
|