@forklaunch/core 0.15.2 → 0.15.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.
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Gets cascading environment file paths: collects all .env.local files from project directory up to root
3
+ * Root detection uses: .forklaunch/manifest.toml
4
+ */
5
+ declare function getCascadingEnvPaths(projectEnvPath: string | undefined, projectRoot?: string): {
6
+ rootEnvExists: boolean;
7
+ projectEnvExists: boolean;
8
+ rootEnvPath?: string;
9
+ projectEnvFilePath?: string;
10
+ loadOrder: string[];
11
+ };
12
+ /**
13
+ * Loads environment variables with cascading precedence: all .env.local files from root to project, then project env file
14
+ */
15
+ declare function loadCascadingEnv(projectEnvPath: string | undefined, projectRoot?: string): {
16
+ rootEnvLoaded: boolean;
17
+ projectEnvLoaded: boolean;
18
+ rootEnvPath?: string;
19
+ projectEnvFilePath?: string;
20
+ envFilesLoaded: string[];
21
+ totalEnvFilesLoaded: number;
22
+ };
23
+
24
+ export { getCascadingEnvPaths, loadCascadingEnv };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Gets cascading environment file paths: collects all .env.local files from project directory up to root
3
+ * Root detection uses: .forklaunch/manifest.toml
4
+ */
5
+ declare function getCascadingEnvPaths(projectEnvPath: string | undefined, projectRoot?: string): {
6
+ rootEnvExists: boolean;
7
+ projectEnvExists: boolean;
8
+ rootEnvPath?: string;
9
+ projectEnvFilePath?: string;
10
+ loadOrder: string[];
11
+ };
12
+ /**
13
+ * Loads environment variables with cascading precedence: all .env.local files from root to project, then project env file
14
+ */
15
+ declare function loadCascadingEnv(projectEnvPath: string | undefined, projectRoot?: string): {
16
+ rootEnvLoaded: boolean;
17
+ projectEnvLoaded: boolean;
18
+ rootEnvPath?: string;
19
+ projectEnvFilePath?: string;
20
+ envFilesLoaded: string[];
21
+ totalEnvFilesLoaded: number;
22
+ };
23
+
24
+ export { getCascadingEnvPaths, loadCascadingEnv };
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/environment/index.ts
31
+ var environment_exports = {};
32
+ __export(environment_exports, {
33
+ getCascadingEnvPaths: () => getCascadingEnvPaths,
34
+ loadCascadingEnv: () => loadCascadingEnv
35
+ });
36
+ module.exports = __toCommonJS(environment_exports);
37
+
38
+ // src/environment/loadCascadingEnv.ts
39
+ var import_dotenv = __toESM(require("dotenv"));
40
+ var import_fs = require("fs");
41
+ var import_path = require("path");
42
+ function getCascadingEnvPaths(projectEnvPath, projectRoot = process.cwd()) {
43
+ const result = {
44
+ rootEnvExists: false,
45
+ projectEnvExists: false,
46
+ rootEnvPath: void 0,
47
+ projectEnvFilePath: void 0,
48
+ loadOrder: []
49
+ };
50
+ const applicationRoot = findApplicationRoot(projectRoot);
51
+ const envLocalFiles = collectEnvLocalFiles(projectRoot, applicationRoot);
52
+ result.loadOrder.push(...envLocalFiles);
53
+ const rootEnvPath = (0, import_path.resolve)(applicationRoot, ".env.local");
54
+ if (envLocalFiles.includes(rootEnvPath)) {
55
+ result.rootEnvExists = true;
56
+ result.rootEnvPath = rootEnvPath;
57
+ }
58
+ if (projectEnvPath) {
59
+ const fullProjectEnvPath = (0, import_path.resolve)(projectRoot, projectEnvPath);
60
+ if ((0, import_fs.existsSync)(fullProjectEnvPath)) {
61
+ result.projectEnvExists = true;
62
+ result.projectEnvFilePath = fullProjectEnvPath;
63
+ if (!result.loadOrder.includes(fullProjectEnvPath)) {
64
+ result.loadOrder.push(fullProjectEnvPath);
65
+ }
66
+ }
67
+ }
68
+ return result;
69
+ }
70
+ function loadCascadingEnv(projectEnvPath, projectRoot = process.cwd()) {
71
+ const paths = getCascadingEnvPaths(projectEnvPath, projectRoot);
72
+ const result = {
73
+ rootEnvLoaded: false,
74
+ projectEnvLoaded: false,
75
+ rootEnvPath: paths.rootEnvPath,
76
+ projectEnvFilePath: paths.projectEnvFilePath,
77
+ envFilesLoaded: [],
78
+ totalEnvFilesLoaded: 0
79
+ };
80
+ const seen = /* @__PURE__ */ new Set();
81
+ for (const envPath of paths.loadOrder) {
82
+ if (seen.has(envPath)) {
83
+ continue;
84
+ }
85
+ seen.add(envPath);
86
+ const envResult = import_dotenv.default.config({
87
+ path: envPath,
88
+ override: true
89
+ });
90
+ if (!envResult?.error) {
91
+ result.envFilesLoaded.push(envPath);
92
+ result.totalEnvFilesLoaded++;
93
+ if (envPath === paths.rootEnvPath) {
94
+ result.rootEnvLoaded = true;
95
+ }
96
+ if (envPath === paths.projectEnvFilePath) {
97
+ result.projectEnvLoaded = true;
98
+ }
99
+ }
100
+ }
101
+ return result;
102
+ }
103
+ function collectEnvLocalFiles(projectRoot, applicationRoot) {
104
+ const envLocalPaths = [];
105
+ let currentPath = (0, import_path.resolve)(projectRoot);
106
+ const normalizedAppRoot = (0, import_path.resolve)(applicationRoot);
107
+ while (currentPath.length >= normalizedAppRoot.length) {
108
+ const envLocalPath = (0, import_path.resolve)(currentPath, ".env.local");
109
+ if ((0, import_fs.existsSync)(envLocalPath)) {
110
+ envLocalPaths.push(envLocalPath);
111
+ }
112
+ if (currentPath === normalizedAppRoot) {
113
+ break;
114
+ }
115
+ const parentPath = (0, import_path.dirname)(currentPath);
116
+ if (parentPath === currentPath) {
117
+ break;
118
+ }
119
+ currentPath = parentPath;
120
+ }
121
+ return envLocalPaths.reverse();
122
+ }
123
+ function findApplicationRoot(startPath) {
124
+ let currentPath = (0, import_path.resolve)(startPath);
125
+ const originalStart = currentPath;
126
+ const maxDepth = 10;
127
+ let depth = 0;
128
+ while (depth < maxDepth) {
129
+ const forklaunchManifest = (0, import_path.resolve)(
130
+ currentPath,
131
+ ".forklaunch",
132
+ "manifest.toml"
133
+ );
134
+ if ((0, import_fs.existsSync)(forklaunchManifest)) {
135
+ return currentPath;
136
+ }
137
+ const parentPath = (0, import_path.dirname)(currentPath);
138
+ if (parentPath === currentPath) {
139
+ break;
140
+ }
141
+ currentPath = parentPath;
142
+ depth++;
143
+ }
144
+ return originalStart;
145
+ }
146
+ // Annotate the CommonJS export names for ESM import in node:
147
+ 0 && (module.exports = {
148
+ getCascadingEnvPaths,
149
+ loadCascadingEnv
150
+ });
151
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/environment/index.ts","../../src/environment/loadCascadingEnv.ts"],"sourcesContent":["export * from './loadCascadingEnv';\n","import dotenv from 'dotenv';\nimport { existsSync } from 'fs';\nimport { dirname, resolve } from 'path';\n\n/**\n * Gets cascading environment file paths: collects all .env.local files from project directory up to root\n * Root detection uses: .forklaunch/manifest.toml\n */\nexport function getCascadingEnvPaths(\n projectEnvPath: string | undefined,\n projectRoot: string = process.cwd()\n): {\n rootEnvExists: boolean;\n projectEnvExists: boolean;\n rootEnvPath?: string;\n projectEnvFilePath?: string;\n loadOrder: string[];\n} {\n const result = {\n rootEnvExists: false,\n projectEnvExists: false,\n rootEnvPath: undefined as string | undefined,\n projectEnvFilePath: undefined as string | undefined,\n loadOrder: [] as string[]\n };\n\n const applicationRoot = findApplicationRoot(projectRoot);\n\n const envLocalFiles = collectEnvLocalFiles(projectRoot, applicationRoot);\n result.loadOrder.push(...envLocalFiles);\n\n const rootEnvPath = resolve(applicationRoot, '.env.local');\n if (envLocalFiles.includes(rootEnvPath)) {\n result.rootEnvExists = true;\n result.rootEnvPath = rootEnvPath;\n }\n\n if (projectEnvPath) {\n const fullProjectEnvPath = resolve(projectRoot, projectEnvPath);\n if (existsSync(fullProjectEnvPath)) {\n result.projectEnvExists = true;\n result.projectEnvFilePath = fullProjectEnvPath;\n if (!result.loadOrder.includes(fullProjectEnvPath)) {\n result.loadOrder.push(fullProjectEnvPath);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Loads environment variables with cascading precedence: all .env.local files from root to project, then project env file\n */\nexport function loadCascadingEnv(\n projectEnvPath: string | undefined,\n projectRoot: string = process.cwd()\n): {\n rootEnvLoaded: boolean;\n projectEnvLoaded: boolean;\n rootEnvPath?: string;\n projectEnvFilePath?: string;\n envFilesLoaded: string[];\n totalEnvFilesLoaded: number;\n} {\n const paths = getCascadingEnvPaths(projectEnvPath, projectRoot);\n const result = {\n rootEnvLoaded: false,\n projectEnvLoaded: false,\n rootEnvPath: paths.rootEnvPath,\n projectEnvFilePath: paths.projectEnvFilePath,\n envFilesLoaded: [] as string[],\n totalEnvFilesLoaded: 0\n };\n\n const seen = new Set<string>();\n for (const envPath of paths.loadOrder) {\n if (seen.has(envPath)) {\n continue;\n }\n seen.add(envPath);\n\n const envResult = dotenv.config({\n path: envPath,\n override: true\n });\n\n if (!envResult?.error) {\n result.envFilesLoaded.push(envPath);\n result.totalEnvFilesLoaded++;\n\n if (envPath === paths.rootEnvPath) {\n result.rootEnvLoaded = true;\n }\n if (envPath === paths.projectEnvFilePath) {\n result.projectEnvLoaded = true;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Collects all .env.local files from project directory up to application root\n * Returns paths in order from root to project (for proper precedence)\n */\nfunction collectEnvLocalFiles(\n projectRoot: string,\n applicationRoot: string\n): string[] {\n const envLocalPaths: string[] = [];\n\n let currentPath = resolve(projectRoot);\n const normalizedAppRoot = resolve(applicationRoot);\n\n while (currentPath.length >= normalizedAppRoot.length) {\n const envLocalPath = resolve(currentPath, '.env.local');\n if (existsSync(envLocalPath)) {\n envLocalPaths.push(envLocalPath);\n }\n\n if (currentPath === normalizedAppRoot) {\n break;\n }\n\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n break;\n }\n\n currentPath = parentPath;\n }\n\n return envLocalPaths.reverse();\n}\n\n/**\n * Finds application root by looking for .forklaunch/manifest.toml\n */\nfunction findApplicationRoot(startPath: string): string {\n let currentPath = resolve(startPath);\n const originalStart = currentPath;\n const maxDepth = 10;\n let depth = 0;\n\n while (depth < maxDepth) {\n const forklaunchManifest = resolve(\n currentPath,\n '.forklaunch',\n 'manifest.toml'\n );\n if (existsSync(forklaunchManifest)) {\n return currentPath;\n }\n\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n break;\n }\n\n currentPath = parentPath;\n depth++;\n }\n\n return originalStart;\n}\n"],"mappings":"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","names":["dotenv"]}
@@ -0,0 +1,113 @@
1
+ // src/environment/loadCascadingEnv.ts
2
+ import dotenv from "dotenv";
3
+ import { existsSync } from "fs";
4
+ import { dirname, resolve } from "path";
5
+ function getCascadingEnvPaths(projectEnvPath, projectRoot = process.cwd()) {
6
+ const result = {
7
+ rootEnvExists: false,
8
+ projectEnvExists: false,
9
+ rootEnvPath: void 0,
10
+ projectEnvFilePath: void 0,
11
+ loadOrder: []
12
+ };
13
+ const applicationRoot = findApplicationRoot(projectRoot);
14
+ const envLocalFiles = collectEnvLocalFiles(projectRoot, applicationRoot);
15
+ result.loadOrder.push(...envLocalFiles);
16
+ const rootEnvPath = resolve(applicationRoot, ".env.local");
17
+ if (envLocalFiles.includes(rootEnvPath)) {
18
+ result.rootEnvExists = true;
19
+ result.rootEnvPath = rootEnvPath;
20
+ }
21
+ if (projectEnvPath) {
22
+ const fullProjectEnvPath = resolve(projectRoot, projectEnvPath);
23
+ if (existsSync(fullProjectEnvPath)) {
24
+ result.projectEnvExists = true;
25
+ result.projectEnvFilePath = fullProjectEnvPath;
26
+ if (!result.loadOrder.includes(fullProjectEnvPath)) {
27
+ result.loadOrder.push(fullProjectEnvPath);
28
+ }
29
+ }
30
+ }
31
+ return result;
32
+ }
33
+ function loadCascadingEnv(projectEnvPath, projectRoot = process.cwd()) {
34
+ const paths = getCascadingEnvPaths(projectEnvPath, projectRoot);
35
+ const result = {
36
+ rootEnvLoaded: false,
37
+ projectEnvLoaded: false,
38
+ rootEnvPath: paths.rootEnvPath,
39
+ projectEnvFilePath: paths.projectEnvFilePath,
40
+ envFilesLoaded: [],
41
+ totalEnvFilesLoaded: 0
42
+ };
43
+ const seen = /* @__PURE__ */ new Set();
44
+ for (const envPath of paths.loadOrder) {
45
+ if (seen.has(envPath)) {
46
+ continue;
47
+ }
48
+ seen.add(envPath);
49
+ const envResult = dotenv.config({
50
+ path: envPath,
51
+ override: true
52
+ });
53
+ if (!envResult?.error) {
54
+ result.envFilesLoaded.push(envPath);
55
+ result.totalEnvFilesLoaded++;
56
+ if (envPath === paths.rootEnvPath) {
57
+ result.rootEnvLoaded = true;
58
+ }
59
+ if (envPath === paths.projectEnvFilePath) {
60
+ result.projectEnvLoaded = true;
61
+ }
62
+ }
63
+ }
64
+ return result;
65
+ }
66
+ function collectEnvLocalFiles(projectRoot, applicationRoot) {
67
+ const envLocalPaths = [];
68
+ let currentPath = resolve(projectRoot);
69
+ const normalizedAppRoot = resolve(applicationRoot);
70
+ while (currentPath.length >= normalizedAppRoot.length) {
71
+ const envLocalPath = resolve(currentPath, ".env.local");
72
+ if (existsSync(envLocalPath)) {
73
+ envLocalPaths.push(envLocalPath);
74
+ }
75
+ if (currentPath === normalizedAppRoot) {
76
+ break;
77
+ }
78
+ const parentPath = dirname(currentPath);
79
+ if (parentPath === currentPath) {
80
+ break;
81
+ }
82
+ currentPath = parentPath;
83
+ }
84
+ return envLocalPaths.reverse();
85
+ }
86
+ function findApplicationRoot(startPath) {
87
+ let currentPath = resolve(startPath);
88
+ const originalStart = currentPath;
89
+ const maxDepth = 10;
90
+ let depth = 0;
91
+ while (depth < maxDepth) {
92
+ const forklaunchManifest = resolve(
93
+ currentPath,
94
+ ".forklaunch",
95
+ "manifest.toml"
96
+ );
97
+ if (existsSync(forklaunchManifest)) {
98
+ return currentPath;
99
+ }
100
+ const parentPath = dirname(currentPath);
101
+ if (parentPath === currentPath) {
102
+ break;
103
+ }
104
+ currentPath = parentPath;
105
+ depth++;
106
+ }
107
+ return originalStart;
108
+ }
109
+ export {
110
+ getCascadingEnvPaths,
111
+ loadCascadingEnv
112
+ };
113
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/environment/loadCascadingEnv.ts"],"sourcesContent":["import dotenv from 'dotenv';\nimport { existsSync } from 'fs';\nimport { dirname, resolve } from 'path';\n\n/**\n * Gets cascading environment file paths: collects all .env.local files from project directory up to root\n * Root detection uses: .forklaunch/manifest.toml\n */\nexport function getCascadingEnvPaths(\n projectEnvPath: string | undefined,\n projectRoot: string = process.cwd()\n): {\n rootEnvExists: boolean;\n projectEnvExists: boolean;\n rootEnvPath?: string;\n projectEnvFilePath?: string;\n loadOrder: string[];\n} {\n const result = {\n rootEnvExists: false,\n projectEnvExists: false,\n rootEnvPath: undefined as string | undefined,\n projectEnvFilePath: undefined as string | undefined,\n loadOrder: [] as string[]\n };\n\n const applicationRoot = findApplicationRoot(projectRoot);\n\n const envLocalFiles = collectEnvLocalFiles(projectRoot, applicationRoot);\n result.loadOrder.push(...envLocalFiles);\n\n const rootEnvPath = resolve(applicationRoot, '.env.local');\n if (envLocalFiles.includes(rootEnvPath)) {\n result.rootEnvExists = true;\n result.rootEnvPath = rootEnvPath;\n }\n\n if (projectEnvPath) {\n const fullProjectEnvPath = resolve(projectRoot, projectEnvPath);\n if (existsSync(fullProjectEnvPath)) {\n result.projectEnvExists = true;\n result.projectEnvFilePath = fullProjectEnvPath;\n if (!result.loadOrder.includes(fullProjectEnvPath)) {\n result.loadOrder.push(fullProjectEnvPath);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Loads environment variables with cascading precedence: all .env.local files from root to project, then project env file\n */\nexport function loadCascadingEnv(\n projectEnvPath: string | undefined,\n projectRoot: string = process.cwd()\n): {\n rootEnvLoaded: boolean;\n projectEnvLoaded: boolean;\n rootEnvPath?: string;\n projectEnvFilePath?: string;\n envFilesLoaded: string[];\n totalEnvFilesLoaded: number;\n} {\n const paths = getCascadingEnvPaths(projectEnvPath, projectRoot);\n const result = {\n rootEnvLoaded: false,\n projectEnvLoaded: false,\n rootEnvPath: paths.rootEnvPath,\n projectEnvFilePath: paths.projectEnvFilePath,\n envFilesLoaded: [] as string[],\n totalEnvFilesLoaded: 0\n };\n\n const seen = new Set<string>();\n for (const envPath of paths.loadOrder) {\n if (seen.has(envPath)) {\n continue;\n }\n seen.add(envPath);\n\n const envResult = dotenv.config({\n path: envPath,\n override: true\n });\n\n if (!envResult?.error) {\n result.envFilesLoaded.push(envPath);\n result.totalEnvFilesLoaded++;\n\n if (envPath === paths.rootEnvPath) {\n result.rootEnvLoaded = true;\n }\n if (envPath === paths.projectEnvFilePath) {\n result.projectEnvLoaded = true;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Collects all .env.local files from project directory up to application root\n * Returns paths in order from root to project (for proper precedence)\n */\nfunction collectEnvLocalFiles(\n projectRoot: string,\n applicationRoot: string\n): string[] {\n const envLocalPaths: string[] = [];\n\n let currentPath = resolve(projectRoot);\n const normalizedAppRoot = resolve(applicationRoot);\n\n while (currentPath.length >= normalizedAppRoot.length) {\n const envLocalPath = resolve(currentPath, '.env.local');\n if (existsSync(envLocalPath)) {\n envLocalPaths.push(envLocalPath);\n }\n\n if (currentPath === normalizedAppRoot) {\n break;\n }\n\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n break;\n }\n\n currentPath = parentPath;\n }\n\n return envLocalPaths.reverse();\n}\n\n/**\n * Finds application root by looking for .forklaunch/manifest.toml\n */\nfunction findApplicationRoot(startPath: string): string {\n let currentPath = resolve(startPath);\n const originalStart = currentPath;\n const maxDepth = 10;\n let depth = 0;\n\n while (depth < maxDepth) {\n const forklaunchManifest = resolve(\n currentPath,\n '.forklaunch',\n 'manifest.toml'\n );\n if (existsSync(forklaunchManifest)) {\n return currentPath;\n }\n\n const parentPath = dirname(currentPath);\n if (parentPath === currentPath) {\n break;\n }\n\n currentPath = parentPath;\n depth++;\n }\n\n return originalStart;\n}\n"],"mappings":";AAAA,OAAO,YAAY;AACnB,SAAS,kBAAkB;AAC3B,SAAS,SAAS,eAAe;AAM1B,SAAS,qBACd,gBACA,cAAsB,QAAQ,IAAI,GAOlC;AACA,QAAM,SAAS;AAAA,IACb,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,WAAW,CAAC;AAAA,EACd;AAEA,QAAM,kBAAkB,oBAAoB,WAAW;AAEvD,QAAM,gBAAgB,qBAAqB,aAAa,eAAe;AACvE,SAAO,UAAU,KAAK,GAAG,aAAa;AAEtC,QAAM,cAAc,QAAQ,iBAAiB,YAAY;AACzD,MAAI,cAAc,SAAS,WAAW,GAAG;AACvC,WAAO,gBAAgB;AACvB,WAAO,cAAc;AAAA,EACvB;AAEA,MAAI,gBAAgB;AAClB,UAAM,qBAAqB,QAAQ,aAAa,cAAc;AAC9D,QAAI,WAAW,kBAAkB,GAAG;AAClC,aAAO,mBAAmB;AAC1B,aAAO,qBAAqB;AAC5B,UAAI,CAAC,OAAO,UAAU,SAAS,kBAAkB,GAAG;AAClD,eAAO,UAAU,KAAK,kBAAkB;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,iBACd,gBACA,cAAsB,QAAQ,IAAI,GAQlC;AACA,QAAM,QAAQ,qBAAqB,gBAAgB,WAAW;AAC9D,QAAM,SAAS;AAAA,IACb,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,aAAa,MAAM;AAAA,IACnB,oBAAoB,MAAM;AAAA,IAC1B,gBAAgB,CAAC;AAAA,IACjB,qBAAqB;AAAA,EACvB;AAEA,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,WAAW,MAAM,WAAW;AACrC,QAAI,KAAK,IAAI,OAAO,GAAG;AACrB;AAAA,IACF;AACA,SAAK,IAAI,OAAO;AAEhB,UAAM,YAAY,OAAO,OAAO;AAAA,MAC9B,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AAED,QAAI,CAAC,WAAW,OAAO;AACrB,aAAO,eAAe,KAAK,OAAO;AAClC,aAAO;AAEP,UAAI,YAAY,MAAM,aAAa;AACjC,eAAO,gBAAgB;AAAA,MACzB;AACA,UAAI,YAAY,MAAM,oBAAoB;AACxC,eAAO,mBAAmB;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,qBACP,aACA,iBACU;AACV,QAAM,gBAA0B,CAAC;AAEjC,MAAI,cAAc,QAAQ,WAAW;AACrC,QAAM,oBAAoB,QAAQ,eAAe;AAEjD,SAAO,YAAY,UAAU,kBAAkB,QAAQ;AACrD,UAAM,eAAe,QAAQ,aAAa,YAAY;AACtD,QAAI,WAAW,YAAY,GAAG;AAC5B,oBAAc,KAAK,YAAY;AAAA,IACjC;AAEA,QAAI,gBAAgB,mBAAmB;AACrC;AAAA,IACF;AAEA,UAAM,aAAa,QAAQ,WAAW;AACtC,QAAI,eAAe,aAAa;AAC9B;AAAA,IACF;AAEA,kBAAc;AAAA,EAChB;AAEA,SAAO,cAAc,QAAQ;AAC/B;AAKA,SAAS,oBAAoB,WAA2B;AACtD,MAAI,cAAc,QAAQ,SAAS;AACnC,QAAM,gBAAgB;AACtB,QAAM,WAAW;AACjB,MAAI,QAAQ;AAEZ,SAAO,QAAQ,UAAU;AACvB,UAAM,qBAAqB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,WAAW,kBAAkB,GAAG;AAClC,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,QAAQ,WAAW;AACtC,QAAI,eAAe,aAAa;AAC9B;AAAA,IACF;AAEA,kBAAc;AACd;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}