pulse-js-framework 1.10.4 → 1.11.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.
Files changed (65) hide show
  1. package/README.md +11 -0
  2. package/cli/build.js +13 -3
  3. package/compiler/directives.js +356 -0
  4. package/compiler/lexer.js +18 -3
  5. package/compiler/parser/core.js +6 -0
  6. package/compiler/parser/view.js +2 -6
  7. package/compiler/preprocessor.js +43 -23
  8. package/compiler/sourcemap.js +3 -1
  9. package/compiler/transformer/actions.js +329 -0
  10. package/compiler/transformer/export.js +7 -0
  11. package/compiler/transformer/expressions.js +85 -33
  12. package/compiler/transformer/imports.js +3 -0
  13. package/compiler/transformer/index.js +2 -0
  14. package/compiler/transformer/store.js +1 -1
  15. package/compiler/transformer/style.js +45 -16
  16. package/compiler/transformer/view.js +23 -2
  17. package/loader/rollup-plugin-server-components.js +391 -0
  18. package/loader/vite-plugin-server-components.js +420 -0
  19. package/loader/webpack-loader-server-components.js +356 -0
  20. package/package.json +124 -82
  21. package/runtime/async.js +4 -0
  22. package/runtime/context.js +16 -3
  23. package/runtime/dom-adapter.js +5 -3
  24. package/runtime/dom-virtual-list.js +2 -1
  25. package/runtime/form.js +8 -3
  26. package/runtime/graphql/cache.js +1 -1
  27. package/runtime/graphql/client.js +22 -0
  28. package/runtime/graphql/hooks.js +12 -6
  29. package/runtime/graphql/subscriptions.js +2 -0
  30. package/runtime/hmr.js +6 -3
  31. package/runtime/http.js +1 -0
  32. package/runtime/i18n.js +2 -0
  33. package/runtime/lru-cache.js +3 -1
  34. package/runtime/native.js +46 -20
  35. package/runtime/pulse.js +3 -0
  36. package/runtime/router/core.js +5 -1
  37. package/runtime/router/index.js +17 -1
  38. package/runtime/router/psc-integration.js +301 -0
  39. package/runtime/security.js +58 -29
  40. package/runtime/server-components/actions-server.js +798 -0
  41. package/runtime/server-components/actions.js +389 -0
  42. package/runtime/server-components/client.js +447 -0
  43. package/runtime/server-components/error-sanitizer.js +438 -0
  44. package/runtime/server-components/index.js +275 -0
  45. package/runtime/server-components/security-csrf.js +593 -0
  46. package/runtime/server-components/security-errors.js +227 -0
  47. package/runtime/server-components/security-ratelimit.js +733 -0
  48. package/runtime/server-components/security-validation.js +467 -0
  49. package/runtime/server-components/security.js +598 -0
  50. package/runtime/server-components/serializer.js +617 -0
  51. package/runtime/server-components/server.js +382 -0
  52. package/runtime/server-components/types.js +383 -0
  53. package/runtime/server-components/utils/mutex.js +60 -0
  54. package/runtime/server-components/utils/path-sanitizer.js +109 -0
  55. package/runtime/ssr.js +2 -1
  56. package/runtime/store.js +19 -10
  57. package/runtime/utils.js +12 -128
  58. package/types/animation.d.ts +300 -0
  59. package/types/i18n.d.ts +283 -0
  60. package/types/persistence.d.ts +267 -0
  61. package/types/sse.d.ts +248 -0
  62. package/types/sw.d.ts +150 -0
  63. package/runtime/a11y.js.original +0 -1844
  64. package/runtime/graphql.js.original +0 -1326
  65. package/runtime/router.js.original +0 -1605
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Pulse Server Components - Security Error Classes
3
+ *
4
+ * Specialized error classes for Server Components security violations.
5
+ * All extend RuntimeError for consistency with the framework.
6
+ *
7
+ * @module pulse-js-framework/runtime/server-components/security-errors
8
+ */
9
+
10
+ import { RuntimeError } from '../errors.js';
11
+
12
+ // ============================================================================
13
+ // Base Security Error
14
+ // ============================================================================
15
+
16
+ /**
17
+ * Base class for all Server Components security errors.
18
+ * Extends RuntimeError with security-specific context.
19
+ *
20
+ * @extends RuntimeError
21
+ */
22
+ export class PSCSecurityError extends RuntimeError {
23
+ constructor(message, options = {}) {
24
+ super(message, {
25
+ code: 'PSC_SECURITY_ERROR',
26
+ ...options
27
+ });
28
+ this.name = 'PSCSecurityError';
29
+ }
30
+ }
31
+
32
+ // ============================================================================
33
+ // Serialization Error
34
+ // ============================================================================
35
+
36
+ /**
37
+ * Error thrown when props contain non-serializable values.
38
+ *
39
+ * Non-serializable types:
40
+ * - Functions
41
+ * - Symbols
42
+ * - Class instances (Promise, Error, custom classes)
43
+ * - Circular references
44
+ *
45
+ * @extends PSCSecurityError
46
+ */
47
+ export class PSCSerializationError extends PSCSecurityError {
48
+ /**
49
+ * @param {string} message - Error message
50
+ * @param {Object} [details] - Additional error details
51
+ * @param {string} [details.path] - Property path where error occurred
52
+ * @param {string} [details.type] - Type of non-serializable value
53
+ * @param {Array} [details.errors] - Array of all serialization errors
54
+ */
55
+ constructor(message, details = {}) {
56
+ super(message, {
57
+ code: 'PSC_NON_SERIALIZABLE',
58
+ context: details.type ? `Type: ${details.type}` : undefined,
59
+ suggestion: details.type === 'function'
60
+ ? 'Use Server Actions instead of inline functions'
61
+ : details.type === 'class-instance'
62
+ ? 'Pass plain objects instead of class instances'
63
+ : 'Ensure all props are JSON-serializable (strings, numbers, booleans, plain objects, arrays)',
64
+ details: details.errors
65
+ });
66
+ this.name = 'PSCSerializationError';
67
+ this.path = details.path;
68
+ this.propType = details.type;
69
+ }
70
+ }
71
+
72
+ // ============================================================================
73
+ // Environment Variable Error
74
+ // ============================================================================
75
+
76
+ /**
77
+ * Error thrown when props contain environment variable references.
78
+ *
79
+ * Detects patterns like:
80
+ * - process.env.API_KEY
81
+ * - import.meta.env.VITE_API_KEY
82
+ * - Deno.env.get('API_KEY')
83
+ *
84
+ * Note: This is usually a warning, not a blocking error, since strings
85
+ * could contain these patterns as documentation/examples.
86
+ *
87
+ * @extends PSCSecurityError
88
+ */
89
+ export class PSCEnvVarError extends PSCSecurityError {
90
+ /**
91
+ * @param {string} message - Error message
92
+ * @param {Object} [details] - Additional error details
93
+ * @param {string} [details.path] - Property path where env var was found
94
+ * @param {string} [details.variable] - Environment variable name
95
+ * @param {string} [details.pattern] - Full pattern that matched
96
+ * @param {Array} [details.warnings] - Array of all env var detections
97
+ */
98
+ constructor(message, details = {}) {
99
+ super(message, {
100
+ code: 'PSC_ENV_VAR_IN_PROPS',
101
+ context: details.variable ? `Variable: ${details.variable}` : undefined,
102
+ suggestion: 'Avoid passing environment variables as props. Keep secrets on the server.',
103
+ details: details.warnings
104
+ });
105
+ this.name = 'PSCEnvVarError';
106
+ this.path = details.path;
107
+ this.variable = details.variable;
108
+ this.pattern = details.pattern;
109
+ }
110
+ }
111
+
112
+ // ============================================================================
113
+ // CSRF Error
114
+ // ============================================================================
115
+
116
+ /**
117
+ * Error thrown when CSRF token validation fails.
118
+ *
119
+ * Reasons:
120
+ * - MISSING_TOKEN: No CSRF token in request
121
+ * - INVALID_FORMAT: Token format is incorrect
122
+ * - EXPIRED: Token has expired
123
+ * - INVALID_SIGNATURE: HMAC signature doesn't match
124
+ * - UNKNOWN_TOKEN: Token not found in store
125
+ * - TOKEN_ALREADY_USED: Single-use token was already used
126
+ *
127
+ * @extends PSCSecurityError
128
+ */
129
+ export class PSCCSRFError extends PSCSecurityError {
130
+ /**
131
+ * @param {string} reason - Failure reason code
132
+ * @param {Object} [details] - Additional error details
133
+ * @param {string} [details.token] - Partial token (first 8 chars)
134
+ * @param {boolean} [details.expired] - Whether token expired
135
+ */
136
+ constructor(reason, details = {}) {
137
+ const messages = {
138
+ MISSING_TOKEN: 'CSRF token missing from request',
139
+ INVALID_FORMAT: 'CSRF token has invalid format',
140
+ EXPIRED: 'CSRF token has expired',
141
+ INVALID_SIGNATURE: 'CSRF token signature is invalid',
142
+ UNKNOWN_TOKEN: 'CSRF token not found in store',
143
+ TOKEN_ALREADY_USED: 'CSRF token has already been used'
144
+ };
145
+
146
+ const message = messages[reason] || 'CSRF validation failed';
147
+
148
+ super(message, {
149
+ code: 'PSC_CSRF_INVALID',
150
+ context: reason ? `Reason: ${reason}` : undefined,
151
+ suggestion: reason === 'EXPIRED'
152
+ ? 'CSRF token expired. Reload the page to get a new token.'
153
+ : reason === 'MISSING_TOKEN'
154
+ ? 'Include CSRF token in X-CSRF-Token header or ensure meta tag is present.'
155
+ : reason === 'INVALID_SIGNATURE'
156
+ ? 'CSRF token signature invalid. Possible tampering detected.'
157
+ : 'Ensure CSRF token is correctly generated and transmitted.',
158
+ details
159
+ });
160
+ this.name = 'PSCCSRFError';
161
+ this.reason = reason;
162
+ this.expired = details.expired;
163
+ }
164
+ }
165
+
166
+ // ============================================================================
167
+ // Rate Limit Error
168
+ // ============================================================================
169
+
170
+ /**
171
+ * Error thrown when rate limit is exceeded.
172
+ *
173
+ * Contains information about:
174
+ * - Which limit was exceeded (action, user, or global)
175
+ * - How long to wait before retrying
176
+ * - When the limit will reset
177
+ *
178
+ * @extends PSCSecurityError
179
+ */
180
+ export class PSCRateLimitError extends PSCSecurityError {
181
+ /**
182
+ * @param {string} message - Error message
183
+ * @param {Object} [details] - Additional error details
184
+ * @param {string} [details.reason] - Which limit was exceeded
185
+ * @param {number} [details.retryAfter] - Milliseconds until retry allowed
186
+ * @param {number} [details.resetAt] - Timestamp when limit resets
187
+ * @param {number} [details.limit] - Maximum requests allowed
188
+ * @param {string} [details.actionId] - Action ID that was rate limited
189
+ */
190
+ constructor(message, details = {}) {
191
+ super(message, {
192
+ code: 'PSC_RATE_LIMIT_EXCEEDED',
193
+ context: details.reason ? `Reason: ${details.reason}` : undefined,
194
+ suggestion: details.retryAfter
195
+ ? `Wait ${Math.ceil(details.retryAfter / 1000)}s before retrying`
196
+ : 'Reduce request frequency',
197
+ details
198
+ });
199
+ this.name = 'PSCRateLimitError';
200
+ this.reason = details.reason;
201
+ this.retryAfter = details.retryAfter;
202
+ this.resetAt = details.resetAt;
203
+ this.limit = details.limit;
204
+ this.actionId = details.actionId;
205
+ }
206
+
207
+ /**
208
+ * Check if error is a rate limit error
209
+ * @param {Error} error - Error to check
210
+ * @returns {boolean}
211
+ */
212
+ static isRateLimitError(error) {
213
+ return error instanceof PSCRateLimitError || error?.name === 'PSCRateLimitError';
214
+ }
215
+ }
216
+
217
+ // ============================================================================
218
+ // Exports
219
+ // ============================================================================
220
+
221
+ export default {
222
+ PSCSecurityError,
223
+ PSCSerializationError,
224
+ PSCEnvVarError,
225
+ PSCCSRFError,
226
+ PSCRateLimitError
227
+ };