pulse-js-framework 1.7.13 → 1.7.16

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/cli/index.js CHANGED
@@ -9,6 +9,7 @@ import { dirname, join, resolve, relative } from 'path';
9
9
  import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, watch } from 'fs';
10
10
  import { log } from './logger.js';
11
11
  import { findPulseFiles, parseArgs } from './utils/file-utils.js';
12
+ import { runHelp } from './help.js';
12
13
 
13
14
  const __filename = fileURLToPath(import.meta.url);
14
15
  const __dirname = dirname(__filename);
@@ -136,10 +137,28 @@ function suggestCommand(input) {
136
137
  */
137
138
  async function main() {
138
139
  const args = process.argv.slice(2);
139
- const command = args[0] || 'help';
140
+ let command = args[0] || 'help';
141
+
142
+ // Handle global --help and -h flags
143
+ if (command === '--help' || command === '-h') {
144
+ command = 'help';
145
+ }
146
+
147
+ // Handle --version and -v flags
148
+ if (command === '--version' || command === '-v') {
149
+ command = 'version';
150
+ }
151
+
152
+ // Handle command-specific help: pulse <cmd> --help or pulse <cmd> -h
153
+ const cmdArgs = args.slice(1);
154
+ if (cmdArgs.includes('--help') || cmdArgs.includes('-h')) {
155
+ // Show help for the specific command
156
+ await commands.help([command]);
157
+ return;
158
+ }
140
159
 
141
160
  if (command in commands) {
142
- await commands[command](args.slice(1));
161
+ await commands[command](cmdArgs);
143
162
  } else {
144
163
  log.error(`Unknown command: ${command}`);
145
164
 
@@ -156,110 +175,10 @@ async function main() {
156
175
 
157
176
  /**
158
177
  * Show help message
178
+ * Supports: pulse help, pulse help <command>
159
179
  */
160
- function showHelp() {
161
- log.info(`
162
- Pulse Framework CLI v${VERSION}
163
-
164
- Usage: pulse <command> [options]
165
-
166
- Commands:
167
- create <name> Create a new Pulse project
168
- init [options] Initialize project in current directory
169
- dev [port] Start development server (default: 3000)
170
- build Build for production (minified)
171
- preview [port] Preview production build (default: 4173)
172
- compile <file> Compile a .pulse file to JavaScript
173
- mobile <cmd> Mobile app commands (init, build, run)
174
- lint [files] Validate .pulse files for errors and style
175
- format [files] Format .pulse files consistently
176
- analyze Analyze bundle size and dependencies
177
- test [files] Run tests with coverage support
178
- doctor Run project diagnostics
179
- scaffold <type> Generate components, pages, stores
180
- docs Generate API documentation from JSDoc
181
- release <type> Create a new release (patch, minor, major)
182
- docs-test Test documentation (syntax, imports, HTTP)
183
- version Show version number
184
- help Show this help message
185
-
186
- Create/Init Options:
187
- --typescript Create TypeScript project
188
- --minimal Create minimal project structure
189
-
190
- Compile Options:
191
- --watch, -w Watch files and recompile on changes
192
- --dry-run Show what would be compiled without writing
193
- --output, -o Output directory (default: same as input)
194
-
195
- Lint Options:
196
- --fix Auto-fix fixable issues
197
- --watch, -w Watch files and re-lint on changes
198
- --dry-run Show fixes without applying (use with --fix)
199
-
200
- Format Options:
201
- --check Check formatting without writing (dry-run)
202
- --watch, -w Watch files and re-format on changes
203
- --write Write formatted output (default)
204
-
205
- Analyze Options:
206
- --json Output analysis as JSON
207
- --verbose Show detailed metrics
208
-
209
- Test Options:
210
- --coverage, -c Collect code coverage
211
- --watch, -w Watch files and re-run tests
212
- --filter, -f Filter tests by name pattern
213
- --timeout, -t Test timeout in ms (default: 30000)
214
- --bail, -b Stop on first failure
215
- --create <name> Generate a new test file
216
-
217
- Doctor Options:
218
- --verbose, -v Show detailed diagnostics
219
- --json Output as JSON
220
-
221
- Scaffold Options:
222
- --dir, -d <path> Output directory
223
- --force, -f Overwrite existing files
224
- --props Include props section (components)
225
-
226
- Docs Options:
227
- --generate, -g Generate documentation
228
- --format, -f Output format: markdown, json, html
229
- --output, -o Output directory (default: docs/api)
230
-
231
- Release Options:
232
- --dry-run Show what would be done without making changes
233
- --no-push Create commit and tag but don't push
234
- --title <text> Release title for changelog
235
- --skip-prompt Use empty changelog (for automation)
236
- --skip-docs-test Skip documentation tests before release
237
- --from-commits Auto-extract changelog from git commits since last tag
238
-
239
- Examples:
240
- pulse create my-app
241
- pulse create my-app --typescript
242
- pulse init --typescript
243
- pulse dev
244
- pulse build
245
- pulse test
246
- pulse test --coverage --watch
247
- pulse test --create MyComponent
248
- pulse doctor
249
- pulse doctor --verbose
250
- pulse scaffold component Button
251
- pulse scaffold page Dashboard
252
- pulse scaffold store user
253
- pulse docs --generate
254
- pulse docs --generate --format html
255
- pulse compile src/App.pulse
256
- pulse lint src/ --fix
257
- pulse format --check
258
- pulse analyze --json
259
- pulse release patch
260
-
261
- Documentation: https://github.com/vincenthirtz/pulse-js-framework
262
- `);
180
+ function showHelp(args = []) {
181
+ runHelp(args);
263
182
  }
264
183
 
265
184
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulse-js-framework",
3
- "version": "1.7.13",
3
+ "version": "1.7.16",
4
4
  "description": "A declarative DOM framework with CSS selector-based structure and reactive pulsations",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -88,7 +88,7 @@
88
88
  "./compiler/lexer": "./compiler/lexer.js",
89
89
  "./compiler/parser": "./compiler/parser.js",
90
90
  "./compiler/transformer": "./compiler/transformer.js",
91
- "./core/errors": "./core/errors.js",
91
+ "./core/errors": "./runtime/errors.js",
92
92
  "./vite": {
93
93
  "types": "./types/index.d.ts",
94
94
  "default": "./loader/vite-plugin.js"
@@ -109,14 +109,17 @@
109
109
  "LICENSE"
110
110
  ],
111
111
  "scripts": {
112
- "test": "npm run test:compiler && npm run test:sourcemap && npm run test:pulse && npm run test:dom && npm run test:dom-adapter && npm run test:router && npm run test:store && npm run test:hmr && npm run test:lint && npm run test:format && npm run test:analyze && npm run test:cli && npm run test:cli-ui && npm run test:lru-cache && npm run test:utils && npm run test:docs && npm run test:async && npm run test:form && npm run test:http && npm run test:devtools && npm run test:native && npm run test:a11y && npm run test:logger && npm run test:errors && npm run test:security && npm run test:websocket && npm run test:graphql && npm run test:doctor && npm run test:scaffold && npm run test:test-runner && npm run test:build",
112
+ "test": "npm run test:compiler && npm run test:sourcemap && npm run test:pulse && npm run test:dom && npm run test:dom-element && npm run test:dom-adapter && npm run test:enhanced-mock-adapter && npm run test:router && npm run test:store && npm run test:context && npm run test:hmr && npm run test:lint && npm run test:format && npm run test:analyze && npm run test:cli && npm run test:cli-ui && npm run test:lru-cache && npm run test:utils && npm run test:docs && npm run test:docs-nav && npm run test:async && npm run test:form && npm run test:http && npm run test:devtools && npm run test:native && npm run test:a11y && npm run test:a11y-enhanced && npm run test:logger && npm run test:errors && npm run test:security && npm run test:websocket && npm run test:graphql && npm run test:doctor && npm run test:scaffold && npm run test:test-runner && npm run test:build && npm run test:integration && npm run test:context-stress && npm run test:form-edge-cases && npm run test:graphql-subscriptions && npm run test:http-edge-cases && npm run test:integration-advanced && npm run test:websocket-stress && npm run test:ssr",
113
113
  "test:compiler": "node test/compiler.test.js",
114
114
  "test:sourcemap": "node test/sourcemap.test.js",
115
115
  "test:pulse": "node test/pulse.test.js",
116
116
  "test:dom": "node test/dom.test.js",
117
+ "test:dom-element": "node test/dom-element.test.js",
117
118
  "test:dom-adapter": "node test/dom-adapter.test.js",
119
+ "test:enhanced-mock-adapter": "node test/enhanced-mock-adapter.test.js",
118
120
  "test:router": "node test/router.test.js",
119
121
  "test:store": "node test/store.test.js",
122
+ "test:context": "node test/context.test.js",
120
123
  "test:hmr": "node test/hmr.test.js",
121
124
  "test:lint": "node test/lint.test.js",
122
125
  "test:format": "node test/format.test.js",
@@ -126,12 +129,14 @@
126
129
  "test:lru-cache": "node test/lru-cache.test.js",
127
130
  "test:utils": "node test/utils.test.js",
128
131
  "test:docs": "node test/docs.test.js",
132
+ "test:docs-nav": "node test/docs-navigation.test.js",
129
133
  "test:async": "node test/async.test.js",
130
134
  "test:form": "node test/form.test.js",
131
135
  "test:http": "node test/http.test.js",
132
136
  "test:devtools": "node test/devtools.test.js",
133
137
  "test:native": "node test/native.test.js",
134
138
  "test:a11y": "node test/a11y.test.js",
139
+ "test:a11y-enhanced": "node test/a11y-enhanced.test.js",
135
140
  "test:logger": "node test/logger.test.js",
136
141
  "test:errors": "node test/errors.test.js",
137
142
  "test:security": "node test/security.test.js",
@@ -141,6 +146,14 @@
141
146
  "test:scaffold": "node test/scaffold.test.js",
142
147
  "test:test-runner": "node test/test-runner.test.js",
143
148
  "test:build": "node test/build.test.js",
149
+ "test:integration": "node test/integration.test.js",
150
+ "test:context-stress": "node test/context-stress.test.js",
151
+ "test:form-edge-cases": "node test/form-edge-cases.test.js",
152
+ "test:graphql-subscriptions": "node test/graphql-subscriptions.test.js",
153
+ "test:http-edge-cases": "node test/http-edge-cases.test.js",
154
+ "test:integration-advanced": "node test/integration-advanced.test.js",
155
+ "test:websocket-stress": "node test/websocket-stress.test.js",
156
+ "test:ssr": "node test/ssr.test.js",
144
157
  "build:netlify": "node scripts/build-netlify.js",
145
158
  "version": "node scripts/sync-version.js",
146
159
  "docs": "node cli/index.js dev docs"
package/runtime/async.js CHANGED
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import { pulse, effect, batch, onCleanup } from './pulse.js';
10
+ import { getSSRAsyncContext, registerAsync, getCachedAsync, hasCachedAsync } from './ssr-async.js';
10
11
 
11
12
  // ============================================================================
12
13
  // Versioned Async - Centralized Race Condition Handling
@@ -328,6 +329,44 @@ export function useAsync(asyncFn, options = {}) {
328
329
  retryDelay = 1000
329
330
  } = options;
330
331
 
332
+ // SSR MODE: Check for cached data or register async operation
333
+ const ssrCtx = getSSRAsyncContext();
334
+ if (ssrCtx) {
335
+ // Check if we already have cached data (second render pass)
336
+ if (hasCachedAsync(asyncFn)) {
337
+ const cachedData = getCachedAsync(asyncFn);
338
+ return {
339
+ data: pulse(cachedData),
340
+ error: pulse(null),
341
+ loading: pulse(false),
342
+ status: pulse('success'),
343
+ execute: () => Promise.resolve(cachedData),
344
+ reset: () => {},
345
+ abort: () => {}
346
+ };
347
+ }
348
+
349
+ // First render pass: register async operation for collection
350
+ if (immediate) {
351
+ const promise = asyncFn().catch(err => {
352
+ // Store error for SSR error handling
353
+ return null;
354
+ });
355
+ registerAsync(asyncFn, promise);
356
+ }
357
+
358
+ // Return loading state for first pass
359
+ return {
360
+ data: pulse(initialData),
361
+ error: pulse(null),
362
+ loading: pulse(true),
363
+ status: pulse('loading'),
364
+ execute: () => Promise.resolve(initialData),
365
+ reset: () => {},
366
+ abort: () => {}
367
+ };
368
+ }
369
+
331
370
  const data = pulse(initialData);
332
371
  const error = pulse(null);
333
372
  const loading = pulse(false);