@invisibleloop/pulse 0.5.0 → 0.5.1
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/docs/src/pages/accessibility.js +0 -1
- package/docs/src/pages/auth.js +0 -2
- package/docs/src/pages/caching.js +0 -1
- package/docs/src/pages/components/accordion.js +0 -1
- package/docs/src/pages/components/alert.js +0 -1
- package/docs/src/pages/components/app-badge.js +0 -1
- package/docs/src/pages/components/avatar.js +0 -1
- package/docs/src/pages/components/badge.js +0 -1
- package/docs/src/pages/components/banner.js +0 -1
- package/docs/src/pages/components/breadcrumbs.js +0 -1
- package/docs/src/pages/components/button.js +0 -1
- package/docs/src/pages/components/card.js +0 -1
- package/docs/src/pages/components/carousel.js +0 -1
- package/docs/src/pages/components/charts.js +0 -1
- package/docs/src/pages/components/checkbox.js +0 -1
- package/docs/src/pages/components/cluster.js +0 -1
- package/docs/src/pages/components/code-window.js +0 -1
- package/docs/src/pages/components/container.js +0 -1
- package/docs/src/pages/components/divider.js +0 -1
- package/docs/src/pages/components/empty.js +0 -1
- package/docs/src/pages/components/feature.js +0 -1
- package/docs/src/pages/components/fieldset.js +0 -1
- package/docs/src/pages/components/footer.js +0 -1
- package/docs/src/pages/components/grid.js +0 -1
- package/docs/src/pages/components/heading.js +0 -1
- package/docs/src/pages/components/icons.js +0 -1
- package/docs/src/pages/components/image.js +0 -1
- package/docs/src/pages/components/input.js +0 -1
- package/docs/src/pages/components/list.js +0 -1
- package/docs/src/pages/components/media.js +0 -1
- package/docs/src/pages/components/modal.js +0 -1
- package/docs/src/pages/components/nav.js +0 -1
- package/docs/src/pages/components/pricing.js +0 -1
- package/docs/src/pages/components/progress.js +0 -1
- package/docs/src/pages/components/prose.js +0 -1
- package/docs/src/pages/components/pullquote.js +0 -1
- package/docs/src/pages/components/radio.js +0 -1
- package/docs/src/pages/components/rating.js +0 -1
- package/docs/src/pages/components/search.js +0 -1
- package/docs/src/pages/components/section.js +0 -1
- package/docs/src/pages/components/segmented.js +0 -1
- package/docs/src/pages/components/select.js +0 -1
- package/docs/src/pages/components/spinner.js +0 -1
- package/docs/src/pages/components/stack.js +0 -1
- package/docs/src/pages/components/stat.js +0 -1
- package/docs/src/pages/components/stepper.js +0 -1
- package/docs/src/pages/components/table.js +0 -1
- package/docs/src/pages/components/testimonial.js +0 -1
- package/docs/src/pages/components/textarea.js +0 -1
- package/docs/src/pages/components/timeline.js +0 -1
- package/docs/src/pages/components/toggle.js +0 -1
- package/docs/src/pages/components/tooltip.js +0 -1
- package/docs/src/pages/components.js +0 -1
- package/docs/src/pages/config.js +0 -1
- package/docs/src/pages/deploy.js +0 -1
- package/docs/src/pages/extending.js +0 -1
- package/docs/src/pages/faq.js +0 -1
- package/docs/src/pages/getting-started.js +0 -1
- package/docs/src/pages/guard.js +0 -3
- package/docs/src/pages/how-it-works.js +0 -1
- package/docs/src/pages/images.js +0 -2
- package/docs/src/pages/meta.js +0 -2
- package/docs/src/pages/navigation.js +0 -1
- package/docs/src/pages/performance.js +0 -2
- package/docs/src/pages/project-structure.js +0 -2
- package/docs/src/pages/prompt-examples.js +0 -1
- package/docs/src/pages/raw-responses.js +0 -4
- package/docs/src/pages/routing.js +0 -2
- package/docs/src/pages/server-api.js +0 -2
- package/docs/src/pages/server-data.js +0 -1
- package/docs/src/pages/slash-commands.js +0 -1
- package/docs/src/pages/spec.js +1 -0
- package/docs/src/pages/streaming.js +0 -2
- package/docs/src/pages/testing.js +0 -1
- package/docs/src/pages/validation.js +0 -1
- package/package.json +1 -1
- package/public/.pulse-ui-version +1 -1
- package/src/spec/schema.js +5 -0
package/docs/src/pages/auth.js
CHANGED
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Integrating Auth0 OAuth authentication with Pulse using guard functions, ctx.setCookie, and raw response specs.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/auth',
|
|
17
16
|
prev,
|
|
@@ -141,7 +140,6 @@ export default {
|
|
|
141
140
|
profile: async (ctx) => fetchUserProfile(ctx.cookies.session),
|
|
142
141
|
},
|
|
143
142
|
|
|
144
|
-
state: {},
|
|
145
143
|
view: (state, server) => \`
|
|
146
144
|
<main id="main-content">
|
|
147
145
|
<h1>Welcome, \${server.profile.name}</h1>
|
|
@@ -12,7 +12,6 @@ export default {
|
|
|
12
12
|
description: 'macOS-style window chrome around a code block. Accepts pre-highlighted HTML as the content slot.',
|
|
13
13
|
styles: ['/pulse-ui.css', '/docs.css'],
|
|
14
14
|
},
|
|
15
|
-
state: {},
|
|
16
15
|
view: () => renderComponentPage({
|
|
17
16
|
currentHref: '/components/code-window',
|
|
18
17
|
prev,
|
|
@@ -12,7 +12,6 @@ export default {
|
|
|
12
12
|
description: 'Responsive image component with optional aspect-ratio crop and caption for Pulse UI.',
|
|
13
13
|
styles: ['/pulse-ui.css', '/docs.css'],
|
|
14
14
|
},
|
|
15
|
-
state: {},
|
|
16
15
|
view: () => renderComponentPage({
|
|
17
16
|
currentHref: '/components/image',
|
|
18
17
|
prev,
|
|
@@ -12,7 +12,6 @@ export default {
|
|
|
12
12
|
description: 'Vertical padding wrapper with optional background. Compose with container() for full-width background with constrained content.',
|
|
13
13
|
styles: ['/pulse-ui.css', '/docs.css'],
|
|
14
14
|
},
|
|
15
|
-
state: {},
|
|
16
15
|
view: () => renderComponentPage({
|
|
17
16
|
currentHref: '/components/section',
|
|
18
17
|
prev,
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Server-rendered UI components for Pulse — button, card, input, alert, stat, avatar, table and more. Fully accessible, mobile-ready, zero client JS.',
|
|
12
12
|
styles: ['/pulse-ui.css', '/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/components',
|
|
17
16
|
prev,
|
package/docs/src/pages/config.js
CHANGED
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Full reference for pulse.config.js — port, Lighthouse thresholds, load test config, environments, and per-route overrides.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/config',
|
|
17
16
|
prev,
|
package/docs/src/pages/deploy.js
CHANGED
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Escape hatches for features outside the Pulse spec — onRequest middleware, raw server access, WebSockets, SSE, and custom error handling.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/extending',
|
|
17
16
|
prev,
|
package/docs/src/pages/faq.js
CHANGED
package/docs/src/pages/guard.js
CHANGED
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Per-route authorization in Pulse. Guard functions run before server data fetchers and redirect unauthorized requests.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/guard',
|
|
17
16
|
prev,
|
|
@@ -33,7 +32,6 @@ export default {
|
|
|
33
32
|
user: async (ctx) => getCurrentUser(ctx.cookies.session),
|
|
34
33
|
},
|
|
35
34
|
|
|
36
|
-
state: {},
|
|
37
35
|
view: (state, server) => \`
|
|
38
36
|
<main id="main-content">
|
|
39
37
|
<h1>Welcome, \${server.user.name}</h1>
|
|
@@ -87,7 +85,6 @@ export default {
|
|
|
87
85
|
if (ctx.cookies.session) return { redirect: '/dashboard' }
|
|
88
86
|
},
|
|
89
87
|
|
|
90
|
-
state: {},
|
|
91
88
|
view: () => \`<main id="main-content">...</main>\`,
|
|
92
89
|
}`, 'js'))}
|
|
93
90
|
|
|
@@ -70,7 +70,6 @@ export default {
|
|
|
70
70
|
description: 'How the Pulse MCP server gives an AI agent the knowledge and tools to build Pulse apps correctly.',
|
|
71
71
|
styles: ['/pulse-ui.css', '/docs.css'],
|
|
72
72
|
},
|
|
73
|
-
state: {},
|
|
74
73
|
view: () => renderLayout({
|
|
75
74
|
currentHref: '/how-it-works',
|
|
76
75
|
prev,
|
package/docs/src/pages/images.js
CHANGED
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'The img() and picture() helpers for optimised, CLS-free image markup.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/images',
|
|
17
16
|
prev,
|
|
@@ -95,7 +94,6 @@ import { img, picture } from '@invisibleloop/pulse/image'`, 'js'))}
|
|
|
95
94
|
|
|
96
95
|
export default {
|
|
97
96
|
route: '/blog/:slug',
|
|
98
|
-
state: {},
|
|
99
97
|
server: {
|
|
100
98
|
data: async (ctx) => ({ post: await db.posts.findBySlug(ctx.params.slug) }),
|
|
101
99
|
},
|
package/docs/src/pages/meta.js
CHANGED
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'How to configure page metadata, Open Graph tags, and structured data in Pulse.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/meta',
|
|
17
16
|
prev,
|
|
@@ -28,7 +27,6 @@ export default {
|
|
|
28
27
|
description: 'Learn about the team behind Acme Corp.',
|
|
29
28
|
styles: ['/app.css'],
|
|
30
29
|
},
|
|
31
|
-
state: {},
|
|
32
30
|
view: () => \`<h1>About Us</h1>\`,
|
|
33
31
|
}`, 'js'))}
|
|
34
32
|
<p>This generates:</p>
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Performance targets, techniques, and built-in optimisations in Pulse.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/performance',
|
|
17
16
|
prev,
|
|
@@ -85,7 +84,6 @@ export default {
|
|
|
85
84
|
export default {
|
|
86
85
|
route: '/about',
|
|
87
86
|
meta: { title: 'About', styles: ['/app.css'] },
|
|
88
|
-
state: {},
|
|
89
87
|
view: () => \`<main><h1>About us</h1></main>\`,
|
|
90
88
|
}`, 'js'))}
|
|
91
89
|
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Recommended directory layout for a Pulse application.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/project-structure',
|
|
17
16
|
prev,
|
|
@@ -77,7 +76,6 @@ import { card } from '../components/card.js'
|
|
|
77
76
|
|
|
78
77
|
export default {
|
|
79
78
|
route: '/',
|
|
80
|
-
state: {},
|
|
81
79
|
view: () => card({ title: 'Hello', body: 'Welcome to Pulse' }),
|
|
82
80
|
}`, 'js'), 'src/pages/home.js')}
|
|
83
81
|
|
|
@@ -29,7 +29,6 @@ export default {
|
|
|
29
29
|
description: 'Real prompts for building Pulse pages with your AI agent — from creating pages to authentication, performance audits, and integrations.',
|
|
30
30
|
styles: ['/docs.css'],
|
|
31
31
|
},
|
|
32
|
-
state: {},
|
|
33
32
|
view: () => renderLayout({
|
|
34
33
|
currentHref: '/prompt-examples',
|
|
35
34
|
prev,
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Return non-HTML responses from Pulse specs — RSS, XML, JSON, and other content types.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/raw-responses',
|
|
17
16
|
prev,
|
|
@@ -25,7 +24,6 @@ export default {
|
|
|
25
24
|
${codeBlock(highlight(`export default {
|
|
26
25
|
route: '/feed.xml',
|
|
27
26
|
contentType: 'application/rss+xml',
|
|
28
|
-
state: {},
|
|
29
27
|
server: {
|
|
30
28
|
data: async () => ({
|
|
31
29
|
posts: await db.posts.latest(20),
|
|
@@ -53,7 +51,6 @@ export default {
|
|
|
53
51
|
${codeBlock(highlight(`export default {
|
|
54
52
|
route: '/api/products',
|
|
55
53
|
contentType: 'application/json',
|
|
56
|
-
state: {},
|
|
57
54
|
server: {
|
|
58
55
|
data: async (ctx) => ({
|
|
59
56
|
products: await db.products.list({
|
|
@@ -73,7 +70,6 @@ export default {
|
|
|
73
70
|
route: '/sitemap.xml',
|
|
74
71
|
contentType: 'application/xml',
|
|
75
72
|
serverTtl: 3600,
|
|
76
|
-
state: {},
|
|
77
73
|
server: {
|
|
78
74
|
data: async () => ({
|
|
79
75
|
pages: await db.pages.allPublished(),
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'How Pulse routes requests to page specs — static and dynamic routes, params, and conventions.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/routing',
|
|
17
16
|
prev,
|
|
@@ -24,7 +23,6 @@ export default {
|
|
|
24
23
|
<p>Every spec has a <code>route</code> field. This is the URL pattern the spec handles:</p>
|
|
25
24
|
${codeBlock(highlight(`export default {
|
|
26
25
|
route: '/about',
|
|
27
|
-
state: {},
|
|
28
26
|
view: () => \`<h1>About</h1>\`,
|
|
29
27
|
}`, 'js'))}
|
|
30
28
|
<p>Pulse matches the exact path. By default, trailing slashes are removed — <code>/about/</code> redirects to <code>/about</code> with a 301. This is controlled by the <code>trailingSlash</code> option in <code>createServer</code>:</p>
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Complete reference for createServer — all options, hooks, and response behaviour.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/server-api',
|
|
17
16
|
prev,
|
|
@@ -176,7 +175,6 @@ await createServer(specs, {
|
|
|
176
175
|
}
|
|
177
176
|
},
|
|
178
177
|
|
|
179
|
-
state: {},
|
|
180
178
|
view: () => \`<form method="POST">...</form>\`,
|
|
181
179
|
}`, 'js'))}
|
|
182
180
|
${callout('note', 'Raw response specs (<code>contentType</code> set) accept any HTTP method without <code>spec.methods</code> — they are always method-agnostic.')}
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Fetch, transform, and combine data on the server before rendering — external APIs, multiple fetchers, parallel requests.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/server-data',
|
|
17
16
|
prev,
|
package/docs/src/pages/spec.js
CHANGED
|
@@ -35,6 +35,7 @@ export default {
|
|
|
35
35
|
['<code>constraints</code>', '<code>object</code>', 'No', 'Min/max bounds enforced after every mutation.'],
|
|
36
36
|
['<code>persist</code>', '<code>string[]</code>', 'No', 'State keys to save in <code>localStorage</code>.'],
|
|
37
37
|
['<code>server</code>', '<code>object</code>', 'No', 'Server-side data fetcher. Result passed to <code>view</code> as second arg.'],
|
|
38
|
+
['<code>guard</code>', '<code>function</code>', 'No', 'Async pre-render hook. Return <code>{ redirect }</code> or <code>{ status, json }</code> to short-circuit. See <a href="/guard">Guard</a>.'],
|
|
38
39
|
['<code>store</code>', '<code>string[]</code>', 'No', 'Global store keys this page subscribes to. See <a href="/store">Global Store</a>.'],
|
|
39
40
|
['<code>methods</code>', '<code>string[]</code>', 'No', 'HTTP methods this page accepts. Default <code>[\'GET\', \'HEAD\']</code>. Add <code>\'POST\'</code> etc. to opt in.'],
|
|
40
41
|
['<code>stream</code>', '<code>object</code>', 'No', 'Streaming SSR config: <code>shell</code> + <code>deferred</code> segment names.'],
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'How streaming server-side rendering works in Pulse — shell, deferred segments, and when to use it.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/streaming',
|
|
17
16
|
prev,
|
|
@@ -28,7 +27,6 @@ export default {
|
|
|
28
27
|
<p>To use streaming, the <code>view</code> is an <strong>object of named segment functions</strong> rather than a single function. The spec declares which segments are in the shell and which are deferred:</p>
|
|
29
28
|
${codeBlock(highlight(`export default {
|
|
30
29
|
route: '/dashboard',
|
|
31
|
-
state: {},
|
|
32
30
|
server: {
|
|
33
31
|
data: async (ctx) => ({
|
|
34
32
|
user: await auth.getUser(ctx.cookies.sessionId), // fast
|
|
@@ -11,7 +11,6 @@ export default {
|
|
|
11
11
|
description: 'Test Pulse view functions with renderSync and render — query the HTML output with CSS-like selectors, no DOM required.',
|
|
12
12
|
styles: ['/docs.css'],
|
|
13
13
|
},
|
|
14
|
-
state: {},
|
|
15
14
|
view: () => renderLayout({
|
|
16
15
|
currentHref: '/testing',
|
|
17
16
|
prev,
|
package/package.json
CHANGED
package/public/.pulse-ui-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.5.
|
|
1
|
+
0.5.1
|
package/src/spec/schema.js
CHANGED
|
@@ -369,6 +369,11 @@ export function validateSpec(spec) {
|
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
+
// hydrate — auto-derived by the framework, should never be set manually
|
|
373
|
+
if (spec.hydrate !== undefined) {
|
|
374
|
+
warnings.push('spec.hydrate is set manually — it is auto-derived by the framework from the URL entry passed to createServer. Remove it from the spec.')
|
|
375
|
+
}
|
|
376
|
+
|
|
372
377
|
// meta quality
|
|
373
378
|
if (!spec.meta) {
|
|
374
379
|
warnings.push('spec.meta is missing — add at minimum title and description for SEO')
|