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.
- package/README.md +11 -0
- package/cli/build.js +13 -3
- package/compiler/directives.js +356 -0
- package/compiler/lexer.js +18 -3
- package/compiler/parser/core.js +6 -0
- package/compiler/parser/view.js +2 -6
- package/compiler/preprocessor.js +43 -23
- package/compiler/sourcemap.js +3 -1
- package/compiler/transformer/actions.js +329 -0
- package/compiler/transformer/export.js +7 -0
- package/compiler/transformer/expressions.js +85 -33
- package/compiler/transformer/imports.js +3 -0
- package/compiler/transformer/index.js +2 -0
- package/compiler/transformer/store.js +1 -1
- package/compiler/transformer/style.js +45 -16
- package/compiler/transformer/view.js +23 -2
- package/loader/rollup-plugin-server-components.js +391 -0
- package/loader/vite-plugin-server-components.js +420 -0
- package/loader/webpack-loader-server-components.js +356 -0
- package/package.json +124 -82
- package/runtime/async.js +4 -0
- package/runtime/context.js +16 -3
- package/runtime/dom-adapter.js +5 -3
- package/runtime/dom-virtual-list.js +2 -1
- package/runtime/form.js +8 -3
- package/runtime/graphql/cache.js +1 -1
- package/runtime/graphql/client.js +22 -0
- package/runtime/graphql/hooks.js +12 -6
- package/runtime/graphql/subscriptions.js +2 -0
- package/runtime/hmr.js +6 -3
- package/runtime/http.js +1 -0
- package/runtime/i18n.js +2 -0
- package/runtime/lru-cache.js +3 -1
- package/runtime/native.js +46 -20
- package/runtime/pulse.js +3 -0
- package/runtime/router/core.js +5 -1
- package/runtime/router/index.js +17 -1
- package/runtime/router/psc-integration.js +301 -0
- package/runtime/security.js +58 -29
- package/runtime/server-components/actions-server.js +798 -0
- package/runtime/server-components/actions.js +389 -0
- package/runtime/server-components/client.js +447 -0
- package/runtime/server-components/error-sanitizer.js +438 -0
- package/runtime/server-components/index.js +275 -0
- package/runtime/server-components/security-csrf.js +593 -0
- package/runtime/server-components/security-errors.js +227 -0
- package/runtime/server-components/security-ratelimit.js +733 -0
- package/runtime/server-components/security-validation.js +467 -0
- package/runtime/server-components/security.js +598 -0
- package/runtime/server-components/serializer.js +617 -0
- package/runtime/server-components/server.js +382 -0
- package/runtime/server-components/types.js +383 -0
- package/runtime/server-components/utils/mutex.js +60 -0
- package/runtime/server-components/utils/path-sanitizer.js +109 -0
- package/runtime/ssr.js +2 -1
- package/runtime/store.js +19 -10
- package/runtime/utils.js +12 -128
- package/types/animation.d.ts +300 -0
- package/types/i18n.d.ts +283 -0
- package/types/persistence.d.ts +267 -0
- package/types/sse.d.ts +248 -0
- package/types/sw.d.ts +150 -0
- package/runtime/a11y.js.original +0 -1844
- package/runtime/graphql.js.original +0 -1326
- 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
|
+
};
|