carrick 0.3.58 → 0.3.59

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 (58) hide show
  1. package/README.md +94 -26
  2. package/bin/carrick.mjs +13 -2
  3. package/dist/auth/credentials.d.ts +14 -0
  4. package/dist/auth/credentials.js +86 -0
  5. package/dist/auth/credentials.js.map +1 -0
  6. package/dist/auth/oauth.d.ts +11 -0
  7. package/dist/auth/oauth.js +119 -0
  8. package/dist/auth/oauth.js.map +1 -0
  9. package/dist/auth/read.d.ts +139 -0
  10. package/dist/auth/read.js +44 -0
  11. package/dist/auth/read.js.map +1 -0
  12. package/dist/auth/run.d.ts +12 -0
  13. package/dist/auth/run.js +68 -0
  14. package/dist/auth/run.js.map +1 -0
  15. package/dist/contract.d.ts +10 -0
  16. package/dist/contract.js +3 -0
  17. package/dist/contract.js.map +1 -1
  18. package/dist/definition.js +2 -2
  19. package/dist/definition.js.map +1 -1
  20. package/dist/diagnostics.d.ts +35 -1
  21. package/dist/diagnostics.js +52 -11
  22. package/dist/diagnostics.js.map +1 -1
  23. package/dist/hook/refresh.d.ts +32 -0
  24. package/dist/hook/refresh.js +138 -0
  25. package/dist/hook/refresh.js.map +1 -0
  26. package/dist/hook/session-start.js +13 -0
  27. package/dist/hook/session-start.js.map +1 -1
  28. package/dist/init/connect.d.ts +17 -0
  29. package/dist/init/connect.js +120 -0
  30. package/dist/init/connect.js.map +1 -0
  31. package/dist/init/mcp.d.ts +50 -0
  32. package/dist/init/mcp.js +235 -0
  33. package/dist/init/mcp.js.map +1 -0
  34. package/dist/init/projects.d.ts +46 -0
  35. package/dist/init/projects.js +137 -0
  36. package/dist/init/projects.js.map +1 -0
  37. package/dist/init/repos.d.ts +113 -19
  38. package/dist/init/repos.js +60 -39
  39. package/dist/init/repos.js.map +1 -1
  40. package/dist/init/run.d.ts +16 -0
  41. package/dist/init/run.js +243 -61
  42. package/dist/init/run.js.map +1 -1
  43. package/dist/init/settings.d.ts +1 -1
  44. package/dist/init/settings.js +1 -1
  45. package/dist/init/settings.js.map +1 -1
  46. package/dist/server.js +173 -16
  47. package/dist/server.js.map +1 -1
  48. package/package.json +6 -6
  49. package/sidecar/dist/src/capture/deno-project.d.ts +41 -0
  50. package/sidecar/dist/src/capture/deno-project.js +513 -0
  51. package/sidecar/dist/src/capture/index.d.ts +1 -0
  52. package/sidecar/dist/src/capture/index.js +60 -19
  53. package/sidecar/dist/src/capture/self-check.d.ts +2 -0
  54. package/sidecar/dist/src/capture/self-check.js +3 -2
  55. package/sidecar/dist/src/project-loader.js +22 -1
  56. package/dist/init/identity.d.ts +0 -20
  57. package/dist/init/identity.js +0 -60
  58. package/dist/init/identity.js.map +0 -1
@@ -37,6 +37,8 @@ import { installedVersions, lockfileVersions } from './lockfile.js';
37
37
  import { rewriteEmittedSpecifiers } from './paths-rewrite.js';
38
38
  import { selfCheckStub } from './self-check.js';
39
39
  import { collectSpecifiers, isRelative, packageNameOf } from './specifiers.js';
40
+ import { DenoProject, findDenoConfig } from './deno-project.js';
41
+ export { DenoProject, findDenoConfig } from './deno-project.js';
40
42
  // v2 check core ("tsc as the judge"). Same bundle, same seam: the sidecar
41
43
  // reaches it only through this door (index.js).
42
44
  export { runCheck } from './check.js';
@@ -90,10 +92,23 @@ export function captureStub(opts) {
90
92
  const stubDir = path.resolve(opts.outDir);
91
93
  const errors = [];
92
94
  const configPath = opts.tsconfigPath
93
- ? path.resolve(opts.tsconfigPath)
95
+ ? path.resolve(repoRoot, opts.tsconfigPath)
94
96
  : path.join(repoRoot, 'tsconfig.json');
95
97
  let parsed;
96
- if (!fs.existsSync(configPath)) {
98
+ let deno;
99
+ try {
100
+ const config = findDenoConfig(repoRoot, opts.tsconfigPath);
101
+ if (config)
102
+ deno = new DenoProject(config, repoRoot);
103
+ }
104
+ catch (err) {
105
+ return fail(stubDir, packageName, [err instanceof Error ? err.message : String(err)]);
106
+ }
107
+ if (deno) {
108
+ parsed = deno.parsed;
109
+ errors.push(...deno.diagnostics);
110
+ }
111
+ else if (!fs.existsSync(configPath)) {
97
112
  if (opts.tsconfigPath) {
98
113
  // An explicitly named tsconfig that does not exist is a caller bug.
99
114
  return fail(stubDir, packageName, [`tsconfig not found at ${configPath}`]);
@@ -137,17 +152,20 @@ export function captureStub(opts) {
137
152
  const entryDir = parsed.options.rootDir
138
153
  ? path.resolve(path.dirname(configPath), parsed.options.rootDir)
139
154
  : repoRoot;
140
- const entryPath = path.join(entryDir, `${SURFACE_ENTRY_BASENAME}.ts`);
155
+ const entryPath = deno
156
+ ? path.join(deno.cacheDir, `${SURFACE_ENTRY_BASENAME}.ts`)
157
+ : path.join(entryDir, `${SURFACE_ENTRY_BASENAME}.ts`);
158
+ fs.mkdirSync(path.dirname(entryPath), { recursive: true });
141
159
  // ---- Phase A: analysis program over placeholder entry + anchor sources ----
142
160
  let resolved;
143
161
  try {
144
- resolved = resolveAnchors(opts, parsed, { repoRoot, entryDir, entryPath });
162
+ resolved = resolveAnchors(opts, parsed, { repoRoot, entryDir: path.dirname(entryPath), entryPath }, deno);
145
163
  }
146
164
  catch (err) {
147
165
  return fail(stubDir, packageName, [err instanceof Error ? err.message : String(err)]);
148
166
  }
149
167
  // ---- Augmentation detection over the tsconfig's full file list ----
150
- const augmentationSources = findAugmentationFiles(parsed.fileNames.filter((f) => !f.includes(`${path.sep}node_modules${path.sep}`)));
168
+ const augmentationSources = [...new Set([...findAugmentationFiles(parsed.fileNames.filter((f) => !f.includes(`${path.sep}node_modules${path.sep}`))), ...(deno?.globals ?? [])])];
151
169
  // ---- Phase B: declaration emit of the final entry ----
152
170
  const entryLines = ['// Generated by Carrick capture v2. Deleted after emit.'];
153
171
  for (const anchor of resolved) {
@@ -162,6 +180,7 @@ export function captureStub(opts) {
162
180
  // hand-written declarations in the import closure) are never re-emitted by
163
181
  // tsc; they must ship verbatim or the tree's references to them dangle.
164
182
  const declarationSources = new Map();
183
+ const sourceByEmitted = new Map();
165
184
  let emitPartial = false;
166
185
  try {
167
186
  fs.writeFileSync(entryPath, entryLines.join('\n') + '\n');
@@ -179,8 +198,12 @@ export function captureStub(opts) {
179
198
  outDir: staging,
180
199
  rootDir: entryDir,
181
200
  };
182
- const program = ts.createProgram([entryPath, ...augmentationSources], emitOptions);
183
- const emitResult = program.emit(undefined, (fileName, text) => emitted.set(fileName, text), undefined,
201
+ const program = ts.createProgram([entryPath, ...augmentationSources], emitOptions, deno?.host(emitOptions));
202
+ const emitResult = program.emit(undefined, (fileName, text, _bom, _error, sources) => {
203
+ emitted.set(fileName, text);
204
+ if (sources?.[0])
205
+ sourceByEmitted.set(path.relative(staging, fileName).split(path.sep).join('/'), sources[0].fileName);
206
+ }, undefined,
184
207
  /* emitOnlyDtsFiles */ true);
185
208
  // emitSkipped is PER-PROGRAM even when only one file's declaration emit
186
209
  // failed (e.g. TS4023 from a hand-rolled ambient stub shadowing a real
@@ -202,6 +225,7 @@ export function captureStub(opts) {
202
225
  if (rel.startsWith('..') || rel.includes('node_modules/'))
203
226
  continue;
204
227
  declarationSources.set(rel, sourceFile.getFullText());
228
+ sourceByEmitted.set(rel, abs);
205
229
  }
206
230
  }
207
231
  catch (err) {
@@ -235,8 +259,13 @@ export function captureStub(opts) {
235
259
  let surfaceAbsPath = '';
236
260
  for (const [fileName, text] of emitted) {
237
261
  let rel = path.relative(staging, fileName).split(path.sep).join('/');
238
- if (rel === `${SURFACE_ENTRY_BASENAME}.d.ts`)
262
+ if (path.basename(rel) === `${SURFACE_ENTRY_BASENAME}.d.ts`) {
263
+ const source = sourceByEmitted.get(rel);
264
+ sourceByEmitted.delete(rel);
239
265
  rel = 'surface.d.ts';
266
+ if (source)
267
+ sourceByEmitted.set(rel, source);
268
+ }
240
269
  const dest = path.join(typesDir, rel);
241
270
  fs.mkdirSync(path.dirname(dest), { recursive: true });
242
271
  fs.writeFileSync(dest, text);
@@ -268,7 +297,14 @@ export function captureStub(opts) {
268
297
  .filter((rel) => emittedFiles.includes(rel))
269
298
  .map((rel) => `types/${rel}`);
270
299
  // ---- Post-emit specifier rewrite (paths mappings + absolute internals) ----
271
- const specifierRewrites = rewriteEmittedSpecifiers({
300
+ let denoRewrites = 0;
301
+ try {
302
+ denoRewrites = deno?.rewrite(typesDir, emittedFiles, sourceByEmitted) ?? 0;
303
+ }
304
+ catch (err) {
305
+ return fail(stubDir, packageName, [err instanceof Error ? err.message : String(err)]);
306
+ }
307
+ const specifierRewrites = denoRewrites + rewriteEmittedSpecifiers({
272
308
  typesDir,
273
309
  files: emittedFiles,
274
310
  options: parsed.options,
@@ -297,16 +333,19 @@ export function captureStub(opts) {
297
333
  // only transitives resolve").
298
334
  const installed = installedVersions(repoRoot, externalSpecs);
299
335
  const lockVersions = lockfileVersions(repoRoot);
336
+ for (const name of Object.keys(deno?.pinned ?? {}))
337
+ externalSpecs.add(name);
300
338
  const pinned = {};
301
339
  const unpinned = [];
302
340
  for (const name of [...externalSpecs].sort()) {
303
- const version = installed.get(name) ?? lockVersions.get(name);
341
+ const version = deno?.pinned[name] ?? installed.get(name) ?? lockVersions.get(name);
304
342
  if (version)
305
343
  pinned[name] = version;
306
344
  else
307
345
  unpinned.push(name);
308
346
  }
309
- const bareCheckout = !fs.existsSync(path.join(repoRoot, 'node_modules'));
347
+ const dependencyRoot = deno?.config.workspaceRoot ?? repoRoot;
348
+ const bareCheckout = !deno && !fs.existsSync(path.join(dependencyRoot, 'node_modules'));
310
349
  fs.writeFileSync(path.join(stubDir, 'package.json'), JSON.stringify({
311
350
  name: packageName,
312
351
  version: '0.0.0-carrick',
@@ -329,7 +368,8 @@ export function captureStub(opts) {
329
368
  resolved,
330
369
  pinned,
331
370
  bareCheckout,
332
- repoRoot,
371
+ repoRoot: dependencyRoot,
372
+ compilerHost: deno ? options => deno.host(options) : undefined,
333
373
  });
334
374
  const fidelity = computeFidelity(aliases);
335
375
  fs.writeFileSync(path.join(stubDir, 'carrick-manifest.json'), JSON.stringify({
@@ -371,7 +411,7 @@ function demoteDanglingAliases(args) {
371
411
  let surfaceKey;
372
412
  for (const fileName of args.emitted.keys()) {
373
413
  const rel = path.relative(args.staging, fileName).split(path.sep).join('/');
374
- if (rel === `${SURFACE_ENTRY_BASENAME}.d.ts`)
414
+ if (path.basename(rel) === `${SURFACE_ENTRY_BASENAME}.d.ts`)
375
415
  surfaceKey = fileName;
376
416
  if (rel.endsWith('.d.ts'))
377
417
  treeModules.add(rel.slice(0, -'.d.ts'.length));
@@ -380,10 +420,10 @@ function demoteDanglingAliases(args) {
380
420
  if (rel.endsWith('.d.ts'))
381
421
  treeModules.add(rel.slice(0, -'.d.ts'.length));
382
422
  }
383
- // The surface sits at the tree root, so its relative specifiers resolve
384
- // against the root; anything escaping the root cannot be in the tree.
423
+ // Deno's temporary surface lives in the cache inside the emitted tree.
424
+ const surfaceDir = surfaceKey ? path.posix.dirname(path.relative(args.staging, surfaceKey).split(path.sep).join('/')) : '.';
385
425
  const moduleInTree = (spec) => {
386
- const id = path.posix.normalize(spec);
426
+ const id = path.posix.normalize(path.posix.join(surfaceDir, spec));
387
427
  if (id.startsWith('..'))
388
428
  return false;
389
429
  return treeModules.has(id) || treeModules.has(`${id}/index`);
@@ -429,7 +469,7 @@ function rewriteSurfaceAliasesToUnknown(text, demoted) {
429
469
  return out;
430
470
  }
431
471
  /** Phase A: build the placeholder entry, then resolve every anchor. */
432
- function resolveAnchors(opts, parsed, ctx) {
472
+ function resolveAnchors(opts, parsed, ctx, deno) {
433
473
  const placeholderLines = ['// Carrick capture v2 analysis placeholder.'];
434
474
  for (const anchor of opts.anchors) {
435
475
  placeholderLines.push(`export type ${anchor.alias} = unknown;`);
@@ -441,10 +481,11 @@ function resolveAnchors(opts, parsed, ctx) {
441
481
  .filter((a) => a.kind !== 'literal')
442
482
  .map((a) => path.join(ctx.repoRoot, a.source_file))),
443
483
  ].filter((f) => fs.existsSync(f));
444
- const program = ts.createProgram([ctx.entryPath, ...anchorSources], {
484
+ const options = {
445
485
  ...parsed.options,
446
486
  noEmit: true,
447
- });
487
+ };
488
+ const program = ts.createProgram([ctx.entryPath, ...anchorSources, ...(deno?.globals ?? [])], options, deno?.host(options));
448
489
  const entrySource = program.getSourceFile(ctx.entryPath);
449
490
  const placeholders = new Map();
450
491
  if (entrySource) {
@@ -24,6 +24,7 @@
24
24
  * (import-type seeds, then BFS over relative imports). The spike's
25
25
  * file-granularity shortcut is gone.
26
26
  */
27
+ import ts from 'typescript';
27
28
  import type { CaptureAliasRecord } from './api.js';
28
29
  import type { ResolvedAnchor } from './anchors.js';
29
30
  export interface SelfCheckArgs {
@@ -34,5 +35,6 @@ export interface SelfCheckArgs {
34
35
  bareCheckout: boolean;
35
36
  /** Producer repo root; its node_modules (if any) backs resolution. */
36
37
  repoRoot: string;
38
+ compilerHost?: (options: ts.CompilerOptions) => ts.CompilerHost;
37
39
  }
38
40
  export declare function selfCheckStub(args: SelfCheckArgs): CaptureAliasRecord[];
@@ -61,7 +61,7 @@ export function selfCheckStub(args) {
61
61
  }
62
62
  }
63
63
  function runSelfCheck(args, treeFiles) {
64
- const program = ts.createProgram(treeFiles, {
64
+ const options = {
65
65
  noEmit: true,
66
66
  strict: true,
67
67
  // MUST be false: the whole stub tree is .d.ts (see module header).
@@ -69,7 +69,8 @@ function runSelfCheck(args, treeFiles) {
69
69
  module: ts.ModuleKind.ESNext,
70
70
  moduleResolution: ts.ModuleResolutionKind.Bundler,
71
71
  types: [],
72
- });
72
+ };
73
+ const program = ts.createProgram(treeFiles, options, args.compilerHost?.(options));
73
74
  const checker = program.getTypeChecker();
74
75
  const diagnostics = ts.getPreEmitDiagnostics(program);
75
76
  // Failed module specifiers, split external-pinned vs internal, per FILE.
@@ -12,6 +12,7 @@
12
12
  import { Project } from 'ts-morph';
13
13
  import * as path from 'node:path';
14
14
  import * as fs from 'node:fs';
15
+ import { DenoProject, findDenoConfig } from './capture/index.js';
15
16
  /**
16
17
  * Source-file patterns used when the repo declares no tsconfig, relative to
17
18
  * the repo root. `node_modules` is excluded explicitly: a glob that matches
@@ -169,7 +170,27 @@ export class ProjectLoader {
169
170
  // Priority 2: Use tsconfig.json file
170
171
  else {
171
172
  const tsconfigPath = this.findTsConfig();
172
- if (tsconfigPath) {
173
+ const denoConfig = findDenoConfig(this.repoRoot, this.tsconfigPath);
174
+ if (denoConfig) {
175
+ this.log(`Project will load with Deno config: ${denoConfig.configPath}`);
176
+ this.buildProject = () => {
177
+ const deno = new DenoProject(denoConfig, this.repoRoot);
178
+ const project = new Project({
179
+ compilerOptions: deno.parsed.options,
180
+ skipAddingFilesFromTsConfig: true,
181
+ resolutionHost: (host, getOptions) => ({
182
+ resolveModuleNames: (names, from) => names.map(name => deno.resolve(name, from, getOptions(), host)),
183
+ resolveTypeReferenceDirectives: (names, from) => names.map(name => deno.resolveTypeReference(typeof name === 'string' ? name : name.fileName, from, getOptions(), host)),
184
+ }),
185
+ });
186
+ for (const file of deno.parsed.fileNames)
187
+ project.addSourceFileAtPath(file);
188
+ for (const diagnostic of deno.diagnostics)
189
+ this.logError(diagnostic);
190
+ return project;
191
+ };
192
+ }
193
+ else if (tsconfigPath) {
173
194
  this.log(`Project will load with tsconfig: ${tsconfigPath}`);
174
195
  this.buildProject = () => new Project({
175
196
  tsConfigFilePath: tsconfigPath,
@@ -1,20 +0,0 @@
1
- export type Identity = {
2
- /** The GitHub login, when the source could name one. */
3
- login: string | null;
4
- source: "gh" | "token";
5
- };
6
- export type IdentityLookup = {
7
- identity: Identity | null;
8
- /** What to do about it, ready to print. Null when there is an identity. */
9
- problem: string | null;
10
- };
11
- export type IdentityOptions = {
12
- env?: NodeJS.ProcessEnv;
13
- /** Injectable for tests: runs `gh auth status` and returns its output. */
14
- ghStatus?: () => string;
15
- };
16
- /** The login out of `gh auth status`, whatever wording it used. */
17
- export declare function loginFromGhStatus(output: string): string | null;
18
- export declare function githubIdentity(options?: IdentityOptions): IdentityLookup;
19
- /** One line for the summary. */
20
- export declare function describeIdentity(identity: Identity): string;
@@ -1,60 +0,0 @@
1
- // The GitHub identity `carrick init` requires.
2
- //
3
- // There is no anonymous tier (carrick#729, ruled 2026-09-08): the local index
4
- // is built from the identified free tier's allowance, so setup asks who you are
5
- // before it writes anything. The check is offline and reuses whatever the
6
- // machine already has — the GitHub CLI's login, or a token in the environment —
7
- // rather than opening a browser flow of its own.
8
- //
9
- // This states the identity. Spending an allowance against it is the cloud's
10
- // side (carrick-cloud#601) and is not wired here.
11
- import { spawnSync } from "node:child_process";
12
- function defaultGhStatus() {
13
- // Both streams: `gh auth status` writes to stderr on older versions and to
14
- // stdout on newer ones, and a run that reads one of them finds nothing on
15
- // half the machines it runs on.
16
- const run = spawnSync("gh", ["auth", "status"], { encoding: "utf8" });
17
- if (run.error)
18
- throw run.error;
19
- return `${run.stdout ?? ""}\n${run.stderr ?? ""}`;
20
- }
21
- /** The login out of `gh auth status`, whatever wording it used. */
22
- export function loginFromGhStatus(output) {
23
- const match = /Logged in to \S+ account (\S+)/.exec(output) ?? /Logged in to \S+ as (\S+)/.exec(output);
24
- return match?.[1] ?? null;
25
- }
26
- export function githubIdentity(options = {}) {
27
- const env = options.env ?? process.env;
28
- const ghStatus = options.ghStatus ?? defaultGhStatus;
29
- try {
30
- const login = loginFromGhStatus(ghStatus());
31
- if (login)
32
- return { identity: { login, source: "gh" }, problem: null };
33
- }
34
- catch {
35
- // No gh, or gh is not logged in. The token below is the other way in.
36
- }
37
- const token = env["GITHUB_TOKEN"] || env["GH_TOKEN"];
38
- if (token)
39
- return { identity: { login: null, source: "token" }, problem: null };
40
- return {
41
- identity: null,
42
- problem: [
43
- "carrick init needs your GitHub identity, and this machine has none it can use.",
44
- "",
45
- "Either:",
46
- " gh auth login (the GitHub CLI: https://cli.github.com)",
47
- " export GITHUB_TOKEN=<token> (any token that identifies you)",
48
- "",
49
- "Carrick indexes what you already have access to, and the free tier's",
50
- "allowance is counted against the account that asks for it.",
51
- ].join("\n"),
52
- };
53
- }
54
- /** One line for the summary. */
55
- export function describeIdentity(identity) {
56
- return identity.login
57
- ? `GitHub identity: ${identity.login} (from the GitHub CLI)`
58
- : "GitHub identity: the token in this environment";
59
- }
60
- //# sourceMappingURL=identity.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/init/identity.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,0EAA0E;AAC1E,gFAAgF;AAChF,iDAAiD;AACjD,EAAE;AACF,4EAA4E;AAC5E,kDAAkD;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAoB/C,SAAS,eAAe;IACtB,2EAA2E;IAC3E,0EAA0E;IAC1E,gCAAgC;IAChC,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACtE,IAAI,GAAG,CAAC,KAAK;QAAE,MAAM,GAAG,CAAC,KAAK,CAAC;IAC/B,OAAO,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,KAAK,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;AACpD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,KAAK,GACT,gCAAgC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,2BAA2B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5F,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAA2B,EAAE;IAC1D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,eAAe,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC5C,IAAI,KAAK;YAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;IACxE,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IACrD,IAAI,KAAK;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAEhF,OAAO;QACL,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE;YACP,gFAAgF;YAChF,EAAE;YACF,SAAS;YACT,0EAA0E;YAC1E,iEAAiE;YACjE,EAAE;YACF,sEAAsE;YACtE,4DAA4D;SAC7D,CAAC,IAAI,CAAC,IAAI,CAAC;KACb,CAAC;AACJ,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IACjD,OAAO,QAAQ,CAAC,KAAK;QACnB,CAAC,CAAC,oBAAoB,QAAQ,CAAC,KAAK,wBAAwB;QAC5D,CAAC,CAAC,gDAAgD,CAAC;AACvD,CAAC"}