@fairgarden/monolith 0.1.0-0.canary.0

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 (54) hide show
  1. package/Readme.md +84 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +160 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/compat.d.ts +4 -0
  7. package/dist/compat.d.ts.map +1 -0
  8. package/dist/compat.js +174 -0
  9. package/dist/compat.js.map +1 -0
  10. package/dist/eslint.d.ts +62 -0
  11. package/dist/eslint.d.ts.map +1 -0
  12. package/dist/eslint.js +198 -0
  13. package/dist/eslint.js.map +1 -0
  14. package/dist/index.d.ts +28 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +84 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/link.d.ts +24 -0
  19. package/dist/link.d.ts.map +1 -0
  20. package/dist/link.js +473 -0
  21. package/dist/link.js.map +1 -0
  22. package/dist/mounts.d.ts +37 -0
  23. package/dist/mounts.d.ts.map +1 -0
  24. package/dist/mounts.js +58 -0
  25. package/dist/mounts.js.map +1 -0
  26. package/dist/package-json.d.ts +38 -0
  27. package/dist/package-json.d.ts.map +1 -0
  28. package/dist/package-json.js +156 -0
  29. package/dist/package-json.js.map +1 -0
  30. package/dist/portability.d.ts +41 -0
  31. package/dist/portability.d.ts.map +1 -0
  32. package/dist/portability.js +171 -0
  33. package/dist/portability.js.map +1 -0
  34. package/dist/portable-link.d.ts +22 -0
  35. package/dist/portable-link.d.ts.map +1 -0
  36. package/dist/portable-link.js +24 -0
  37. package/dist/portable-link.js.map +1 -0
  38. package/dist/proxies.d.ts +33 -0
  39. package/dist/proxies.d.ts.map +1 -0
  40. package/dist/proxies.js +177 -0
  41. package/dist/proxies.js.map +1 -0
  42. package/dist/resolve.d.ts +5 -0
  43. package/dist/resolve.d.ts.map +1 -0
  44. package/dist/resolve.js +181 -0
  45. package/dist/resolve.js.map +1 -0
  46. package/dist/routes.d.ts +23 -0
  47. package/dist/routes.d.ts.map +1 -0
  48. package/dist/routes.js +102 -0
  49. package/dist/routes.js.map +1 -0
  50. package/dist/types.d.ts +111 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +2 -0
  53. package/dist/types.js.map +1 -0
  54. package/package.json +77 -0
package/Readme.md ADDED
@@ -0,0 +1,84 @@
1
+ # FairGarden Monolith
2
+
3
+ <!-- fg:version -->
4
+
5
+ Version **0.1.0-alpha.1**
6
+
7
+ <!-- /fg:version -->
8
+
9
+ <!-- fg:releasing -->
10
+
11
+ ## Releasing
12
+
13
+ This module releases on its own. `0.1.0-alpha.1` is what main is working towards,
14
+ not what is published — the version here is always the next one.
15
+
16
+ 1. **Publish it.** Run the *Publish* workflow from the Actions tab, picking the
17
+ dist tag. It refuses if that version is already on npm.
18
+ 2. **Move it on.** `pnpm release` — opens a pull request bumping this branch
19
+ to `0.1.0-alpha.2`, or `pnpm release --id rc` to change
20
+ identifier. A prerelease gets no maintenance branch; there is no released
21
+ line behind it yet.
22
+
23
+ Every push to main publishes `@fairgarden/monolith@canary`. A canary is not a release and
24
+ carries no promise; it is there so main can be tried without a checkout.
25
+
26
+ <!-- /fg:releasing -->
27
+
28
+ Compose several Next.js apps into one deployable app.
29
+
30
+ ```ts
31
+ // apps/monolith/next.config.ts
32
+ import { withMonolith } from '@fairgarden/monolith'
33
+
34
+ export default withMonolith(
35
+ {},
36
+ {
37
+ www: { package: '@fairgarden/www', prefix: '/' },
38
+ id: '@fairgarden/id',
39
+ }
40
+ )
41
+ ```
42
+
43
+ `id`'s routes are served from `/id`, its assets from `public/id`, and its Pages
44
+ Router API from `/api/id`. `www` takes the site root.
45
+
46
+ ## Documentation
47
+
48
+ The docs are a site in this repository. Run them with:
49
+
50
+ ```bash
51
+ pnpm --filter @fairgarden/monolith-docs dev
52
+ ```
53
+
54
+ - **Overview** — what mounting an app actually does
55
+ - **Mounting** — symlinks, and why `next dev` needs different treatment
56
+ - **Routing** — how rewrites, redirects and headers are merged
57
+ - **What a monolith can serve** — root mounts, and when apps collide
58
+ - **Next versions** — which versions can be mounted together
59
+ - **Dependencies** — what the monolith has to install
60
+ - **Portability** — keeping an app mountable
61
+ - **Functions** — `withMonolith`, `createLink`, `prefixPath` and the rest
62
+
63
+ ## Install
64
+
65
+ ```bash
66
+ pnpm add @fairgarden/monolith
67
+ ```
68
+
69
+ | Import | For |
70
+ | --- | --- |
71
+ | `@fairgarden/monolith` | the monolith's `next.config.ts`, and an app's portability check |
72
+ | `@fairgarden/monolith/link` | an app's own components |
73
+ | `@fairgarden/monolith/eslint` | an app's `eslint.config.mjs` |
74
+
75
+ It also installs `fg-monolith`, for the things that happen around a build:
76
+
77
+ ```bash
78
+ fg-monolith link # mount without starting Next
79
+ fg-monolith merge-package-json # fold each app's dependencies in
80
+ fg-monolith list # print the apps it composes
81
+ ```
82
+
83
+ Submodules, versions and scaffolding are a separate concern, handled by
84
+ `fg-dist` in `@fairgarden/distribution`.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env node
2
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
3
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
4
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
5
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
6
+ });
7
+ }
8
+ return path;
9
+ };
10
+ import path from 'node:path';
11
+ import { pathToFileURL } from 'node:url';
12
+ import { statSync } from 'node:fs';
13
+ import { linkApps } from "./link.js";
14
+ import { mergeAppDependencies, writePackageJson } from "./package-json.js";
15
+ import { getRegisteredApps } from "./index.js";
16
+ // Piping into `head` closes stdout early; that is ordinary use, not a failure.
17
+ for (const stream of [process.stdout, process.stderr]) {
18
+ stream.on('error', (error) => {
19
+ if (error.code === 'EPIPE')
20
+ process.exit(0);
21
+ throw error;
22
+ });
23
+ }
24
+ const USAGE = `Usage: fg-monolith <command> [options]
25
+
26
+ Commands:
27
+ link Mount every app's routes and assets into the monolith
28
+ merge-package-json Fold every app's dependencies into the monolith's package.json
29
+ list Print the apps the monolith composes
30
+
31
+ Options:
32
+ --cwd <dir> Monolith directory (default: the working directory)
33
+ --strategy <name> source | mirror | hardlink | copy (default: source)
34
+ --check Report what would change without writing (merge-package-json)
35
+ --all Take every app dependency, not only what its pages need
36
+
37
+ Submodules, versions and scaffolding are handled by \`fg-dist\`, in
38
+ @fairgarden/distribution.
39
+ `;
40
+ const CONFIG_FILES = [
41
+ 'next.config.ts',
42
+ 'next.config.mts',
43
+ 'next.config.js',
44
+ 'next.config.mjs',
45
+ 'next.config.cjs',
46
+ ];
47
+ const parseArgs = (argv) => {
48
+ const args = {
49
+ command: undefined,
50
+ cwd: process.cwd(),
51
+ strategy: 'source',
52
+ check: false,
53
+ all: false,
54
+ };
55
+ for (let index = 0; index < argv.length; index += 1) {
56
+ const arg = argv[index];
57
+ if (arg === '--cwd') {
58
+ args.cwd = path.resolve(argv[++index] ?? '.');
59
+ }
60
+ else if (arg === '--strategy') {
61
+ args.strategy = (argv[++index] ?? 'source');
62
+ }
63
+ else if (arg === '--check') {
64
+ args.check = true;
65
+ }
66
+ else if (arg === '--all') {
67
+ args.all = true;
68
+ }
69
+ else if (!arg.startsWith('-') && !args.command) {
70
+ args.command = arg;
71
+ }
72
+ else {
73
+ throw new Error(`Unrecognized argument: ${arg}`);
74
+ }
75
+ }
76
+ return args;
77
+ };
78
+ /**
79
+ * The monolith's own Next config is the single source of truth for which apps
80
+ * it composes, so load it — with linking disabled — and read back what it
81
+ * registered.
82
+ */
83
+ const loadApps = async (cwd) => {
84
+ const configPath = CONFIG_FILES.map((file) => path.join(cwd, file)).find((file) => {
85
+ try {
86
+ return statSync(file).isFile();
87
+ }
88
+ catch {
89
+ return false;
90
+ }
91
+ });
92
+ if (!configPath) {
93
+ throw new Error(`No Next config found in ${cwd}.`);
94
+ }
95
+ process.env.FG_MONOLITH_SKIP_LINK = '1';
96
+ const loaded = (await import(__rewriteRelativeImportExtension(pathToFileURL(configPath).href))).default;
97
+ if (typeof loaded === 'function')
98
+ await loaded('phase-production-build');
99
+ const apps = getRegisteredApps();
100
+ if (apps.length === 0) {
101
+ throw new Error(`${configPath} did not register any apps. Is it using withMonolith()?`);
102
+ }
103
+ return apps;
104
+ };
105
+ const main = async () => {
106
+ const args = parseArgs(process.argv.slice(2));
107
+ if (!args.command || args.command === 'help') {
108
+ process.stdout.write(USAGE);
109
+ return args.command ? 0 : 1;
110
+ }
111
+ if (args.command === 'list') {
112
+ for (const app of await loadApps(args.cwd)) {
113
+ process.stdout.write(`${app.prefix}\t${app.source}\t${app.root}\n`);
114
+ }
115
+ return 0;
116
+ }
117
+ if (args.command === 'link') {
118
+ const apps = await loadApps(args.cwd);
119
+ const mounted = await linkApps(args.cwd, apps, {
120
+ strategy: args.strategy,
121
+ sourceDir: path.resolve(args.cwd, 'src', 'app'),
122
+ sourcePagesDir: path.resolve(args.cwd, 'src', 'pages'),
123
+ watch: false,
124
+ });
125
+ for (const target of mounted) {
126
+ process.stdout.write(`${path.relative(args.cwd, target)}\n`);
127
+ }
128
+ return 0;
129
+ }
130
+ if (args.command === 'merge-package-json') {
131
+ const apps = await loadApps(args.cwd);
132
+ const file = path.join(args.cwd, 'package.json');
133
+ const { packageJson, changed, taken } = await mergeAppDependencies(file, apps, {
134
+ all: args.all,
135
+ });
136
+ if (!changed) {
137
+ process.stdout.write('package.json is already up to date.\n');
138
+ return 0;
139
+ }
140
+ if (args.check) {
141
+ process.stderr.write('package.json is out of date; run without --check.\n');
142
+ return 1;
143
+ }
144
+ await writePackageJson(file, packageJson);
145
+ for (const [name, packages] of taken) {
146
+ process.stdout.write(`${name}: ${packages.join(', ')}\n`);
147
+ }
148
+ process.stdout.write(`Updated ${path.relative(process.cwd(), file)}.\n`);
149
+ return 0;
150
+ }
151
+ process.stderr.write(`Unknown command: ${args.command}\n\n${USAGE}`);
152
+ return 1;
153
+ };
154
+ main().then((code) => {
155
+ process.exitCode = code;
156
+ }, (error) => {
157
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
158
+ process.exitCode = 1;
159
+ });
160
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { NextConfig } from 'next';
2
+ import type { ResolvedApp } from './types.ts';
3
+ export declare const assertCompatible: (base: NextConfig, apps: ResolvedApp[], monolithRoot?: string) => void;
4
+ //# sourceMappingURL=compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAiK7C,eAAO,MAAM,gBAAgB,GAC3B,MAAM,UAAU,EAChB,MAAM,WAAW,EAAE,EACnB,eAAe,MAAM,KACpB,IA6CF,CAAA"}
package/dist/compat.js ADDED
@@ -0,0 +1,174 @@
1
+ import { createRequire } from 'node:module';
2
+ import path from 'node:path';
3
+ import semver from 'semver';
4
+ import { inspectExtends, describeViolations } from '@fairgarden/distribution';
5
+ /**
6
+ * Options that change how every route is served. An app cannot have its own
7
+ * value for these, because the monolith serves all of them from one server.
8
+ */
9
+ const SHARED_OPTIONS = [
10
+ 'i18n',
11
+ 'trailingSlash',
12
+ 'skipTrailingSlashRedirect',
13
+ 'skipMiddlewareUrlNormalize',
14
+ 'output',
15
+ 'assetPrefix',
16
+ ];
17
+ /**
18
+ * Options an app can never set, because the monolith owns them and an app's
19
+ * value would silently apply to the whole deployment.
20
+ */
21
+ const OWNED_OPTIONS = ['basePath', 'distDir'];
22
+ const describe = (value) => JSON.stringify(value) ?? String(value);
23
+ /** Config this merges. Everything else an app sets is dropped. */
24
+ const MERGED_OPTIONS = ['rewrites', 'redirects', 'headers'];
25
+ /**
26
+ * Lists an app may set when the monolith already carries every entry: moving
27
+ * them to the monolith, as the error asks, is then visibly done, and the app
28
+ * still builds the same on its own.
29
+ */
30
+ const CARRIED_OPTIONS = ['serverExternalPackages'];
31
+ const missingFromBase = (option, app, base) => {
32
+ const carried = new Set(base[option] ?? []);
33
+ return (app.nextConfig[option] ?? []).filter((entry) => !carried.has(entry));
34
+ };
35
+ /**
36
+ * An app setting anything this cannot merge.
37
+ *
38
+ * Dropping it silently is the failure this is meant to avoid: the app builds
39
+ * alone with the option applied and inside a monolith without it, and nothing
40
+ * says so.
41
+ */
42
+ const droppedOptions = (apps, base) => {
43
+ const problems = [];
44
+ for (const app of apps) {
45
+ for (const option of Object.keys(app.nextConfig)) {
46
+ if (MERGED_OPTIONS.includes(option))
47
+ continue;
48
+ if (SHARED_OPTIONS.includes(option))
49
+ continue;
50
+ if (OWNED_OPTIONS.includes(option))
51
+ continue;
52
+ if (CARRIED_OPTIONS.includes(option)) {
53
+ const missing = missingFromBase(option, app, base);
54
+ if (missing.length === 0)
55
+ continue;
56
+ problems.push(`"${app.name}" sets ${option} to include ${describe(missing)}, which the ` +
57
+ `monolith does not. Add them to the monolith's own ${option}.`);
58
+ continue;
59
+ }
60
+ problems.push(`"${app.name}" sets ${option}, which a monolith cannot merge. Move it ` +
61
+ 'to the monolith, or pass `nextConfig: false` for this app to say it ' +
62
+ 'is deliberate.');
63
+ }
64
+ }
65
+ return problems;
66
+ };
67
+ /**
68
+ * The Next a package would actually load, rather than the range it asks for.
69
+ *
70
+ * Returns undefined when it cannot be resolved, which is the case while tooling
71
+ * loads a config outside an install. Nothing can be compared then.
72
+ */
73
+ const installedNext = (root) => {
74
+ try {
75
+ const require = createRequire(path.join(root, 'package.json'));
76
+ const version = require('next/package.json').version;
77
+ return typeof version === 'string' ? version : undefined;
78
+ }
79
+ catch {
80
+ return undefined;
81
+ }
82
+ };
83
+ /**
84
+ * The monolith compiles every app with its own Next, so an app can never need
85
+ * a newer one than the monolith has.
86
+ *
87
+ * Exact agreement is not required — an app pinned to 16.3.0 is fine inside a
88
+ * monolith on 16.3.5 — but the majors have to match, and the monolith has to be
89
+ * at least as new as the newest app.
90
+ */
91
+ const nextVersionProblems = (monolithRoot, apps) => {
92
+ const monolithVersion = installedNext(monolithRoot);
93
+ if (!monolithVersion)
94
+ return [];
95
+ const problems = [];
96
+ for (const app of apps) {
97
+ const appVersion = installedNext(app.root);
98
+ if (!appVersion)
99
+ continue;
100
+ if (semver.major(appVersion) !== semver.major(monolithVersion)) {
101
+ problems.push(`"${app.name}" is built for Next ${appVersion} but the monolith runs ` +
102
+ `${monolithVersion}. A mounted app is compiled by the monolith's Next, ` +
103
+ 'so their major versions have to match.');
104
+ continue;
105
+ }
106
+ if (semver.lt(monolithVersion, appVersion)) {
107
+ problems.push(`"${app.name}" is built for Next ${appVersion} but the monolith runs ` +
108
+ `${monolithVersion}. The monolith compiles every app, so it has to be ` +
109
+ 'at least as new as the newest one.');
110
+ }
111
+ }
112
+ return problems;
113
+ };
114
+ /**
115
+ * Reject app configs the monolith cannot honour, rather than dropping them
116
+ * quietly and leaving a deployment that half-works.
117
+ */
118
+ /**
119
+ * A distribution that extends another may not ship anything older than it.
120
+ *
121
+ * Checked here as well as by `fg-dist sync`, because shipping a regression is
122
+ * the kind of thing that should stop a build rather than wait to be noticed.
123
+ */
124
+ const extendsProblems = (monolithRoot) => {
125
+ // The manifest is the repository root's, which is above the monolith app.
126
+ for (const root of [monolithRoot, path.join(monolithRoot, '..', '..')]) {
127
+ try {
128
+ const report = inspectExtends(path.resolve(root));
129
+ if (report.violations.length > 0)
130
+ return [describeViolations(report)];
131
+ if (report.parent)
132
+ return [];
133
+ }
134
+ catch {
135
+ continue;
136
+ }
137
+ }
138
+ return [];
139
+ };
140
+ export const assertCompatible = (base, apps, monolithRoot) => {
141
+ const problems = [
142
+ ...(monolithRoot
143
+ ? [...nextVersionProblems(monolithRoot, apps), ...extendsProblems(monolithRoot)]
144
+ : []),
145
+ ...droppedOptions(apps, base),
146
+ ];
147
+ for (const app of apps) {
148
+ for (const option of OWNED_OPTIONS) {
149
+ if (app.nextConfig[option] !== undefined) {
150
+ problems.push(`"${app.name}" sets ${option}, which only the monolith may set. ` +
151
+ `Routes are mounted at ${app.prefix} instead.`);
152
+ }
153
+ }
154
+ for (const option of SHARED_OPTIONS) {
155
+ const appValue = app.nextConfig[option];
156
+ if (appValue === undefined)
157
+ continue;
158
+ const baseValue = base[option];
159
+ if (baseValue === undefined) {
160
+ problems.push(`"${app.name}" sets ${option} to ${describe(appValue)}, but the monolith ` +
161
+ 'does not. Set it on the monolith so every app shares it, or remove it.');
162
+ continue;
163
+ }
164
+ if (JSON.stringify(baseValue) !== JSON.stringify(appValue)) {
165
+ problems.push(`"${app.name}" sets ${option} to ${describe(appValue)}, but the monolith ` +
166
+ `uses ${describe(baseValue)}. These must match.`);
167
+ }
168
+ }
169
+ }
170
+ if (problems.length > 0) {
171
+ throw new Error(`Incompatible Next config in the monolith:\n - ${problems.join('\n - ')}`);
172
+ }
173
+ };
174
+ //# sourceMappingURL=compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compat.js","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Minimal shapes from ESLint's rule API.
3
+ *
4
+ * Declared here rather than depending on `@types/eslint`, which would pull a
5
+ * whole toolchain into a package apps install to run their own builds.
6
+ */
7
+ interface SourceNode {
8
+ value?: unknown;
9
+ range?: [number, number];
10
+ }
11
+ interface ImportNode {
12
+ source?: SourceNode | null;
13
+ arguments?: SourceNode[];
14
+ callee?: {
15
+ type?: string;
16
+ name?: string;
17
+ };
18
+ type?: string;
19
+ }
20
+ interface RuleContext {
21
+ filename?: string;
22
+ getFilename?: () => string;
23
+ options: unknown[];
24
+ report: (descriptor: {
25
+ node: unknown;
26
+ message: string;
27
+ fix?: (fixer: {
28
+ replaceText: (node: unknown, text: string) => unknown;
29
+ }) => unknown;
30
+ }) => void;
31
+ }
32
+ type Visitor = Record<string, ((node: ImportNode) => void) | undefined>;
33
+ interface Rule {
34
+ meta: Record<string, unknown>;
35
+ create: (context: RuleContext) => Visitor;
36
+ }
37
+ export declare const rules: {
38
+ 'no-escaping-relative-imports': Rule;
39
+ 'no-next-link': Rule;
40
+ };
41
+ /**
42
+ * ESLint plugin keeping an app's routes mountable.
43
+ *
44
+ * ```js
45
+ * // eslint.config.mjs
46
+ * import monolith from '@fairgarden/monolith/eslint'
47
+ *
48
+ * export default [...monolith.configs.recommended]
49
+ * ```
50
+ */
51
+ declare const plugin: {
52
+ meta: {
53
+ name: string;
54
+ };
55
+ rules: {
56
+ 'no-escaping-relative-imports': Rule;
57
+ 'no-next-link': Rule;
58
+ };
59
+ configs: Record<string, unknown[]>;
60
+ };
61
+ export default plugin;
62
+ //# sourceMappingURL=eslint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint.d.ts","sourceRoot":"","sources":["../src/eslint.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,UAAU,UAAU;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzB;AACD,UAAU,UAAU;IAClB,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IAC1B,SAAS,CAAC,EAAE,UAAU,EAAE,CAAA;IACxB,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACzC,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AACD,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,MAAM,CAAA;IAC1B,OAAO,EAAE,OAAO,EAAE,CAAA;IAClB,MAAM,EAAE,CAAC,UAAU,EAAE;QACnB,IAAI,EAAE,OAAO,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE;YAAE,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;SAAE,KAAK,OAAO,CAAA;KACpF,KAAK,IAAI,CAAA;CACX;AACD,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC,CAAA;AACvE,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,MAAM,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAA;CAC1C;AAwLD,eAAO,MAAM,KAAK;;;CAGjB,CAAA;AAED;;;;;;;;;GASG;AACH,QAAA,MAAM,MAAM;;;;;;;;aAGK,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;CACzC,CAAA;AAaD,eAAe,MAAM,CAAA"}