asjs-express 1.5.0 → 1.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asjs-express",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Lightweight Express view engine with EJS-like templates, layouts, async page rendering, form enhancement, and a built-in client router.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -4,15 +4,12 @@ const { setupAsjs } = require('asjs-express');
4
4
  const app = express();
5
5
  const port = process.env.PORT || __PORT__;
6
6
 
7
- app.use(express.urlencoded({ extended: false }));
8
-
9
7
  const asjs = setupAsjs(app, {
10
8
  rootDir: __dirname,
11
9
  defaultLayout: 'layouts/main',
12
10
  navItems: [
13
11
  { href: '/', label: 'Home', activeMode: 'exact' },
14
- { href: '/about', label: 'About', activeMode: 'exact' },
15
- { href: '/contact', label: 'Contact', activeMode: 'exact' }
12
+ { href: '/about', label: 'About', activeMode: 'exact' }
16
13
  ],
17
14
  brand: {
18
15
  href: '/',
@@ -25,32 +22,30 @@ const asjs = setupAsjs(app, {
25
22
  loadingBar: true
26
23
  });
27
24
 
28
- // Home
29
25
  app.get('/', asjs.page('home', {
30
26
  title: '__APP_TITLE__',
31
27
  headline: 'Welcome to __APP_TITLE__',
32
- description: 'A three-page starter built with ASJS and Express. SPA navigation, smooth transitions, and server-rendered pages are already set up.',
28
+ description: 'A starter built with ASJS and Express. SPA navigation, smooth transitions, and server-rendered pages are ready out of the box.',
33
29
  features: [
34
30
  {
35
31
  label: 'SPA Navigation',
36
- text: 'Pages swap without a full reload. The header and layout stay in place while only the content area changes.'
32
+ text: 'Pages swap without a full reload. The header and layout stay in place while only the content changes.'
37
33
  },
38
34
  {
39
35
  label: 'Server Rendering',
40
- text: 'Each page is fully rendered on the server. Route data is prepared in the callback before the HTML response is sent.'
36
+ text: 'Each page is fully rendered on the server before it reaches the browser. Route data is prepared in the callback.'
41
37
  },
42
38
  {
43
- label: 'Form Handling',
44
- text: 'Forms submit to the server and return a new rendered state. Validation errors are shown without losing the page shell.'
39
+ label: 'Zero Build Step',
40
+ text: 'No bundler, no compiler. Write EJS-style templates and run with Node. It just works.'
45
41
  }
46
42
  ]
47
43
  }));
48
44
 
49
- // About
50
45
  app.get('/about', asjs.page('about', {
51
46
  title: 'About — __APP_TITLE__',
52
- headline: 'About this project',
53
- description: 'This app is built with ASJS on top of Express. ASJS adds layouts, async page models, client-side transitions, and form helpers without a front-end build step.',
47
+ headline: 'About __APP_TITLE__',
48
+ description: 'Built with ASJS on top of Express. Layouts, async page models, client-side transitions, and a loading bar — without a front-end build step.',
54
49
  facts: [
55
50
  { label: 'Engine', value: 'ASJS __ASJS_VERSION__' },
56
51
  { label: 'Framework', value: 'Express' },
@@ -66,66 +61,8 @@ app.get('/about', asjs.page('about', {
66
61
  ]
67
62
  }));
68
63
 
69
- // Contact — GET
70
- const contactInitialState = {
71
- title: 'Contact — __APP_TITLE__',
72
- headline: 'Get in touch',
73
- description: 'Send a message using the form below. This form is handled on the server and returns a validation state or a success state.',
74
- formValues: { name: '', email: '', message: '' },
75
- formErrors: {},
76
- submitted: false
77
- };
78
-
79
- app.get('/contact', asjs.page('contact', contactInitialState));
80
-
81
- // Contact — POST
82
- app.post('/contact', asjs.createPageRoute('contact', {}, async (req) => {
83
- const formValues = asjs.normalizeFields(req.body, ['name', 'email', 'message']);
84
- const formErrors = asjs.validateFields(formValues, {
85
- name: {
86
- required: 'Please enter your name.'
87
- },
88
- email: {
89
- required: 'Please enter your email address.',
90
- pattern: {
91
- value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
92
- message: 'Please enter a valid email address.'
93
- }
94
- },
95
- message: {
96
- required: 'Please write a message.',
97
- minLength: {
98
- value: 10,
99
- message: 'Please write at least 10 characters.'
100
- }
101
- }
102
- });
103
-
104
- if (asjs.hasValidationErrors(formErrors)) {
105
- return {
106
- status: 422,
107
- title: 'Contact — __APP_TITLE__',
108
- headline: 'Get in touch',
109
- description: 'A few fields need attention before the form can be sent.',
110
- formValues,
111
- formErrors,
112
- submitted: false
113
- };
114
- }
115
-
116
- return {
117
- title: 'Message sent — __APP_TITLE__',
118
- headline: 'Message received',
119
- description: 'Your message has been received. This is a starter demo — no real email was sent.',
120
- formValues: contactInitialState.formValues,
121
- formErrors: {},
122
- submitted: true,
123
- sentValues: formValues
124
- };
125
- }));
126
-
127
64
  app.use(asjs.errors());
128
65
 
129
66
  app.listen(port, () => {
130
- console.log('__APP_TITLE__ is running at http://localhost:' + port);
67
+ console.log('__APP_TITLE__ running at http://localhost:' + port);
131
68
  });
@@ -23,6 +23,5 @@
23
23
  </ul>
24
24
  <div class="hero-actions" style="margin-top: 24px;">
25
25
  <a href="/" class="button button-primary" data-asjs-transition="fade">Back to home</a>
26
- <a href="/contact" class="button button-secondary" data-asjs-transition="fade">Contact</a>
27
26
  </div>
28
- </div>
27
+ </div>
@@ -4,7 +4,6 @@
4
4
  <p><%= description %></p>
5
5
  <div class="hero-actions">
6
6
  <a href="/about" class="button button-primary" data-asjs-transition="fade">Learn more</a>
7
- <a href="/contact" class="button button-secondary" data-asjs-transition="fade">Get in touch</a>
8
7
  </div>
9
8
  </div>
10
9
 
@@ -1,53 +0,0 @@
1
- <% if (locals.submitted) { %>
2
- <div class="section-card status-panel--success" style="margin-top: 0;">
3
- <span class="section-label" style="background: #dcfce7; color: #15803d;">Sent</span>
4
- <h2 style="margin-top: 14px; letter-spacing: -0.04em;"><%= headline %></h2>
5
- <p><%= description %></p>
6
- <div class="render-summary-grid" style="margin-top: 20px;">
7
- <div class="render-item">
8
- <span>Name</span>
9
- <strong><%= sentValues.name %></strong>
10
- </div>
11
- <div class="render-item">
12
- <span>Email</span>
13
- <strong><%= sentValues.email %></strong>
14
- </div>
15
- </div>
16
- <div class="hero-actions" style="margin-top: 24px;">
17
- <a href="/" class="button button-primary" data-asjs-transition="fade">Back to home</a>
18
- <a href="/contact" class="button button-secondary" data-asjs-transition="fade">Send another</a>
19
- </div>
20
- </div>
21
- <% } else { %>
22
- <div class="page-intro">
23
- <span class="section-label">Contact</span>
24
- <h1><%= headline %></h1>
25
- <p><%= description %></p>
26
- </div>
27
-
28
- <div class="section-card form-panel">
29
- <form class="webas-form" method="POST" action="/contact">
30
- <div class="field-grid">
31
- <div class="field-group">
32
- <span>Name</span>
33
- <input type="text" name="name" value="<%= formValues.name %>" placeholder="Your name" autocomplete="name">
34
- <% if (formErrors.name) { %><span class="field-error"><%= formErrors.name %></span><% } %>
35
- </div>
36
- <div class="field-group">
37
- <span>Email</span>
38
- <input type="email" name="email" value="<%= formValues.email %>" placeholder="you@example.com" autocomplete="email">
39
- <% if (formErrors.email) { %><span class="field-error"><%= formErrors.email %></span><% } %>
40
- </div>
41
- </div>
42
- <div class="field-group">
43
- <span>Message</span>
44
- <textarea name="message" placeholder="Your message (at least 10 characters)"><%= formValues.message %></textarea>
45
- <% if (formErrors.message) { %><span class="field-error"><%= formErrors.message %></span><% } %>
46
- </div>
47
- <div class="form-actions">
48
- <button type="submit" class="button button-primary">Send message</button>
49
- <span>The form is validated on the server before the page re-renders.</span>
50
- </div>
51
- </form>
52
- </div>
53
- <% } %>