@foldkit/vite-plugin 0.24.0 → 0.25.0-canary.24f1c43eaaf7
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/README.md +70 -17
- package/dist/build.d.ts +48 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +66 -58
- package/dist/buildToken.d.ts +6 -14
- package/dist/buildToken.d.ts.map +1 -1
- package/dist/buildToken.js +153 -64
- package/dist/foldkitPackages.d.ts +12 -0
- package/dist/foldkitPackages.d.ts.map +1 -0
- package/dist/foldkitPackages.js +37 -0
- package/dist/index.d.ts +22 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +254 -89
- package/dist/relayRegistry.d.ts +17 -0
- package/dist/relayRegistry.d.ts.map +1 -0
- package/dist/relayRegistry.js +101 -0
- package/package.json +12 -9
package/dist/buildToken.js
CHANGED
|
@@ -1,38 +1,28 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { isFoldkitSingletonPackageSpecifier } from './foldkitPackages.js';
|
|
1
4
|
// The build id names the deployment a page came from. The server stamps it on
|
|
2
5
|
// the rendered root, the client carries it, and hydration refuses a page whose
|
|
3
6
|
// id is not its own before it adopts any DOM.
|
|
4
7
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// wins on the element, so a stale page's `<input name="email">` can otherwise be
|
|
11
|
-
// adopted for a new build's `<input name="ssn">`, carrying what a visitor typed
|
|
12
|
-
// into a field that submits under a different name.
|
|
8
|
+
// The aggregate plugin generates one opaque id when a Vite app build contains
|
|
9
|
+
// both the client and ssr environments. The id lives on the ViteBuilder's
|
|
10
|
+
// ResolvedConfig object, so concurrent builders cannot overwrite one another
|
|
11
|
+
// and a later builder in the same process gets a fresh value. Separately
|
|
12
|
+
// invoked builds have no shared session and must receive an explicit value.
|
|
13
13
|
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// in the project turns a value published in HTML into an oracle for the secrets
|
|
21
|
-
// among them. A value the deployment already has (a commit, a release tag, a
|
|
22
|
-
// container digest) has none of those problems.
|
|
23
|
-
//
|
|
24
|
-
// This plugin only compiles the id into application code. Foldkit itself is an
|
|
25
|
-
// ordinary dependency that Vite externalizes from a server build, where a
|
|
26
|
-
// compile-time define never reaches it, so the id is handed to `renderToString`
|
|
27
|
-
// and `Runtime.hydrate` explicitly rather than read from inside the framework.
|
|
28
|
-
//
|
|
29
|
-
// Development is compiled an id too. The dev SSR host renders through
|
|
30
|
-
// `renderToString` like any other, and a hydratable render refuses to run
|
|
31
|
-
// without one, so leaving development unnamed would fail every dev page
|
|
32
|
-
// request.
|
|
14
|
+
// Foldkit's own build-token module contains a placeholder call. This transform
|
|
15
|
+
// replaces that call in both artifacts, which lets Runtime.hydrate and
|
|
16
|
+
// renderToString consume the value without application forwarding. Installed
|
|
17
|
+
// Foldkit must therefore participate in the server build; the aggregate plugin
|
|
18
|
+
// configures that boundary and the post-build check refuses an artifact that
|
|
19
|
+
// still imports Foldkit externally.
|
|
33
20
|
const BUILD_ID_ENVIRONMENT_VARIABLE = 'FOLDKIT_BUILD_ID';
|
|
34
|
-
|
|
35
|
-
|
|
21
|
+
const FRAMEWORK_BUILD_ID_PLACEHOLDER = 'foldkitBuildIdPlaceholder()';
|
|
22
|
+
const buildIdentitySessions = new WeakMap();
|
|
23
|
+
const developmentBuildIds = new WeakMap();
|
|
24
|
+
/** The build id explicitly supplied through plugin configuration or the
|
|
25
|
+
* environment, or `undefined` when neither supplied a nonempty value.
|
|
36
26
|
*
|
|
37
27
|
* @internal Exported for tests.
|
|
38
28
|
*/
|
|
@@ -45,19 +35,7 @@ export const resolveBuildId = (configured) => {
|
|
|
45
35
|
? fromEnvironment
|
|
46
36
|
: undefined;
|
|
47
37
|
};
|
|
48
|
-
|
|
49
|
-
// one live source session supplies both the server and client transforms rather
|
|
50
|
-
// than producing independently deployable artifacts. A value that moved would
|
|
51
|
-
// only make the dev server disagree with the tab already open against it. A
|
|
52
|
-
// hydratable render still requires an id, so development has to be given one
|
|
53
|
-
// rather than left without.
|
|
54
|
-
//
|
|
55
|
-
// It is exactly wrong for a build, which is why a build with no id is refused
|
|
56
|
-
// rather than defaulted: two deployments sharing an id is the case the id
|
|
57
|
-
// exists to catch.
|
|
58
|
-
const DEVELOPMENT_BUILD_ID = 'development';
|
|
59
|
-
/** The value `import.meta.env.FOLDKIT_BUILD_ID` compiles to, or `undefined`
|
|
60
|
-
* when a build was given no id and must refuse to render a hydratable page.
|
|
38
|
+
/** The id a standalone plugin compiles for one Vite command.
|
|
61
39
|
*
|
|
62
40
|
* @internal Exported for tests.
|
|
63
41
|
*/
|
|
@@ -66,29 +44,140 @@ export const buildIdForCommand = (command, configured) => {
|
|
|
66
44
|
if (resolved !== undefined) {
|
|
67
45
|
return resolved;
|
|
68
46
|
}
|
|
69
|
-
return command === 'serve' ?
|
|
47
|
+
return command === 'serve' ? 'development' : undefined;
|
|
48
|
+
};
|
|
49
|
+
const hasCoordinatedArtifacts = (builder) => builder.environments['client'] !== undefined &&
|
|
50
|
+
builder.environments['ssr'] !== undefined;
|
|
51
|
+
const beginBuildIdentity = (builder, configuredBuildId, verifyFrameworkIdentity) => {
|
|
52
|
+
const isCoordinated = hasCoordinatedArtifacts(builder);
|
|
53
|
+
const buildId = configuredBuildId ?? (isCoordinated ? randomUUID() : undefined);
|
|
54
|
+
const session = {
|
|
55
|
+
buildId,
|
|
56
|
+
externalizedEnvironments: new Set(),
|
|
57
|
+
verifyFrameworkIdentity,
|
|
58
|
+
};
|
|
59
|
+
buildIdentitySessions.set(builder.config, session);
|
|
60
|
+
for (const environment of Object.values(builder.environments)) {
|
|
61
|
+
buildIdentitySessions.set(environment.config, session);
|
|
62
|
+
buildIdentitySessions.set(environment.getTopLevelConfig(), session);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const buildIdForConfig = (config, configuredBuildId) => {
|
|
66
|
+
if (config.command === 'build') {
|
|
67
|
+
return buildIdentitySessions.get(config)?.buildId ?? configuredBuildId;
|
|
68
|
+
}
|
|
69
|
+
const existing = developmentBuildIds.get(config);
|
|
70
|
+
if (existing !== undefined) {
|
|
71
|
+
return existing;
|
|
72
|
+
}
|
|
73
|
+
const fresh = configuredBuildId ?? randomUUID();
|
|
74
|
+
developmentBuildIds.set(config, fresh);
|
|
75
|
+
return fresh;
|
|
76
|
+
};
|
|
77
|
+
const replaceAll = (source, code, search, replacement) => {
|
|
78
|
+
let didReplace = false;
|
|
79
|
+
let fromIndex = 0;
|
|
80
|
+
while (fromIndex < code.length) {
|
|
81
|
+
const index = code.indexOf(search, fromIndex);
|
|
82
|
+
if (index === -1) {
|
|
83
|
+
return didReplace;
|
|
84
|
+
}
|
|
85
|
+
source.overwrite(index, index + search.length, replacement);
|
|
86
|
+
didReplace = true;
|
|
87
|
+
fromIndex = index + search.length;
|
|
88
|
+
}
|
|
89
|
+
return didReplace;
|
|
70
90
|
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
const isFoldkitBuildTokenModule = (id) => {
|
|
92
|
+
const fileName = (id.split('?', 1)[0] ?? '').replaceAll('\\', '/');
|
|
93
|
+
return (fileName.endsWith('/foldkit/src/buildToken.ts') ||
|
|
94
|
+
fileName.endsWith('/foldkit/dist/buildToken.js'));
|
|
95
|
+
};
|
|
96
|
+
const hasExternalFoldkitSingletonImport = (imports, dynamicImports) => [...imports, ...dynamicImports].some(isFoldkitSingletonPackageSpecifier);
|
|
97
|
+
const transformBuildIdentity = (code, id, config, configuredBuildId) => {
|
|
98
|
+
if (!isFoldkitBuildTokenModule(id) ||
|
|
99
|
+
!code.includes(FRAMEWORK_BUILD_ID_PLACEHOLDER)) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
const buildId = buildIdForConfig(config, configuredBuildId);
|
|
103
|
+
const replacement = buildId === undefined ? 'undefined' : JSON.stringify(buildId);
|
|
104
|
+
const transformed = new MagicString(code);
|
|
105
|
+
const transformedFramework = replaceAll(transformed, code, FRAMEWORK_BUILD_ID_PLACEHOLDER, replacement);
|
|
106
|
+
if (!transformedFramework) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
code: transformed.toString(),
|
|
111
|
+
map: transformed.generateMap({ hires: 'boundary', source: id }),
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
const verifyBuildIdentity = (builder) => {
|
|
115
|
+
const session = buildIdentitySessions.get(builder.config);
|
|
116
|
+
if (session === undefined || !session.verifyFrameworkIdentity) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const externalized = [...session.externalizedEnvironments];
|
|
120
|
+
if (externalized.length === 0) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
throw new Error('[foldkit] A Foldkit singleton package was externalized from the ' +
|
|
124
|
+
`${externalized.join(' and ')} ` +
|
|
125
|
+
`${externalized.length === 1 ? 'artifact' : 'artifacts'}, so it can ` +
|
|
126
|
+
'load a framework copy whose hydration build identity was not compiled. ' +
|
|
127
|
+
'Remove Foldkit packages from explicit SSR or Rolldown externalization ' +
|
|
128
|
+
'settings and let @foldkit/vite-plugin bundle them.');
|
|
129
|
+
};
|
|
130
|
+
/** Compiles one build identity into application entries and Foldkit itself.
|
|
75
131
|
*
|
|
76
|
-
*
|
|
77
|
-
* compiles nothing when it was given neither, so a hydratable render fails with
|
|
78
|
-
* `MissingBuildId` rather than serving a page hydration cannot place.
|
|
79
|
-
* Development serves a fixed id instead because one live source session
|
|
80
|
-
* supplies both transforms and has no deployment identity to derive.
|
|
132
|
+
* @internal
|
|
81
133
|
*/
|
|
82
|
-
export const foldkitBuildToken = (buildId) =>
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
:
|
|
89
|
-
|
|
90
|
-
|
|
134
|
+
export const foldkitBuildToken = (buildId, verifyFrameworkIdentity = true) => {
|
|
135
|
+
const configuredBuildId = resolveBuildId(buildId);
|
|
136
|
+
return [
|
|
137
|
+
{
|
|
138
|
+
name: 'foldkit:build-token',
|
|
139
|
+
enforce: 'pre',
|
|
140
|
+
sharedDuringBuild: true,
|
|
141
|
+
config: (_config, { command }) => {
|
|
142
|
+
const legacyBuildId = configuredBuildId ?? (command === 'serve' ? 'development' : undefined);
|
|
143
|
+
return legacyBuildId === undefined
|
|
144
|
+
? {}
|
|
145
|
+
: {
|
|
146
|
+
define: {
|
|
147
|
+
'import.meta.env.FOLDKIT_BUILD_ID': JSON.stringify(legacyBuildId),
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
buildApp: {
|
|
152
|
+
order: 'pre',
|
|
153
|
+
async handler(builder) {
|
|
154
|
+
beginBuildIdentity(builder, configuredBuildId, verifyFrameworkIdentity);
|
|
91
155
|
},
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
156
|
+
},
|
|
157
|
+
transform(code, id) {
|
|
158
|
+
const config = this.environment.getTopLevelConfig();
|
|
159
|
+
return transformBuildIdentity(code, id, config, configuredBuildId);
|
|
160
|
+
},
|
|
161
|
+
generateBundle(_options, bundle) {
|
|
162
|
+
const isExternalized = Object.values(bundle).some(output => output.type === 'chunk' &&
|
|
163
|
+
hasExternalFoldkitSingletonImport(output.imports, output.dynamicImports));
|
|
164
|
+
if (!isExternalized) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
buildIdentitySessions
|
|
168
|
+
.get(this.environment.getTopLevelConfig())
|
|
169
|
+
?.externalizedEnvironments.add(this.environment.name);
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: 'foldkit:verify-build-token',
|
|
174
|
+
sharedDuringBuild: true,
|
|
175
|
+
buildApp: {
|
|
176
|
+
order: 'post',
|
|
177
|
+
async handler(builder) {
|
|
178
|
+
verifyBuildIdentity(builder);
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
];
|
|
183
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Tests whether an import refers to a package that must share Foldkit's
|
|
2
|
+
* runtime instance.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare const isFoldkitSingletonPackageSpecifier: (specifier: string) => boolean;
|
|
7
|
+
/** Resolves the installed packages that must share Foldkit's runtime instance.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare const resolveInstalledFoldkitPackages: (root: string) => Array<string>;
|
|
12
|
+
//# sourceMappingURL=foldkitPackages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foldkitPackages.d.ts","sourceRoot":"","sources":["../src/foldkitPackages.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,cAClC,MAAM,KAChB,OAKA,CAAA;AAEH;;;GAGG;AACH,eAAO,MAAM,+BAA+B,SACpC,MAAM,KACX,KAAK,CAAC,MAAM,CAmBd,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Array, Predicate } from 'effect';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
const FOLDKIT_SINGLETON_PACKAGES = [
|
|
5
|
+
'foldkit',
|
|
6
|
+
'@foldkit/ui',
|
|
7
|
+
'@foldkit/devtools',
|
|
8
|
+
];
|
|
9
|
+
/** Tests whether an import refers to a package that must share Foldkit's
|
|
10
|
+
* runtime instance.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export const isFoldkitSingletonPackageSpecifier = (specifier) => Array.some(FOLDKIT_SINGLETON_PACKAGES, packageName => specifier === packageName || specifier.startsWith(`${packageName}/`));
|
|
15
|
+
/** Resolves the installed packages that must share Foldkit's runtime instance.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export const resolveInstalledFoldkitPackages = (root) => {
|
|
20
|
+
// NOTE: Vite can supply a relative root before it resolves the config, while
|
|
21
|
+
// createRequire requires an absolute path.
|
|
22
|
+
const requireFromRoot = createRequire(resolve(root, 'noop.js'));
|
|
23
|
+
return Array.filter(FOLDKIT_SINGLETON_PACKAGES, packageName => {
|
|
24
|
+
try {
|
|
25
|
+
requireFromRoot.resolve(packageName);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
// NOTE: optional ESM-only packages can throw
|
|
30
|
+
// ERR_PACKAGE_PATH_NOT_EXPORTED even when installed. Only
|
|
31
|
+
// MODULE_NOT_FOUND proves this consumer does not have the package.
|
|
32
|
+
return !(error instanceof Error &&
|
|
33
|
+
Predicate.hasProperty(error, 'code') &&
|
|
34
|
+
error.code === 'MODULE_NOT_FOUND');
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,18 +2,21 @@ import type { Plugin } from 'vite';
|
|
|
2
2
|
import { type FoldkitBuildOptions } from './build.js';
|
|
3
3
|
import { type FoldkitSsrOptions } from './ssr.js';
|
|
4
4
|
export { type BrandDistResult, brandDistDirectory } from './brandDist.js';
|
|
5
|
-
export { FOLDKIT_FETCH_MODULE_ID, FoldkitBuildManifest, type FoldkitBuildOptions, type FoldkitPrerenderOptions, foldkitBuild, } from './build.js';
|
|
5
|
+
export { FOLDKIT_FETCH_MODULE_ID, FoldkitBuildManifest, FoldkitBuildMetadata, type FoldkitBuildApi, type FoldkitBuildOptions, type FoldkitPrerenderOptions, foldkitBuild, } from './build.js';
|
|
6
6
|
export { type FoldkitSsrOptions, foldkitSsr } from './ssr.js';
|
|
7
7
|
export { type ViewIdentityTransformResult, foldkitViewIdentity, transformViewIdentity, } from './viewIdentity.js';
|
|
8
8
|
/** Options for the `foldkit` Vite plugin. */
|
|
9
9
|
export type FoldkitPluginOptions = Readonly<{
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* By default, the dev server hosts the DevTools MCP relay and publishes its
|
|
12
|
+
* address for the MCP server to find. Middleware and HTTPS servers use a
|
|
13
|
+
* separate loopback listener. Published addresses carry an access token.
|
|
14
|
+
*
|
|
15
|
+
* A number starts an unauthenticated listener on that port on every
|
|
16
|
+
* interface; set `FOLDKIT_DEVTOOLS_MCP_PORT` in the MCP server to match.
|
|
17
|
+
* `false` disables the relay. Vitest never starts it.
|
|
15
18
|
*/
|
|
16
|
-
devToolsMcpPort?: number;
|
|
19
|
+
devToolsMcpPort?: number | false;
|
|
17
20
|
/**
|
|
18
21
|
* Serve server-rendered pages from the Vite dev server, and, with
|
|
19
22
|
* `ssr.build`, emit a Web `fetch` handler as the server bundle. When
|
|
@@ -35,25 +38,21 @@ export type FoldkitPluginOptions = Readonly<{
|
|
|
35
38
|
build?: boolean | FoldkitBuildOptions;
|
|
36
39
|
}>;
|
|
37
40
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* body marked `inert`.
|
|
41
|
+
* An explicit identity for the deployment this build belongs to. Foldkit
|
|
42
|
+
* normally generates an opaque identity when one Vite app build coordinates
|
|
43
|
+
* the client and server artifacts, then compiles it into the framework in
|
|
44
|
+
* both. Hydration compares that value against the id the server stamped and
|
|
45
|
+
* refuses a page from another deployment before adopting its DOM.
|
|
44
46
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
47
|
+
* Set this when the client and server are built separately, or when the id
|
|
48
|
+
* should name a deployment in another system. The `FOLDKIT_BUILD_ID`
|
|
49
|
+
* environment variable supplies the same override when this option is
|
|
50
|
+
* absent. Give every artifact the same value. It is published in the page,
|
|
51
|
+
* so it must not be a secret.
|
|
49
52
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* timestamp — gives the browser bundle and the server bundle different ids
|
|
54
|
-
* within one build, and every page of that deployment is then refused at
|
|
55
|
-
* hydration. Read it from the environment, or store a generated fallback
|
|
56
|
-
* back into the environment so later reads resolve the same id.
|
|
53
|
+
* Reusing an override across deployments makes stale pages appear current.
|
|
54
|
+
* Use a value that changes whenever the deployment's rendering inputs can
|
|
55
|
+
* change.
|
|
57
56
|
*/
|
|
58
57
|
buildId?: string;
|
|
59
58
|
}>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAEV,MAAM,EAIP,MAAM,MAAM,CAAA;AAOb,OAAO,EAAE,KAAK,mBAAmB,EAAgB,MAAM,YAAY,CAAA;AAKnE,OAAO,EAAE,KAAK,iBAAiB,EAAc,MAAM,UAAU,CAAA;AAG7D,OAAO,EAAE,KAAK,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,YAAY,GACb,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC7D,OAAO,EACL,KAAK,2BAA2B,EAChC,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAE1B,6CAA6C;AAC7C,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAChC;;;;;;;OAOG;IACH,GAAG,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,gBAAgB,CAAC,GACzD,QAAQ,CAAC;QACP;;;;;;;;WAQG;QACH,KAAK,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAA;KACtC,CAAC,CAAA;IACJ;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AAs6BF,eAAO,MAAM,OAAO,aAAa,oBAAoB,KAAQ,KAAK,CAAC,MAAM,CAuHxE,CAAA"}
|