vxrn 1.24.3 → 1.24.4
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/dist/config/getAdditionalViteConfig.mjs +16 -0
- package/dist/config/getAdditionalViteConfig.mjs.map +1 -1
- package/dist/config/getAdditionalViteConfig.native.js +16 -0
- package/dist/config/getAdditionalViteConfig.native.js.map +1 -1
- package/dist/exports/dev.mjs +12 -0
- package/dist/exports/dev.mjs.map +1 -1
- package/dist/exports/dev.native.js +18 -0
- package/dist/exports/dev.native.js.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.mjs +2 -1
- package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.native.js +2 -1
- package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
- package/dist/utils/bindKeypressInput.mjs +9 -20
- package/dist/utils/bindKeypressInput.mjs.map +1 -1
- package/dist/utils/bindKeypressInput.native.js +9 -20
- package/dist/utils/bindKeypressInput.native.js.map +1 -1
- package/dist/utils/createNativeDevEngine.mjs +10 -17
- package/dist/utils/createNativeDevEngine.mjs.map +1 -1
- package/dist/utils/createNativeDevEngine.native.js +10 -18
- package/dist/utils/createNativeDevEngine.native.js.map +1 -1
- package/dist/utils/createNativeDevEngine.test.mjs +1 -4
- package/dist/utils/createNativeDevEngine.test.mjs.map +1 -1
- package/dist/utils/createNativeDevEngine.test.native.js +1 -4
- package/dist/utils/createNativeDevEngine.test.native.js.map +1 -1
- package/package.json +11 -11
- package/src/config/getAdditionalViteConfig.ts +24 -0
- package/src/exports/dev.ts +31 -0
- package/src/rn-commands/bundle/buildBundle.ts +1 -0
- package/src/utils/bindKeypressInput.ts +23 -29
- package/src/utils/createNativeDevEngine.test.ts +1 -5
- package/src/utils/createNativeDevEngine.ts +23 -24
- package/types/config/getAdditionalViteConfig.d.ts.map +1 -1
- package/types/exports/dev.d.ts.map +1 -1
- package/types/rn-commands/bundle/buildBundle.d.ts.map +1 -1
- package/types/utils/bindKeypressInput.d.ts.map +1 -1
- package/types/utils/createNativeDevEngine.d.ts +2 -1
- package/types/utils/createNativeDevEngine.d.ts.map +1 -1
|
@@ -34,37 +34,31 @@ export function bindKeypressInput() {
|
|
|
34
34
|
process.exit(0)
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
+
// ONLY ctrl chords are bound, deliberately. a plain `c` used to clear the
|
|
38
|
+
// screen, and that fired on bytes the user never typed: terminal capability
|
|
39
|
+
// replies (`ESC[?1;2c`, `ESC[>0;95;0c`) end in the letter `c`, and
|
|
40
|
+
// emitKeypressEvents turns that trailing byte into a plain `c` keypress. so
|
|
41
|
+
// did pasting any text containing a `c`, since raw mode delivers a paste as
|
|
42
|
+
// ordinary keystrokes. the result was a dev server that wiped the terminal
|
|
43
|
+
// at apparently random moments, with no way to switch it off — vite's
|
|
44
|
+
// `clearScreen: false` does not cover it, because this never goes through
|
|
45
|
+
// vite's logger. vite gates its own single-key shortcuts behind an explicit
|
|
46
|
+
// `bindCLIShortcuts()` opt-in for exactly this reason.
|
|
47
|
+
//
|
|
48
|
+
// stdin here is very often not a human at a prompt: it is one pane of a
|
|
49
|
+
// process runner, a tmux split, or an editor terminal, so anything that
|
|
50
|
+
// reads a bare letter as a command will misfire.
|
|
37
51
|
process.stdin.on('keypress', (_key, data) => {
|
|
38
52
|
const { ctrl, name } = data
|
|
39
|
-
if (ctrl
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
} else {
|
|
50
|
-
switch (name) {
|
|
51
|
-
case 'r':
|
|
52
|
-
// ctx.broadcastToMessageClients({ method: 'reload' })
|
|
53
|
-
// ctx.log.info({
|
|
54
|
-
// msg: 'Reloading app',
|
|
55
|
-
// })
|
|
56
|
-
break
|
|
57
|
-
case 'd':
|
|
58
|
-
// ctx.broadcastToMessageClients({ method: 'devMenu' })
|
|
59
|
-
// ctx.log.info({
|
|
60
|
-
// msg: 'Opening developer menu',
|
|
61
|
-
// })
|
|
62
|
-
break
|
|
63
|
-
case 'c':
|
|
64
|
-
process.stdout.write('\u001b[2J\u001b[0;0H')
|
|
65
|
-
// TODO: after logging we should print information about port and host
|
|
66
|
-
break
|
|
67
|
-
}
|
|
53
|
+
if (ctrl !== true) return
|
|
54
|
+
switch (name) {
|
|
55
|
+
// biome-ignore lint/suspicious/noFallthroughSwitchClause: <explanation>
|
|
56
|
+
case 'c':
|
|
57
|
+
restoreTerminal()
|
|
58
|
+
process.exit()
|
|
59
|
+
case 'z':
|
|
60
|
+
process.emit('SIGTSTP', 'SIGTSTP')
|
|
61
|
+
break
|
|
68
62
|
}
|
|
69
63
|
})
|
|
70
64
|
}
|
|
@@ -47,9 +47,8 @@ describe('wrapNativeBundleModuleScope', () => {
|
|
|
47
47
|
// a top-level `var Headers` in a script becomes a non-configurable global,
|
|
48
48
|
// which is the exact leak that breaks RN's polyfillGlobal in dev
|
|
49
49
|
const body = `${RUNTIME_MARKER}\nvar fetch_hot, fetch$1, Headers, Request, Response$1;\nglobalThis.__rolldown_runtime__ = {};\n`
|
|
50
|
-
const sourcemap = '\n//# sourceMappingURL=x.js.map'
|
|
51
50
|
|
|
52
|
-
const out = wrapNativeBundleModuleScope(prelude + body
|
|
51
|
+
const out = wrapNativeBundleModuleScope(prelude + body)
|
|
53
52
|
|
|
54
53
|
const openIdx = out.indexOf(';(function() {')
|
|
55
54
|
expect(openIdx).toBeGreaterThan(-1)
|
|
@@ -57,9 +56,6 @@ describe('wrapNativeBundleModuleScope', () => {
|
|
|
57
56
|
expect(out.indexOf('globalThis.__DEV__')).toBeLessThan(openIdx)
|
|
58
57
|
// the leaking declaration is now inside the function scope
|
|
59
58
|
expect(out.indexOf('var fetch_hot')).toBeGreaterThan(openIdx)
|
|
60
|
-
// the wrap closes before the sourceMappingURL, which must remain the last line
|
|
61
|
-
expect(out.indexOf('})();')).toBeLessThan(out.indexOf('//# sourceMappingURL'))
|
|
62
|
-
expect(out.trimEnd().endsWith('//# sourceMappingURL=x.js.map')).toBe(true)
|
|
63
59
|
// and the result must still be syntactically valid (balanced wrap)
|
|
64
60
|
expect(() => new Function(out)).not.toThrow()
|
|
65
61
|
})
|
|
@@ -52,7 +52,7 @@ interface NativeDevEngineOptions {
|
|
|
52
52
|
|
|
53
53
|
interface NativeDevEngineResult {
|
|
54
54
|
engine: any
|
|
55
|
-
getBundle: () => Promise<{ code: string
|
|
55
|
+
getBundle: () => Promise<{ code: string }>
|
|
56
56
|
close: () => Promise<void>
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -242,10 +242,10 @@ function getNativePlugins(
|
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
// shared output options for native builds
|
|
245
|
-
function getNativeOutputOptions(prelude: string): OutputOptions {
|
|
245
|
+
function getNativeOutputOptions(prelude: string, sourcemap: boolean): OutputOptions {
|
|
246
246
|
return {
|
|
247
247
|
format: 'esm',
|
|
248
|
-
sourcemap
|
|
248
|
+
sourcemap,
|
|
249
249
|
intro: prelude,
|
|
250
250
|
codeSplitting: false,
|
|
251
251
|
strictExecutionOrder: true,
|
|
@@ -323,16 +323,7 @@ export function wrapNativeBundleModuleScope(code: string): string {
|
|
|
323
323
|
const idx = code.indexOf(marker)
|
|
324
324
|
if (idx === -1) return code
|
|
325
325
|
|
|
326
|
-
|
|
327
|
-
const close = '\n})();\n'
|
|
328
|
-
|
|
329
|
-
// keep the sourceMappingURL comment as the final line if present
|
|
330
|
-
const sm = code.match(/\n\/\/# sourceMappingURL=[^\n]*\s*$/)
|
|
331
|
-
if (sm) {
|
|
332
|
-
const smIdx = code.lastIndexOf(sm[0])
|
|
333
|
-
return code.slice(0, idx) + open + code.slice(idx, smIdx) + close + code.slice(smIdx)
|
|
334
|
-
}
|
|
335
|
-
return code.slice(0, idx) + open + code.slice(idx) + close
|
|
326
|
+
return code.slice(0, idx) + ';(function() {\n' + code.slice(idx) + '\n})();\n'
|
|
336
327
|
}
|
|
337
328
|
|
|
338
329
|
/**
|
|
@@ -408,7 +399,7 @@ export async function createNativeDevEngine(
|
|
|
408
399
|
serverUrl: serverUrl || `http://${host}:${port}`,
|
|
409
400
|
})
|
|
410
401
|
|
|
411
|
-
let currentBundle: { code: string
|
|
402
|
+
let currentBundle: { code: string } | null = null
|
|
412
403
|
let bundleResolve: ((value: any) => void) | null = null
|
|
413
404
|
let bundlePromise: Promise<any> | null = null
|
|
414
405
|
|
|
@@ -449,7 +440,12 @@ export async function createNativeDevEngine(
|
|
|
449
440
|
}
|
|
450
441
|
|
|
451
442
|
const outputOptions: OutputOptions = {
|
|
452
|
-
|
|
443
|
+
// no dev sourcemap: nothing consumes one. the bundle handler serves .code and
|
|
444
|
+
// /symbolicate isn't implemented, and the map wouldn't line up anyway — the
|
|
445
|
+
// served code is post-processed (runtime downleveling, IIFE wrap) after the
|
|
446
|
+
// map is generated. generating it cost ~90ms and ~250MB RSS per rebuild on a
|
|
447
|
+
// 6MB bundle, held for the life of the dev server, per platform.
|
|
448
|
+
...getNativeOutputOptions(prelude, false),
|
|
453
449
|
// connect HMR WebSocket using RN's WebSocket module (not the global)
|
|
454
450
|
outro: `
|
|
455
451
|
try {
|
|
@@ -503,13 +499,8 @@ try {
|
|
|
503
499
|
// globals and break RN's polyfillGlobal (dev-only redbox). see fn doc.
|
|
504
500
|
code = wrapNativeBundleModuleScope(code)
|
|
505
501
|
|
|
506
|
-
currentBundle = {
|
|
507
|
-
|
|
508
|
-
map: chunk.map?.toString(),
|
|
509
|
-
}
|
|
510
|
-
console.info(
|
|
511
|
-
`[vxrn] native bundle ready (${Math.round(chunk.code.length / 1024)}KB)`
|
|
512
|
-
)
|
|
502
|
+
currentBundle = { code }
|
|
503
|
+
console.info(`[vxrn] native bundle ready (${Math.round(code.length / 1024)}KB)`)
|
|
513
504
|
if (bundleResolve) {
|
|
514
505
|
bundleResolve(currentBundle)
|
|
515
506
|
bundleResolve = null
|
|
@@ -587,6 +578,8 @@ interface NativeBuildOptions {
|
|
|
587
578
|
entryFile?: string
|
|
588
579
|
assetsDest?: string
|
|
589
580
|
plugins?: Plugin[]
|
|
581
|
+
/** only pass when the map is written somewhere — it costs a second copy of the bundle */
|
|
582
|
+
sourcemap?: boolean
|
|
590
583
|
}
|
|
591
584
|
|
|
592
585
|
export async function buildNativeBundle(
|
|
@@ -600,6 +593,7 @@ export async function buildNativeBundle(
|
|
|
600
593
|
entryFile,
|
|
601
594
|
assetsDest,
|
|
602
595
|
plugins: userPlugins = [],
|
|
596
|
+
sourcemap = false,
|
|
603
597
|
} = options
|
|
604
598
|
|
|
605
599
|
const { build } = await import('rolldown')
|
|
@@ -636,7 +630,7 @@ export async function buildNativeBundle(
|
|
|
636
630
|
...getNativePlugins(root, platform, viteImportGlobPlugin, dev, assetsDest),
|
|
637
631
|
...userPlugins,
|
|
638
632
|
],
|
|
639
|
-
output: getNativeOutputOptions(prelude),
|
|
633
|
+
output: getNativeOutputOptions(prelude, sourcemap),
|
|
640
634
|
})
|
|
641
635
|
const chunk = result.output.find((o) => o.type === 'chunk' && o.isEntry)
|
|
642
636
|
|
|
@@ -646,7 +640,12 @@ export async function buildNativeBundle(
|
|
|
646
640
|
|
|
647
641
|
let code = postProcessNativeBundle(chunk.code)
|
|
648
642
|
code = await downlevelClassFieldsInBundle(code)
|
|
649
|
-
|
|
643
|
+
// note: this map is only as good as the chunk's — it describes chunk.code, and
|
|
644
|
+
// the two post-process passes above shift lines. the per-module transforms
|
|
645
|
+
// (vxrnCompilerPlugin, hermesCompatSWCPlugin) also return code without maps, so
|
|
646
|
+
// module positions are post-babel/post-swc. good enough for file attribution,
|
|
647
|
+
// not for exact line/column symbolication.
|
|
648
|
+
return { code, map: sourcemap ? chunk.map?.toString() : undefined }
|
|
650
649
|
}
|
|
651
650
|
|
|
652
651
|
const VIRTUAL_NATIVE_ENTRY = 'virtual:native-entry'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getAdditionalViteConfig.d.ts","sourceRoot":"","sources":["../../src/config/getAdditionalViteConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,MAAM,CAAA;AAMpD;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"getAdditionalViteConfig.d.ts","sourceRoot":"","sources":["../../src/config/getAdditionalViteConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,MAAM,CAAA;AAMpD;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAyEvE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/exports/dev.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/exports/dev.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AA+C3C,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG;IACrC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,GAAG,GAAU,WAAW,UAAU;;;;;;EAwM9C,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildBundle.d.ts","sourceRoot":"","sources":["../../../src/rn-commands/bundle/buildBundle.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,qCAAqC,CAAA;AAI5C,YAAY,EAAE,iBAAiB,EAAE,CAAA;AAEjC,wBAAsB,WAAW,CAC/B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EACpB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,iBAAiB,EACvB,UAAU,GAAE,GAAU,GACrB,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"buildBundle.d.ts","sourceRoot":"","sources":["../../../src/rn-commands/bundle/buildBundle.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,qCAAqC,CAAA;AAI5C,YAAY,EAAE,iBAAiB,EAAE,CAAA;AAEjC,wBAAsB,WAAW,CAC/B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EACpB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,iBAAiB,EACvB,UAAU,GAAE,GAAU,GACrB,OAAO,CAAC,IAAI,CAAC,CAuEf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bindKeypressInput.d.ts","sourceRoot":"","sources":["../../src/utils/bindKeypressInput.ts"],"names":[],"mappings":"AAeA,wBAAgB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"bindKeypressInput.d.ts","sourceRoot":"","sources":["../../src/utils/bindKeypressInput.ts"],"names":[],"mappings":"AAeA,wBAAgB,iBAAiB,SAgDhC"}
|
|
@@ -24,7 +24,6 @@ interface NativeDevEngineResult {
|
|
|
24
24
|
engine: any;
|
|
25
25
|
getBundle: () => Promise<{
|
|
26
26
|
code: string;
|
|
27
|
-
map?: string;
|
|
28
27
|
}>;
|
|
29
28
|
close: () => Promise<void>;
|
|
30
29
|
}
|
|
@@ -71,6 +70,8 @@ interface NativeBuildOptions {
|
|
|
71
70
|
entryFile?: string;
|
|
72
71
|
assetsDest?: string;
|
|
73
72
|
plugins?: Plugin[];
|
|
73
|
+
/** only pass when the map is written somewhere — it costs a second copy of the bundle */
|
|
74
|
+
sourcemap?: boolean;
|
|
74
75
|
}
|
|
75
76
|
export declare function buildNativeBundle(options: NativeBuildOptions): Promise<{
|
|
76
77
|
code: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createNativeDevEngine.d.ts","sourceRoot":"","sources":["../../src/utils/createNativeDevEngine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAA+B,MAAM,EAAkB,MAAM,UAAU,CAAA;AA0BnF,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CAE3D;AAED,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CAChE;AAED,UAAU,qBAAqB;IAC7B,MAAM,EAAE,GAAG,CAAA;IACX,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"createNativeDevEngine.d.ts","sourceRoot":"","sources":["../../src/utils/createNativeDevEngine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAA+B,MAAM,EAAkB,MAAM,UAAU,CAAA;AA0BnF,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CAE3D;AAED,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CAChE;AAED,UAAU,qBAAqB;IAC7B,MAAM,EAAE,GAAG,CAAA;IACX,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC1C,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAuBD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,KAAK,GAAG,SAAS,EAC3B,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM;;;;;;;;EAqHb;AAgGD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOhE;AAoDD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CA4LhC;AAID,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAA;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,yFAAyF;IACzF,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA8DzC;AA4KD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAuB5C;AAoBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAwGzE"}
|