weifuwu 0.2.2 → 0.2.3

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 (45) hide show
  1. package/README.md +56 -5
  2. package/dist/compress.d.ts +6 -0
  3. package/dist/cookie.d.ts +12 -0
  4. package/dist/index.d.ts +21 -0
  5. package/dist/index.js +1420 -0
  6. package/dist/middleware.d.ts +21 -0
  7. package/dist/rate-limit.d.ts +8 -0
  8. package/dist/router.d.ts +55 -0
  9. package/dist/serve.d.ts +19 -0
  10. package/dist/static.d.ts +7 -0
  11. package/dist/tsx.d.ts +17 -0
  12. package/dist/types.d.ts +9 -0
  13. package/dist/upload.d.ts +14 -0
  14. package/dist/validate.d.ts +9 -0
  15. package/package.json +14 -2
  16. package/AGENTS.md +0 -105
  17. package/compress.ts +0 -69
  18. package/cookie.ts +0 -58
  19. package/index.ts +0 -21
  20. package/middleware.ts +0 -178
  21. package/rate-limit.ts +0 -68
  22. package/router.ts +0 -701
  23. package/serve.ts +0 -126
  24. package/static.ts +0 -113
  25. package/test/compress.test.ts +0 -106
  26. package/test/cookie.test.ts +0 -79
  27. package/test/fixtures/pages/about/page.tsx +0 -3
  28. package/test/fixtures/pages/blog/[slug]/load.ts +0 -3
  29. package/test/fixtures/pages/blog/[slug]/page.tsx +0 -3
  30. package/test/fixtures/pages/blog/[slug]/route.ts +0 -7
  31. package/test/fixtures/pages/blog/layout.tsx +0 -3
  32. package/test/fixtures/pages/layout.tsx +0 -12
  33. package/test/fixtures/pages/page.tsx +0 -3
  34. package/test/middleware.test.ts +0 -407
  35. package/test/rate-limit.test.ts +0 -94
  36. package/test/static.test.ts +0 -93
  37. package/test/tsx.test.ts +0 -285
  38. package/test/unode.test.ts +0 -401
  39. package/test/upload.test.ts +0 -130
  40. package/test/validate.test.ts +0 -133
  41. package/tsconfig.json +0 -13
  42. package/tsx.ts +0 -374
  43. package/types.ts +0 -23
  44. package/upload.ts +0 -101
  45. package/validate.ts +0 -88
package/router.ts DELETED
@@ -1,701 +0,0 @@
1
- import { WebSocketServer, type WebSocket } from 'ws'
2
- import type { IncomingMessage } from 'node:http'
3
- import type { Duplex } from 'node:stream'
4
- import { buildSchema, graphql, type GraphQLSchema } from 'graphql'
5
- import { makeExecutableSchema } from '@graphql-tools/schema'
6
- import { streamText } from 'ai'
7
- import type { Context, Handler, Middleware, ErrorHandler } from './types.ts'
8
-
9
- type StreamTextParams = Parameters<typeof streamText>[0]
10
-
11
- export type WebSocketHandler = {
12
- open?: (ws: WebSocket, ctx: Context) => void | Promise<void>
13
- message?: (ws: WebSocket, ctx: Context, data: string | Buffer) => void | Promise<void>
14
- close?: (ws: WebSocket, ctx: Context) => void | Promise<void>
15
- error?: (ws: WebSocket, ctx: Context, error: Error) => void | Promise<void>
16
- }
17
-
18
- export type AIOptions = Omit<StreamTextParams, 'model'> & {
19
- model: string | (() => any)
20
- }
21
-
22
- export type AIHandler = (
23
- req: Request,
24
- ctx: Context,
25
- ) => AIOptions | Promise<AIOptions>
26
-
27
- export type GraphQLOptions = {
28
- schema: string | GraphQLSchema
29
- rootValue?: any
30
- resolvers?: any
31
- context?: (req: Request, ctx: Context) => Record<string, any> | Promise<Record<string, any>>
32
- graphiql?: boolean
33
- }
34
-
35
- type TrieNode = {
36
- children: Map<string, TrieNode>
37
- handlers: Map<string, Handler>
38
- middlewares: Map<string, Middleware[]>
39
- param?: string
40
- wildcard?: boolean
41
- pathMws: Middleware[]
42
- subRouter?: Router
43
- }
44
-
45
- type WsTrieNode = {
46
- children: Map<string, WsTrieNode>
47
- handler?: WebSocketHandler
48
- middlewares: Middleware[]
49
- param?: string
50
- }
51
-
52
- const createTrieNode = (): TrieNode => ({
53
- children: new Map(),
54
- handlers: new Map(),
55
- middlewares: new Map(),
56
- pathMws: [],
57
- })
58
-
59
- const createWsNode = (): WsTrieNode => ({
60
- children: new Map(),
61
- middlewares: [],
62
- })
63
-
64
- const getTrieNode = (node: TrieNode, segment: string): TrieNode => {
65
- if (segment.startsWith(':')) {
66
- if (!node.children.has(':')) {
67
- const child = createTrieNode()
68
- child.param = segment.slice(1)
69
- node.children.set(':', child)
70
- }
71
- const child = node.children.get(':')!
72
- if (child.param !== segment.slice(1)) {
73
- throw new Error(
74
- `Param name conflict: ":${child.param}" already registered at this path position, cannot register ":"${segment.slice(1)}"`,
75
- )
76
- }
77
- return child
78
- }
79
- if (!node.children.has(segment)) {
80
- node.children.set(segment, createTrieNode())
81
- }
82
- return node.children.get(segment)!
83
- }
84
-
85
- const matchTrieNode = (
86
- node: TrieNode,
87
- segment: string,
88
- params: Record<string, string>,
89
- ): TrieNode | null => {
90
- if (node.children.has(segment)) return node.children.get(segment)!
91
- if (node.children.has(':')) {
92
- const child = node.children.get(':')!
93
- if (child.param) params[child.param] = segment
94
- return child
95
- }
96
- return null
97
- }
98
-
99
- const getWsNode = (node: WsTrieNode, segment: string): WsTrieNode => {
100
- if (segment.startsWith(':')) {
101
- if (!node.children.has(':')) {
102
- const child = createWsNode()
103
- child.param = segment.slice(1)
104
- node.children.set(':', child)
105
- }
106
- const child = node.children.get(':')!
107
- if (child.param !== segment.slice(1)) {
108
- throw new Error(
109
- `Param name conflict: ":${child.param}" already registered at this path position`,
110
- )
111
- }
112
- return child
113
- }
114
- if (!node.children.has(segment)) {
115
- node.children.set(segment, createWsNode())
116
- }
117
- return node.children.get(segment)!
118
- }
119
-
120
- const matchWsNode = (
121
- node: WsTrieNode,
122
- segment: string,
123
- params: Record<string, string>,
124
- ): WsTrieNode | null => {
125
- if (node.children.has(segment)) return node.children.get(segment)!
126
- if (node.children.has(':')) {
127
- const child = node.children.get(':')!
128
- if (child.param) params[child.param] = segment
129
- return child
130
- }
131
- return null
132
- }
133
-
134
- type WsMatchResult = {
135
- handler: WebSocketHandler
136
- middlewares: Middleware[]
137
- params: Record<string, string>
138
- } | null
139
-
140
- type WsUpgradeHandler = (req: IncomingMessage, socket: Duplex, head: Buffer) => void
141
-
142
- export class Router {
143
- private root: TrieNode = createTrieNode()
144
- private wsRoot: WsTrieNode = createWsNode()
145
- private globalMws: Middleware[] = []
146
- private errorHandler?: ErrorHandler
147
-
148
- use(mw: Middleware): this
149
- use(path: string, router: Router): this
150
- use(path: string, mw: Middleware): this
151
- use(arg1: string | Middleware, arg2?: Router | Middleware): this {
152
- if (typeof arg1 === 'string') {
153
- if (arg2 instanceof Router) {
154
- let node = this.root
155
- for (const segment of this.splitPath(arg1)) {
156
- node = getTrieNode(node, segment)
157
- }
158
- node.subRouter = arg2
159
- } else if (typeof arg2 === 'function') {
160
- let node = this.root
161
- for (const segment of this.splitPath(arg1)) {
162
- node = getTrieNode(node, segment)
163
- }
164
- node.pathMws.push(arg2)
165
- }
166
- } else if (typeof arg1 === 'function') {
167
- this.globalMws.push(arg1)
168
- }
169
- return this
170
- }
171
-
172
- get(path: string, ...args: [...Middleware[], Handler]): this {
173
- return this.route('GET', path, ...args)
174
- }
175
-
176
- post(path: string, ...args: [...Middleware[], Handler]): this {
177
- return this.route('POST', path, ...args)
178
- }
179
-
180
- put(path: string, ...args: [...Middleware[], Handler]): this {
181
- return this.route('PUT', path, ...args)
182
- }
183
-
184
- delete(path: string, ...args: [...Middleware[], Handler]): this {
185
- return this.route('DELETE', path, ...args)
186
- }
187
-
188
- patch(path: string, ...args: [...Middleware[], Handler]): this {
189
- return this.route('PATCH', path, ...args)
190
- }
191
-
192
- head(path: string, ...args: [...Middleware[], Handler]): this {
193
- return this.route('HEAD', path, ...args)
194
- }
195
-
196
- options(path: string, ...args: [...Middleware[], Handler]): this {
197
- return this.route('OPTIONS', path, ...args)
198
- }
199
-
200
- all(path: string, ...args: [...Middleware[], Handler]): this {
201
- return this.route('*', path, ...args)
202
- }
203
-
204
- onError(handler: ErrorHandler): this {
205
- this.errorHandler = handler
206
- return this
207
- }
208
-
209
- route(method: string, path: string, ...args: [...Middleware[], Handler]): this {
210
- const handler = args.pop()! as Handler
211
- const middlewares = args as Middleware[]
212
- const segments = this.splitPath(path)
213
- let node = this.root
214
-
215
- for (const segment of segments) {
216
- if (segment === '*') {
217
- node.wildcard = true
218
- node.handlers.set(method, handler)
219
- if (middlewares.length > 0) node.middlewares.set(method, middlewares)
220
- return this
221
- }
222
- node = getTrieNode(node, segment)
223
- }
224
-
225
- node.handlers.set(method, handler)
226
- if (middlewares.length > 0) node.middlewares.set(method, middlewares)
227
- return this
228
- }
229
-
230
- ws(path: string, ...args: [...Middleware[], WebSocketHandler]): this {
231
- const handler = args.pop()! as WebSocketHandler
232
- const middlewares = args as Middleware[]
233
- const segments = this.splitPath(path)
234
- let node = this.wsRoot
235
-
236
- for (const segment of segments) {
237
- node = getWsNode(node, segment)
238
- }
239
-
240
- node.handler = handler
241
- if (middlewares.length > 0) node.middlewares = middlewares
242
- return this
243
- }
244
-
245
- graphql(path: string, ...args: [...Middleware[], GraphQLOptions]): this {
246
- const options = args.pop()! as GraphQLOptions
247
- const middlewares = args as Middleware[]
248
- const schema: GraphQLSchema =
249
- typeof options.schema === 'string'
250
- ? options.resolvers
251
- ? makeExecutableSchema({
252
- typeDefs: options.schema,
253
- resolvers: options.resolvers,
254
- })
255
- : buildSchema(options.schema)
256
- : options.schema
257
-
258
- const handler: Handler = (req, ctx) => {
259
- const url = new URL(req.url)
260
-
261
- if (
262
- options.graphiql &&
263
- req.method === 'GET' &&
264
- !url.searchParams.has('query')
265
- ) {
266
- return new Response(getGraphiQLHtml(url.pathname), {
267
- status: 200,
268
- headers: { 'Content-Type': 'text/html' },
269
- })
270
- }
271
-
272
- if (req.method !== 'GET' && req.method !== 'POST') {
273
- return new Response('Not Found', { status: 404 })
274
- }
275
-
276
- const paramsPromise =
277
- req.method === 'GET'
278
- ? Promise.resolve(parseGraphQLParamsFromGet(url))
279
- : parseGraphQLParamsFromPost(req)
280
-
281
- return paramsPromise.then((params) => {
282
- if (!params) {
283
- return Response.json(
284
- { errors: [{ message: 'Missing query' }] },
285
- { status: 400 },
286
- )
287
- }
288
- return executeGraphQLQuery(schema, params, options, req, ctx)
289
- })
290
- }
291
-
292
- return this.all(path, ...middlewares, handler)
293
- }
294
-
295
- ai(path: string, ...args: [...Middleware[], AIHandler]): this {
296
- const handler = args.pop()! as AIHandler
297
- const middlewares = args as Middleware[]
298
-
299
- const routeHandler: Handler = async (req, ctx) => {
300
- const options = await handler(req, ctx)
301
- const result = streamText(options as StreamTextParams)
302
- return result.toTextStreamResponse()
303
- }
304
-
305
- return this.post(path, ...middlewares, routeHandler)
306
- }
307
-
308
- handler(): Handler {
309
- return (req, ctx) => {
310
- const url = new URL(req.url)
311
- return this.handle(req, ctx, this.splitPath(url.pathname), Object.fromEntries(url.searchParams))
312
- }
313
- }
314
-
315
- websocketHandler(): WsUpgradeHandler {
316
- const wss = new WebSocketServer({ noServer: true })
317
- const wsRoot = this.wsRoot
318
- const router = this
319
-
320
- return (req, socket, head) => {
321
- const url = new URL(req.url ?? '/', 'http://localhost')
322
- const segments = url.pathname.split('/').filter(Boolean)
323
- const query = Object.fromEntries(url.searchParams)
324
-
325
- const match = router.matchWsTrie(wsRoot, segments)
326
- if (!match) {
327
- socket.destroy()
328
- return
329
- }
330
-
331
- const webReq = new Request(url.href, {
332
- method: req.method ?? 'GET',
333
- headers: Object.fromEntries(
334
- Object.entries(req.headers).map(([k, v]) => [k, Array.isArray(v) ? v.join(', ') : v ?? '']),
335
- ),
336
- })
337
- const ctx: Context = { params: match.params, query }
338
-
339
- if (match.middlewares.length === 0) {
340
- upgradeSocket(wss, req, socket, head, match.handler, ctx)
341
- return
342
- }
343
-
344
- let index = 0
345
- const dispatch: Handler = async (innerReq, ctx) => {
346
- if (index < match.middlewares.length) {
347
- const mw = match.middlewares[index++]
348
- return mw!(innerReq, ctx, dispatch)
349
- }
350
- return await new Promise<Response>((resolve) => {
351
- upgradeSocket(wss, req, socket, head, match.handler, ctx)
352
- resolve(new Response(null, { status: 101 }))
353
- })
354
- }
355
-
356
- Promise.resolve(dispatch(webReq, ctx)).then((result) => {
357
- if (result.status !== 101) {
358
- sendHttpResponseOnSocket(socket, result)
359
- }
360
- }).catch(() => {
361
- socket.destroy()
362
- })
363
- }
364
- }
365
-
366
- private splitPath(path: string): string[] {
367
- return path.split('/').filter(Boolean)
368
- }
369
-
370
- private matchTrie(
371
- method: string,
372
- segments: string[],
373
- ): {
374
- handler?: Handler
375
- middlewares: Middleware[]
376
- pathMws: Middleware[]
377
- params: Record<string, string>
378
- subRouter?: { router: Router; remainingIdx: number }
379
- } | null {
380
- let node = this.root
381
- const params: Record<string, string> = {}
382
- const pathMws: Middleware[] = [...this.root.pathMws]
383
- let wildcardHandler: Handler | null = null
384
- let wildcardMws: Middleware[] = []
385
- let wildcardIdx = -1
386
-
387
- for (let i = 0; i < segments.length; i++) {
388
- pathMws.push(...node.pathMws)
389
-
390
- if (node.wildcard) {
391
- const h = node.handlers.get(method) || node.handlers.get('*')
392
- if (h) {
393
- wildcardHandler = h
394
- wildcardMws = node.middlewares.get(method) || node.middlewares.get('*') || []
395
- wildcardIdx = i
396
- }
397
- }
398
-
399
- const segment = segments[i]
400
- if (!segment) break
401
-
402
- const next = matchTrieNode(node, segment, params)
403
- if (!next) {
404
- if (node.subRouter) {
405
- return {
406
- pathMws,
407
- params,
408
- middlewares: [],
409
- subRouter: { router: node.subRouter, remainingIdx: i },
410
- }
411
- }
412
- if (wildcardHandler) {
413
- params['*'] = segments.slice(wildcardIdx).join('/')
414
- return { handler: wildcardHandler, middlewares: wildcardMws, pathMws, params }
415
- }
416
- return null
417
- }
418
- node = next
419
- }
420
-
421
- if (node.subRouter) {
422
- return {
423
- pathMws,
424
- params,
425
- middlewares: [],
426
- subRouter: { router: node.subRouter, remainingIdx: segments.length },
427
- }
428
- }
429
-
430
- pathMws.push(...node.pathMws)
431
-
432
- const handler = node.handlers.get(method) || node.handlers.get('*')
433
- if (handler) {
434
- if (node.wildcard) params['*'] = segments.slice(segments.length).join('/')
435
- return {
436
- handler,
437
- middlewares: node.middlewares.get(method) || node.middlewares.get('*') || [],
438
- pathMws,
439
- params,
440
- }
441
- }
442
-
443
- if (wildcardHandler) {
444
- params['*'] = segments.slice(wildcardIdx).join('/')
445
- return { handler: wildcardHandler, middlewares: wildcardMws, pathMws, params }
446
- }
447
- return null
448
- }
449
-
450
- private matchWsTrie(root: WsTrieNode, segments: string[]): WsMatchResult {
451
- let node = root
452
- const params: Record<string, string> = {}
453
-
454
- for (const segment of segments) {
455
- const next = matchWsNode(node, segment, params)
456
- if (!next) return null
457
- node = next
458
- }
459
-
460
- return node.handler
461
- ? { handler: node.handler, middlewares: node.middlewares, params }
462
- : null
463
- }
464
-
465
- private async handle(
466
- req: Request,
467
- ctx: Context,
468
- segments: string[],
469
- query: Record<string, string>,
470
- ): Promise<Response> {
471
- const match = this.matchTrie(req.method, segments)
472
-
473
- if (match?.subRouter) {
474
- const { router: sub, remainingIdx } = match.subRouter
475
- const remainingSegments = segments.slice(remainingIdx)
476
- const delegate: Handler = (req, ctx) =>
477
- sub.handle(req, ctx, remainingSegments, query)
478
-
479
- const allMws = this.globalMws.length + match.pathMws.length === 0
480
- ? [] as Middleware[]
481
- : [...this.globalMws, ...match.pathMws]
482
-
483
- try {
484
- return await this.runChain(allMws, delegate, req, { ...ctx, params: { ...ctx.params, ...match.params } })
485
- } catch (e) {
486
- return this.errorHandler
487
- ? this.errorHandler(e as Error, req, ctx)
488
- : new Response('Internal Server Error', { status: 500 })
489
- }
490
- }
491
-
492
- if (match?.handler) {
493
- const { handler, middlewares: routeMws, pathMws, params } = match
494
- const allMws = this.globalMws.length + pathMws.length + routeMws.length === 0
495
- ? [] as Middleware[]
496
- : [...this.globalMws, ...pathMws, ...routeMws]
497
- const ctxWithMatch = { ...ctx, params: { ...ctx.params, ...params } }
498
-
499
- try {
500
- return await this.runChain(allMws, handler, req, ctxWithMatch)
501
- } catch (e) {
502
- return this.errorHandler
503
- ? this.errorHandler(e as Error, req, ctxWithMatch)
504
- : new Response('Internal Server Error', { status: 500 })
505
- }
506
- }
507
-
508
- if (this.globalMws.length > 0) {
509
- try {
510
- const delegate: Handler = () => new Response('Not Found', { status: 404 })
511
- return await this.runChain(this.globalMws, delegate, req, ctx)
512
- } catch (e) {
513
- return this.errorHandler
514
- ? this.errorHandler(e as Error, req, ctx)
515
- : new Response('Internal Server Error', { status: 500 })
516
- }
517
- }
518
-
519
- return new Response('Not Found', { status: 404 })
520
- }
521
-
522
- private async runChain(
523
- middlewares: Middleware[],
524
- finalHandler: Handler,
525
- req: Request,
526
- ctx: Context,
527
- ): Promise<Response> {
528
- let index = 0
529
- const dispatch: Handler = async (req, ctx) => {
530
- if (index < middlewares.length) {
531
- const mw = middlewares[index++]
532
- return mw
533
- ? await mw(req, ctx, dispatch)
534
- : new Response('Middleware error', { status: 500 })
535
- }
536
- return await finalHandler(req, ctx)
537
- }
538
- return dispatch(req, ctx)
539
- }
540
- }
541
-
542
- function upgradeSocket(
543
- wss: WebSocketServer,
544
- req: IncomingMessage,
545
- socket: Duplex,
546
- head: Buffer,
547
- handler: WebSocketHandler,
548
- ctx: Context,
549
- ): void {
550
- wss.handleUpgrade(req, socket, head, (ws) => {
551
- if (handler.open) {
552
- handler.open(ws, ctx)
553
- }
554
-
555
- ws.on('message', (data) => {
556
- handler.message?.(ws, ctx, data as string | Buffer)
557
- })
558
-
559
- ws.on('close', () => {
560
- handler.close?.(ws, ctx)
561
- })
562
-
563
- ws.on('error', (err) => {
564
- handler.error?.(ws, ctx, err)
565
- })
566
- })
567
- }
568
-
569
- function sendHttpResponseOnSocket(socket: Duplex, response: Response): void {
570
- const statusLine = `HTTP/1.1 ${response.status} ${response.statusText}`
571
- const headerLines: string[] = [statusLine]
572
- response.headers.forEach((value, key) => {
573
- headerLines.push(`${key}: ${value}`)
574
- })
575
- headerLines.push('Connection: close')
576
- headerLines.push('')
577
- const headerStr = headerLines.join('\r\n')
578
-
579
- response.arrayBuffer().then((buf) => {
580
- const body = Buffer.from(buf)
581
- socket.write(headerStr + '\r\n' + body.toString())
582
- socket.end()
583
- }).catch(() => {
584
- socket.write(headerStr + '\r\n')
585
- socket.end()
586
- })
587
- }
588
-
589
- type GraphQLParams = {
590
- query: string
591
- variables: Record<string, any>
592
- operationName?: string
593
- }
594
-
595
- function parseGraphQLParamsFromGet(url: URL): GraphQLParams | null {
596
- const query = url.searchParams.get('query')
597
- if (!query) return null
598
- const variablesStr = url.searchParams.get('variables')
599
- let variables = {}
600
- if (variablesStr) {
601
- try {
602
- variables = JSON.parse(variablesStr)
603
- } catch {
604
- return null
605
- }
606
- }
607
- return {
608
- query,
609
- variables,
610
- operationName: url.searchParams.get('operationName') || undefined,
611
- }
612
- }
613
-
614
- async function parseGraphQLParamsFromPost(req: Request): Promise<GraphQLParams | null> {
615
- try {
616
- const body = (await req.json()) as {
617
- query?: string
618
- variables?: Record<string, any>
619
- operationName?: string
620
- }
621
- if (!body.query) return null
622
- return {
623
- query: body.query,
624
- variables: body.variables || {},
625
- operationName: body.operationName,
626
- }
627
- } catch {
628
- return null
629
- }
630
- }
631
-
632
- async function executeGraphQLQuery(
633
- schema: GraphQLSchema,
634
- params: GraphQLParams,
635
- options: GraphQLOptions,
636
- req: Request,
637
- ctx: Context,
638
- ): Promise<Response> {
639
- const contextValue = options.context ? await options.context(req, ctx) : ctx
640
- const result = await graphql({
641
- schema,
642
- source: params.query,
643
- rootValue: options.rootValue,
644
- contextValue,
645
- variableValues: params.variables,
646
- operationName: params.operationName,
647
- })
648
- return Response.json(result, { status: result.errors ? 400 : 200 })
649
- }
650
-
651
- function getGraphiQLHtml(endpoint: string): string {
652
- return `<!doctype html>
653
- <html lang="en">
654
- <head>
655
- <meta charset="UTF-8" />
656
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
657
- <title>GraphiQL</title>
658
- <style>
659
- body { margin: 0; }
660
- #graphiql { height: 100dvh; }
661
- </style>
662
- <link rel="stylesheet" href="https://esm.sh/graphiql@5.2.2/dist/style.css" />
663
- <script type="importmap">
664
- {
665
- "imports": {
666
- "react": "https://esm.sh/react@19.2.5",
667
- "react/": "https://esm.sh/react@19.2.5/",
668
- "react-dom": "https://esm.sh/react-dom@19.2.5",
669
- "react-dom/": "https://esm.sh/react-dom@19.2.5/",
670
- "graphiql": "https://esm.sh/graphiql@5.2.2?standalone&external=react,react-dom,@graphiql/react,graphql",
671
- "graphiql/": "https://esm.sh/graphiql@5.2.2/",
672
- "@graphiql/react": "https://esm.sh/@graphiql/react@0.37.3?standalone&external=react,react-dom,graphql,@graphiql/toolkit,@emotion/is-prop-valid",
673
- "@graphiql/toolkit": "https://esm.sh/@graphiql/toolkit@0.11.3?standalone&external=graphql",
674
- "graphql": "https://esm.sh/graphql@16.13.2",
675
- "@emotion/is-prop-valid": "data:text/javascript,"
676
- }
677
- }
678
- </script>
679
- <script type="module">
680
- import React from 'react';
681
- import ReactDOM from 'react-dom/client';
682
- import { GraphiQL } from 'graphiql';
683
- import { createGraphiQLFetcher } from '@graphiql/toolkit';
684
- import 'graphiql/setup-workers/esm.sh';
685
-
686
- const fetcher = createGraphiQLFetcher({ url: "${endpoint}" });
687
-
688
- function App() {
689
- return React.createElement(GraphiQL, { fetcher });
690
- }
691
-
692
- const container = document.getElementById('graphiql');
693
- const root = ReactDOM.createRoot(container);
694
- root.render(React.createElement(App));
695
- </script>
696
- </head>
697
- <body>
698
- <div id="graphiql">Loading\u2026</div>
699
- </body>
700
- </html>`
701
- }