@epoch32/visage 1.1.3 → 1.1.5

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 (52) hide show
  1. package/dist/api/index.js +55 -4085
  2. package/dist/charts/index.js +48 -2806
  3. package/dist/devtools/index.js +18 -4771
  4. package/dist/dom/index.js +32 -1639
  5. package/dist/form/index.js +13 -1498
  6. package/dist/index-061jf06a.js +848 -0
  7. package/dist/index-0madxn60.js +442 -0
  8. package/dist/index-1xtrtz1t.js +256 -0
  9. package/dist/index-2zz0g2n2.js +212 -0
  10. package/dist/index-5s255b3w.js +303 -0
  11. package/dist/index-6kfe1nr4.js +1179 -0
  12. package/dist/index-8czhpea8.js +338 -0
  13. package/dist/index-8x8xz80v.js +727 -0
  14. package/dist/index-921pn75b.js +0 -0
  15. package/dist/index-965ryh36.js +537 -0
  16. package/dist/index-9fvarkrx.js +98 -0
  17. package/dist/index-a4xns6cc.js +219 -0
  18. package/dist/index-b5wc752a.js +1696 -0
  19. package/dist/index-df5e614s.js +334 -0
  20. package/dist/index-dyvgtp43.js +1094 -0
  21. package/dist/index-grhdtcb5.js +234 -0
  22. package/dist/index-h6tjqk6e.js +158 -0
  23. package/dist/index-js199er4.js +101 -0
  24. package/dist/index-x2rs3vab.js +124 -0
  25. package/dist/index-y9bq7h9g.js +1162 -0
  26. package/dist/index-zr6cvset.js +2092 -0
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +458 -11920
  29. package/dist/jsx-runtime/index.js +13 -1719
  30. package/dist/query/index.js +47 -2505
  31. package/dist/router/index.js +25 -1945
  32. package/dist/rpc/index.js +39 -3567
  33. package/dist/server/index.js +11 -1256
  34. package/dist/signals/index.js +52 -1160
  35. package/dist/style/index.js +77 -2429
  36. package/dist/template/index.js +7 -1232
  37. package/dist/ui/index.d.ts +1 -1
  38. package/dist/ui/index.js +150 -4249
  39. package/dist/ui/tabs.d.ts +23 -1
  40. package/dist/virtual/index.js +12 -2044
  41. package/dist/vite/index.js +27 -746
  42. package/package.json +2 -2
  43. package/src/dom/render.ts +20 -7
  44. package/src/index.ts +2 -0
  45. package/src/signals/computed.ts +19 -12
  46. package/src/signals/effect.ts +7 -7
  47. package/src/signals/signal.ts +16 -12
  48. package/src/signals/system.ts +50 -21
  49. package/src/ui/index.ts +2 -0
  50. package/src/ui/tabs.tsx +211 -10
  51. package/src/ui/utils.ts +1 -3
  52. package/src/vite/lucide.ts +22 -2
@@ -1,3 +1,7 @@
1
+ import {
2
+ createFetchHandler2
3
+ } from "../index-965ryh36.js";
4
+
1
5
  // src/vite/lucide.ts
2
6
  function parseNamedImports(importClause) {
3
7
  return importClause.split(",").map((s) => s.trim()).filter(Boolean).map((item) => {
@@ -31,12 +35,32 @@ function visageLucide(options = {}) {
31
35
  },
32
36
  load(id) {
33
37
  if (id.startsWith("\x00visage-lucide:")) {
34
- return "export default {};";
38
+ return `
39
+ import * as lucideIcons from "lucide";
40
+ import { createIcon } from "visage/ui";
41
+
42
+ const cache = new Map();
43
+ export const __getIcon = (name) => {
44
+ if (cache.has(name)) return cache.get(name);
45
+ const node = lucideIcons[name];
46
+ const comp = node ? createIcon(name, node) : () => null;
47
+ cache.set(name, comp);
48
+ return comp;
49
+ };
50
+
51
+ export default new Proxy({}, {
52
+ get: (_, prop) => typeof prop === "string" ? __getIcon(prop) : undefined
53
+ });
54
+
55
+ // Dynamic proxy export for all lucide icon names
56
+ ${Object.keys({})};
57
+ export * from "lucide";
58
+ `;
35
59
  }
36
60
  return null;
37
61
  },
38
62
  transform(code, id) {
39
- if (!id.match(/\.[jt]sx?$/) || id.includes("node_modules")) {
63
+ if (!id.match(/\.([jt]sx?|mdx?)$/) || id.includes("node_modules")) {
40
64
  return null;
41
65
  }
42
66
  let transformed = code;
@@ -97,753 +121,10 @@ if (import.meta.hot) {
97
121
  };
98
122
  }
99
123
 
100
- // src/rpc/error.ts
101
- var ERROR_CODE_TO_STATUS = {
102
- BAD_REQUEST: 400,
103
- UNAUTHORIZED: 401,
104
- FORBIDDEN: 403,
105
- NOT_FOUND: 404,
106
- METHOD_NOT_ALLOWED: 405,
107
- TIMEOUT: 408,
108
- CONFLICT: 409,
109
- UNPROCESSABLE_CONTENT: 422,
110
- INTERNAL_SERVER_ERROR: 500
111
- };
112
- var STATUS_TO_ERROR_CODE = {
113
- 400: "BAD_REQUEST",
114
- 401: "UNAUTHORIZED",
115
- 403: "FORBIDDEN",
116
- 404: "NOT_FOUND",
117
- 405: "METHOD_NOT_ALLOWED",
118
- 408: "TIMEOUT",
119
- 409: "CONFLICT",
120
- 422: "UNPROCESSABLE_CONTENT",
121
- 500: "INTERNAL_SERVER_ERROR"
122
- };
123
-
124
- class RPCError extends Error {
125
- code;
126
- status;
127
- issues;
128
- constructor(codeOrStatusOrOptions, message) {
129
- if (typeof codeOrStatusOrOptions === "number") {
130
- const code = STATUS_TO_ERROR_CODE[codeOrStatusOrOptions] || "INTERNAL_SERVER_ERROR";
131
- super(message || code);
132
- this.name = "RPCError";
133
- this.code = code;
134
- this.status = codeOrStatusOrOptions;
135
- } else if (typeof codeOrStatusOrOptions === "string") {
136
- super(message || codeOrStatusOrOptions);
137
- this.name = "RPCError";
138
- this.code = codeOrStatusOrOptions;
139
- this.status = ERROR_CODE_TO_STATUS[codeOrStatusOrOptions] || 500;
140
- } else {
141
- super(codeOrStatusOrOptions.message ?? codeOrStatusOrOptions.code, {
142
- cause: codeOrStatusOrOptions.cause
143
- });
144
- this.name = "RPCError";
145
- this.code = codeOrStatusOrOptions.code;
146
- this.status = ERROR_CODE_TO_STATUS[codeOrStatusOrOptions.code] ?? 500;
147
- this.issues = codeOrStatusOrOptions.issues;
148
- }
149
- }
150
- get statusCode() {
151
- return this.status;
152
- }
153
- }
154
-
155
- // src/form/schema.ts
156
- class Schema {
157
- "~standard" = {
158
- version: 1,
159
- vendor: "visage",
160
- validate: (val) => {
161
- const res = this.validate(val);
162
- if (res.success) {
163
- return { value: res.data };
164
- }
165
- return {
166
- issues: (res.issues || []).map((i) => ({
167
- path: [i.path],
168
- message: i.message
169
- }))
170
- };
171
- }
172
- };
173
- }
174
-
175
- class StringSchema extends Schema {
176
- _min;
177
- _max;
178
- _emailMsg;
179
- _regex;
180
- _isOptional = false;
181
- min(length, message) {
182
- this._min = { val: length, msg: message };
183
- return this;
184
- }
185
- max(length, message) {
186
- this._max = { val: length, msg: message };
187
- return this;
188
- }
189
- email(message) {
190
- this._emailMsg = message ?? "Invalid email address";
191
- return this;
192
- }
193
- regex(pattern, message) {
194
- this._regex = { pattern, msg: message };
195
- return this;
196
- }
197
- optional() {
198
- this._isOptional = true;
199
- return this;
200
- }
201
- validate(value, path = "") {
202
- if (value === undefined || value === null || value === "") {
203
- if (this._isOptional)
204
- return { success: true, data: undefined };
205
- return { success: false, issues: [{ path, message: "This field is required" }] };
206
- }
207
- if (typeof value !== "string") {
208
- return { success: false, issues: [{ path, message: "Must be a string" }] };
209
- }
210
- if (this._min && value.length < this._min.val) {
211
- return {
212
- success: false,
213
- issues: [{ path, message: this._min.msg ?? `Must be at least ${this._min.val} characters` }]
214
- };
215
- }
216
- if (this._max && value.length > this._max.val) {
217
- return {
218
- success: false,
219
- issues: [{ path, message: this._max.msg ?? `Must be at most ${this._max.val} characters` }]
220
- };
221
- }
222
- if (this._emailMsg) {
223
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
224
- if (!emailRegex.test(value)) {
225
- return { success: false, issues: [{ path, message: this._emailMsg }] };
226
- }
227
- }
228
- if (this._regex && !this._regex.pattern.test(value)) {
229
- return {
230
- success: false,
231
- issues: [{ path, message: this._regex.msg ?? "Invalid format" }]
232
- };
233
- }
234
- return { success: true, data: value };
235
- }
236
- }
237
-
238
- class NumberSchema extends Schema {
239
- _min;
240
- _max;
241
- _integer;
242
- _isOptional = false;
243
- min(value, message) {
244
- this._min = { val: value, msg: message };
245
- return this;
246
- }
247
- max(value, message) {
248
- this._max = { val: value, msg: message };
249
- return this;
250
- }
251
- integer(message) {
252
- this._integer = { msg: message };
253
- return this;
254
- }
255
- optional() {
256
- this._isOptional = true;
257
- return this;
258
- }
259
- validate(value, path = "") {
260
- if (value === undefined || value === null || value === "") {
261
- if (this._isOptional)
262
- return { success: true, data: undefined };
263
- return { success: false, issues: [{ path, message: "This field is required" }] };
264
- }
265
- const num = Number(value);
266
- if (Number.isNaN(num) || typeof value === "boolean") {
267
- return { success: false, issues: [{ path, message: "Must be a valid number" }] };
268
- }
269
- if (this._integer && !Number.isInteger(num)) {
270
- return {
271
- success: false,
272
- issues: [{ path, message: this._integer.msg ?? "Must be an integer" }]
273
- };
274
- }
275
- if (this._min && num < this._min.val) {
276
- return {
277
- success: false,
278
- issues: [{ path, message: this._min.msg ?? `Must be at least ${this._min.val}` }]
279
- };
280
- }
281
- if (this._max && num > this._max.val) {
282
- return {
283
- success: false,
284
- issues: [{ path, message: this._max.msg ?? `Must be at most ${this._max.val}` }]
285
- };
286
- }
287
- return { success: true, data: num };
288
- }
289
- }
290
-
291
- class BooleanSchema extends Schema {
292
- validate(value, _path = "") {
293
- return { success: true, data: Boolean(value) };
294
- }
295
- }
296
-
297
- class ObjectSchema extends Schema {
298
- shape;
299
- constructor(shape) {
300
- super();
301
- this.shape = shape;
302
- }
303
- validate(value, basePath = "") {
304
- if (typeof value !== "object" || value === null) {
305
- return { success: false, issues: [{ path: basePath, message: "Must be an object" }] };
306
- }
307
- const issues = [];
308
- const data = {};
309
- for (const key in this.shape) {
310
- const fieldSchema = this.shape[key];
311
- const fieldVal = value[key];
312
- const fieldPath = basePath ? `${basePath}.${key}` : key;
313
- const res = validateWithSchema(fieldSchema, fieldVal, fieldPath);
314
- if (res.success) {
315
- data[key] = res.data;
316
- } else if (res.issues) {
317
- issues.push(...res.issues);
318
- }
319
- }
320
- if (issues.length > 0) {
321
- return { success: false, issues };
322
- }
323
- return { success: true, data };
324
- }
325
- }
326
- function validateWithSchema(schema, value, path = "") {
327
- if (!schema)
328
- return { success: true, data: value };
329
- if (schema instanceof Schema) {
330
- return schema.validate(value, path);
331
- }
332
- if (typeof schema === "object" && "~standard" in schema) {
333
- const res = schema["~standard"].validate(value);
334
- if ("value" in res) {
335
- return { success: true, data: res.value };
336
- }
337
- return {
338
- success: false,
339
- issues: res.issues.map((i) => ({
340
- path: i.path ? i.path.join(".") : path,
341
- message: i.message
342
- }))
343
- };
344
- }
345
- if (typeof schema === "function") {
346
- const res = schema(value);
347
- if (res === true || res === null || res === undefined) {
348
- return { success: true, data: value };
349
- }
350
- if (typeof res === "string") {
351
- return { success: false, issues: [{ path, message: res }] };
352
- }
353
- if (typeof res === "object") {
354
- return res;
355
- }
356
- }
357
- return { success: true, data: value };
358
- }
359
- var v = {
360
- string: () => new StringSchema,
361
- number: () => new NumberSchema,
362
- boolean: () => new BooleanSchema,
363
- object: (shape) => new ObjectSchema(shape)
364
- };
365
-
366
- // src/rpc/procedure.ts
367
- function createProcedure(type, options, middlewares = []) {
368
- return {
369
- type,
370
- inputSchema: options.input,
371
- outputSchema: options.output,
372
- middlewares: [...middlewares],
373
- resolve: options.resolve
374
- };
375
- }
376
- async function executeProcedure(procedure, opts) {
377
- let input = opts.rawInput;
378
- if (procedure.inputSchema) {
379
- const res = validateWithSchema(procedure.inputSchema, opts.rawInput);
380
- if (!res.success) {
381
- throw new RPCError({
382
- code: "BAD_REQUEST",
383
- message: "Invalid procedure input",
384
- issues: res.issues
385
- });
386
- }
387
- input = res.data;
388
- }
389
- let currentIndex = 0;
390
- let currentContext = opts.ctx;
391
- const runPipeline = async (ctx) => {
392
- currentContext = ctx;
393
- if (currentIndex < procedure.middlewares.length) {
394
- const mw = procedure.middlewares[currentIndex++];
395
- return mw({
396
- ctx: currentContext,
397
- req: opts.req,
398
- signal: opts.signal,
399
- next: async (nextOpts) => {
400
- return runPipeline(nextOpts?.ctx ?? currentContext);
401
- }
402
- });
403
- }
404
- return procedure.resolve({
405
- input,
406
- ctx: currentContext,
407
- req: opts.req,
408
- signal: opts.signal
409
- });
410
- };
411
- const output = await runPipeline(currentContext);
412
- if (procedure.outputSchema && procedure.type !== "subscription") {
413
- const res = validateWithSchema(procedure.outputSchema, output);
414
- if (!res.success) {
415
- throw new RPCError({
416
- code: "INTERNAL_SERVER_ERROR",
417
- message: "Invalid procedure output",
418
- issues: res.issues
419
- });
420
- }
421
- return res.data;
422
- }
423
- return output;
424
- }
425
-
426
- // src/rpc/server.ts
427
- function getCORSHeaders(cors, req) {
428
- const headers = new Headers;
429
- if (!cors)
430
- return headers;
431
- const opts = typeof cors === "object" ? cors : {};
432
- const originHeader = req.headers.get("origin") ?? "*";
433
- let allowOrigin = "*";
434
- if (typeof opts.origin === "function") {
435
- const res = opts.origin(originHeader);
436
- if (typeof res === "string")
437
- allowOrigin = res;
438
- else if (res)
439
- allowOrigin = originHeader;
440
- } else if (typeof opts.origin === "string") {
441
- allowOrigin = opts.origin;
442
- } else if (Array.isArray(opts.origin)) {
443
- if (opts.origin.includes(originHeader))
444
- allowOrigin = originHeader;
445
- } else {
446
- allowOrigin = originHeader || "*";
447
- }
448
- headers.set("Access-Control-Allow-Origin", allowOrigin);
449
- headers.set("Access-Control-Allow-Methods", (opts.methods ?? ["GET", "POST", "OPTIONS", "HEAD"]).join(", "));
450
- headers.set("Access-Control-Allow-Headers", (opts.allowedHeaders ?? ["Content-Type", "Authorization", "X-Requested-With"]).join(", "));
451
- if (opts.exposedHeaders) {
452
- headers.set("Access-Control-Expose-Headers", opts.exposedHeaders.join(", "));
453
- }
454
- if (opts.credentials) {
455
- headers.set("Access-Control-Allow-Credentials", "true");
456
- }
457
- if (opts.maxAge !== undefined) {
458
- headers.set("Access-Control-Max-Age", opts.maxAge.toString());
459
- }
460
- return headers;
461
- }
462
- function resolveProcedureFromPath(router, path) {
463
- const parts = path.split(/[./]/).filter(Boolean);
464
- let current = router._def.record;
465
- for (let i = 0;i < parts.length; i++) {
466
- const part = parts[i];
467
- if (!current || typeof current !== "object") {
468
- throw new RPCError({
469
- code: "NOT_FOUND",
470
- message: `Procedure '${path}' not found`
471
- });
472
- }
473
- if (i === parts.length - 1) {
474
- if (part in current && "type" in current[part]) {
475
- return current[part];
476
- }
477
- throw new RPCError({
478
- code: "NOT_FOUND",
479
- message: `Procedure '${path}' not found`
480
- });
481
- }
482
- if (part in current && "_def" in current[part]) {
483
- current = current[part]._def.record;
484
- } else if (part in current && typeof current[part] === "object") {
485
- current = current[part];
486
- } else {
487
- throw new RPCError({
488
- code: "NOT_FOUND",
489
- message: `Procedure '${path}' not found`
490
- });
491
- }
492
- }
493
- throw new RPCError({
494
- code: "NOT_FOUND",
495
- message: `Procedure '${path}' not found`
496
- });
497
- }
498
- function matchesRulePattern(pattern, urlPath, procedurePath) {
499
- if (pattern === "*")
500
- return true;
501
- const cleanUrl = urlPath.replace(/^\/+|\/+$/g, "");
502
- const cleanPattern = pattern.replace(/^\/+|\/+$/g, "");
503
- const cleanProc = procedurePath.replace(/^\/+|\/+$/g, "");
504
- if (cleanUrl === cleanPattern || cleanProc === cleanPattern || cleanProc === cleanPattern.replace(/\//g, ".")) {
505
- return true;
506
- }
507
- if (cleanPattern.endsWith("*")) {
508
- const prefix = cleanPattern.slice(0, -1);
509
- if (cleanUrl.startsWith(prefix) || cleanProc.startsWith(prefix)) {
510
- return true;
511
- }
512
- const dotPrefix = prefix.replace(/\//g, ".");
513
- if (cleanProc.startsWith(dotPrefix)) {
514
- return true;
515
- }
516
- }
517
- try {
518
- const regexStr = cleanPattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
519
- const regex = new RegExp(`^${regexStr}$`);
520
- return regex.test(cleanUrl) || regex.test(cleanProc);
521
- } catch {
522
- return false;
523
- }
524
- }
525
- function createFetchHandler(options) {
526
- const {
527
- router,
528
- endpoint = "",
529
- createContext,
530
- onError,
531
- cors = true,
532
- securityHeaders = true,
533
- rules
534
- } = options;
535
- return async (request, ...extra) => {
536
- const corsHeaders = getCORSHeaders(cors, request);
537
- if (request.method === "OPTIONS") {
538
- return new Response(null, {
539
- status: 204,
540
- headers: corsHeaders
541
- });
542
- }
543
- const baseHeaders = new Headers(corsHeaders);
544
- if (securityHeaders) {
545
- if (typeof securityHeaders === "object") {
546
- for (const [k, v] of Object.entries(securityHeaders)) {
547
- baseHeaders.set(k, v);
548
- }
549
- } else {
550
- baseHeaders.set("X-Content-Type-Options", "nosniff");
551
- }
552
- }
553
- const url = new URL(request.url);
554
- let pathname = url.pathname;
555
- if (endpoint && pathname.startsWith(endpoint)) {
556
- pathname = pathname.slice(endpoint.length);
557
- }
558
- pathname = pathname.replace(/^\/+|\/+$/g, "");
559
- const procedurePath = pathname || url.searchParams.get("procedure") || "";
560
- let ctx = {};
561
- try {
562
- if (createContext) {
563
- ctx = await createContext({ req: request, extra });
564
- }
565
- } catch (err) {
566
- const error = err instanceof RPCError ? err : new RPCError({
567
- code: "UNAUTHORIZED",
568
- message: err.message ?? "Context initialization failed",
569
- cause: err
570
- });
571
- onError?.({ error, req: request });
572
- baseHeaders.set("Content-Type", "application/json");
573
- return new Response(JSON.stringify({
574
- error: {
575
- code: error.code,
576
- message: error.message,
577
- issues: error.issues
578
- }
579
- }), {
580
- status: error.status,
581
- headers: baseHeaders
582
- });
583
- }
584
- const rulesList = [];
585
- if (rules) {
586
- if (Array.isArray(rules)) {
587
- rulesList.push(...rules);
588
- } else {
589
- for (const [match, rule] of Object.entries(rules)) {
590
- rulesList.push({ match, ...rule });
591
- }
592
- }
593
- }
594
- const matchingRules = rulesList.filter((r) => matchesRulePattern(r.match, url.pathname, procedurePath));
595
- for (const rule of matchingRules) {
596
- if (rule.requireHeaders) {
597
- for (const headerName of rule.requireHeaders) {
598
- if (!request.headers.get(headerName)) {
599
- const error = new RPCError({
600
- code: "UNAUTHORIZED",
601
- message: `Missing required header '${headerName}' for rule '${rule.match}'`
602
- });
603
- onError?.({ error, path: procedurePath, req: request });
604
- baseHeaders.set("Content-Type", "application/json");
605
- return new Response(JSON.stringify({
606
- error: {
607
- code: error.code,
608
- message: error.message
609
- }
610
- }), {
611
- status: 401,
612
- headers: baseHeaders
613
- });
614
- }
615
- }
616
- }
617
- if (rule.requireParams) {
618
- for (const paramName of rule.requireParams) {
619
- if (!url.searchParams.has(paramName)) {
620
- const error = new RPCError({
621
- code: "BAD_REQUEST",
622
- message: `Missing required query parameter '${paramName}' for rule '${rule.match}'`
623
- });
624
- onError?.({ error, path: procedurePath, req: request });
625
- baseHeaders.set("Content-Type", "application/json");
626
- return new Response(JSON.stringify({
627
- error: {
628
- code: error.code,
629
- message: error.message
630
- }
631
- }), {
632
- status: 400,
633
- headers: baseHeaders
634
- });
635
- }
636
- }
637
- }
638
- if (rule.guard) {
639
- try {
640
- const guardResult = await rule.guard({ req: request, ctx, path: procedurePath });
641
- if (guardResult === false) {
642
- throw new RPCError({
643
- code: "UNAUTHORIZED",
644
- message: `Access denied by route rule guard for '${rule.match}'`
645
- });
646
- }
647
- } catch (err) {
648
- const error = err instanceof RPCError ? err : new RPCError({
649
- code: "UNAUTHORIZED",
650
- message: err.message ?? "Unauthorized",
651
- cause: err
652
- });
653
- onError?.({ error, path: procedurePath, req: request });
654
- baseHeaders.set("Content-Type", "application/json");
655
- return new Response(JSON.stringify({
656
- error: {
657
- code: error.code,
658
- message: error.message
659
- }
660
- }), {
661
- status: error.status,
662
- headers: baseHeaders
663
- });
664
- }
665
- }
666
- if (rule.headers) {
667
- const resHeaders = typeof rule.headers === "function" ? await rule.headers(request, ctx) : rule.headers;
668
- for (const [k, v] of Object.entries(resHeaders)) {
669
- baseHeaders.set(k, v);
670
- }
671
- }
672
- }
673
- if (request.method === "POST" && (!pathname || pathname === "batch")) {
674
- try {
675
- const body = await request.json();
676
- if (Array.isArray(body)) {
677
- const batchResults = await Promise.all(body.map(async (item) => {
678
- try {
679
- const proc = resolveProcedureFromPath(router, item.path);
680
- const data = await executeProcedure(proc, {
681
- rawInput: item.input,
682
- ctx,
683
- req: request,
684
- signal: request.signal
685
- });
686
- return {
687
- id: item.id,
688
- result: { data }
689
- };
690
- } catch (err) {
691
- const error = err instanceof RPCError ? err : new RPCError({
692
- code: "INTERNAL_SERVER_ERROR",
693
- message: err.message ?? "Internal Server Error",
694
- cause: err
695
- });
696
- onError?.({ error, path: item.path, req: request });
697
- return {
698
- id: item.id,
699
- error: {
700
- code: error.code,
701
- message: error.message,
702
- issues: error.issues
703
- }
704
- };
705
- }
706
- }));
707
- baseHeaders.set("Content-Type", "application/json");
708
- return new Response(JSON.stringify(batchResults), {
709
- status: 200,
710
- headers: baseHeaders
711
- });
712
- }
713
- } catch (err) {
714
- const error = new RPCError({
715
- code: "BAD_REQUEST",
716
- message: "Malformed batch request body",
717
- cause: err
718
- });
719
- baseHeaders.set("Content-Type", "application/json");
720
- return new Response(JSON.stringify({
721
- error: {
722
- code: error.code,
723
- message: error.message
724
- }
725
- }), {
726
- status: 400,
727
- headers: baseHeaders
728
- });
729
- }
730
- }
731
- try {
732
- const procedure = resolveProcedureFromPath(router, procedurePath);
733
- if (procedure.type === "mutation" && request.method !== "POST") {
734
- throw new RPCError({
735
- code: "METHOD_NOT_ALLOWED",
736
- message: "Mutations must use POST method"
737
- });
738
- }
739
- let rawInput;
740
- if (request.method === "GET") {
741
- const inputParam = url.searchParams.get("input");
742
- if (inputParam !== null) {
743
- try {
744
- rawInput = JSON.parse(inputParam);
745
- } catch {
746
- rawInput = inputParam;
747
- }
748
- }
749
- } else if (request.method === "POST") {
750
- try {
751
- const body = await request.json();
752
- rawInput = body && typeof body === "object" && "input" in body ? body.input : body;
753
- } catch {
754
- rawInput = undefined;
755
- }
756
- }
757
- if (procedure.type === "subscription") {
758
- const iterable = await executeProcedure(procedure, {
759
- rawInput,
760
- ctx,
761
- req: request,
762
- signal: request.signal
763
- });
764
- if (!iterable || typeof iterable[Symbol.asyncIterator] !== "function") {
765
- throw new RPCError({
766
- code: "INTERNAL_SERVER_ERROR",
767
- message: "Subscription procedure must return an AsyncIterable"
768
- });
769
- }
770
- const encoder = new TextEncoder;
771
- const stream = new ReadableStream({
772
- async start(controller) {
773
- try {
774
- for await (const chunk of iterable) {
775
- if (request.signal.aborted)
776
- break;
777
- const message = `data: ${JSON.stringify(chunk)}
778
-
779
- `;
780
- controller.enqueue(encoder.encode(message));
781
- }
782
- controller.close();
783
- } catch (err) {
784
- const errorMessage = `event: error
785
- data: ${JSON.stringify({ message: err.message ?? "Stream error" })}
786
-
787
- `;
788
- controller.enqueue(encoder.encode(errorMessage));
789
- controller.close();
790
- }
791
- },
792
- cancel() {
793
- if (typeof iterable.return === "function") {
794
- iterable.return();
795
- }
796
- }
797
- });
798
- baseHeaders.set("Content-Type", "text/event-stream; charset=utf-8");
799
- baseHeaders.set("Cache-Control", "no-cache, no-transform");
800
- baseHeaders.set("Connection", "keep-alive");
801
- return new Response(stream, {
802
- status: 200,
803
- headers: baseHeaders
804
- });
805
- }
806
- const data = await executeProcedure(procedure, {
807
- rawInput,
808
- ctx,
809
- req: request,
810
- signal: request.signal
811
- });
812
- const responsePayload = {
813
- result: { data }
814
- };
815
- baseHeaders.set("Content-Type", "application/json");
816
- return new Response(JSON.stringify(responsePayload), {
817
- status: 200,
818
- headers: baseHeaders
819
- });
820
- } catch (err) {
821
- const error = err instanceof RPCError ? err : new RPCError({
822
- code: "INTERNAL_SERVER_ERROR",
823
- message: err.message ?? "Internal Server Error",
824
- cause: err
825
- });
826
- onError?.({ error, path: procedurePath, req: request });
827
- const responsePayload = {
828
- error: {
829
- code: error.code,
830
- message: error.message,
831
- issues: error.issues
832
- }
833
- };
834
- baseHeaders.set("Content-Type", "application/json");
835
- return new Response(JSON.stringify(responsePayload), {
836
- status: ERROR_CODE_TO_STATUS[error.code] ?? 500,
837
- headers: baseHeaders
838
- });
839
- }
840
- };
841
- }
842
-
843
124
  // src/vite/rpc-middleware.ts
844
125
  function createViteRpcMiddleware(options) {
845
126
  const endpoint = options.endpoint ?? "/api/rpc";
846
- const handler = createFetchHandler({
127
+ const handler = createFetchHandler2({
847
128
  router: options.router,
848
129
  endpoint,
849
130
  cors: true