@contentrain/mcp 0.3.1 → 1.0.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.
- package/LICENSE +1 -1
- package/README.md +147 -238
- package/dist/apply-manager-CaTuu7Lj.mjs +751 -0
- package/dist/apply-manager-CaTuu7Lj.mjs.map +1 -0
- package/dist/astro-parser-RofKmKQi.mjs +166 -0
- package/dist/astro-parser-RofKmKQi.mjs.map +1 -0
- package/dist/branch-lifecycle-DB6sgeJi.mjs +97 -0
- package/dist/branch-lifecycle-DB6sgeJi.mjs.map +1 -0
- package/dist/chunk-BEJ448es.mjs +35 -0
- package/dist/compiler-rIC4ETHv.mjs +44509 -0
- package/dist/compiler-rIC4ETHv.mjs.map +1 -0
- package/dist/compiler-sfc.cjs-BbD04rn_.mjs +50279 -0
- package/dist/compiler-sfc.cjs-BbD04rn_.mjs.map +1 -0
- package/dist/config-CPlhDwsv.mjs +27 -0
- package/dist/config-CPlhDwsv.mjs.map +1 -0
- package/dist/context-yh3cuw5N.mjs +46 -0
- package/dist/context-yh3cuw5N.mjs.map +1 -0
- package/dist/core/apply-manager.d.mts +144 -0
- package/dist/core/apply-manager.d.mts.map +1 -0
- package/dist/core/apply-manager.mjs +6 -0
- package/dist/core/config.d.mts +8 -0
- package/dist/core/config.d.mts.map +1 -0
- package/dist/core/config.mjs +2 -0
- package/dist/core/content-manager.d.mts +53 -0
- package/dist/core/content-manager.d.mts.map +1 -0
- package/dist/core/content-manager.mjs +2 -0
- package/dist/core/context.d.mts +13 -0
- package/dist/core/context.d.mts.map +1 -0
- package/dist/core/context.mjs +3 -0
- package/dist/core/graph-builder.d.mts +12 -0
- package/dist/core/graph-builder.d.mts.map +1 -0
- package/dist/core/graph-builder.mjs +2 -0
- package/dist/core/meta-manager.d.mts +14 -0
- package/dist/core/meta-manager.d.mts.map +1 -0
- package/dist/core/meta-manager.mjs +2 -0
- package/dist/core/model-manager.d.mts +44 -0
- package/dist/core/model-manager.d.mts.map +1 -0
- package/dist/core/model-manager.mjs +2 -0
- package/dist/core/scan-config.d.mts +24 -0
- package/dist/core/scan-config.d.mts.map +1 -0
- package/dist/core/scan-config.mjs +2 -0
- package/dist/core/scanner.d.mts +25 -0
- package/dist/core/scanner.d.mts.map +1 -0
- package/dist/core/scanner.mjs +3 -0
- package/dist/core/validator.d.mts +23 -0
- package/dist/core/validator.d.mts.map +1 -0
- package/dist/core/validator.mjs +3 -0
- package/dist/detect-C8XmJ4S6.mjs +362 -0
- package/dist/detect-C8XmJ4S6.mjs.map +1 -0
- package/dist/fs-BbuGnVcG.mjs +52 -0
- package/dist/fs-BbuGnVcG.mjs.map +1 -0
- package/dist/git/branch-lifecycle.d.mts +28 -0
- package/dist/git/branch-lifecycle.d.mts.map +1 -0
- package/dist/git/branch-lifecycle.mjs +2 -0
- package/dist/git/transaction.d.mts +25 -0
- package/dist/git/transaction.d.mts.map +1 -0
- package/dist/git/transaction.mjs +4 -0
- package/dist/graph-builder-fPrDDwnu.mjs +162 -0
- package/dist/graph-builder-fPrDDwnu.mjs.map +1 -0
- package/dist/id-BdD4HvMY.mjs +12 -0
- package/dist/id-BdD4HvMY.mjs.map +1 -0
- package/dist/index.d.mts +1 -359
- package/dist/index.mjs +15 -2161
- package/dist/index.mjs.map +1 -1
- package/dist/meta-manager-CECrfsKm.mjs +53 -0
- package/dist/meta-manager-CECrfsKm.mjs.map +1 -0
- package/dist/model-manager-BcWWu5l2.mjs +963 -0
- package/dist/model-manager-BcWWu5l2.mjs.map +1 -0
- package/dist/node-Cbq5eR5i.mjs +300 -0
- package/dist/node-Cbq5eR5i.mjs.map +1 -0
- package/dist/scan-config-AJGxCdNd.mjs +159 -0
- package/dist/scan-config-AJGxCdNd.mjs.map +1 -0
- package/dist/scanner-BdTiv8sw.mjs +619 -0
- package/dist/scanner-BdTiv8sw.mjs.map +1 -0
- package/dist/serializer-Dueih-i2.mjs +33 -0
- package/dist/serializer-Dueih-i2.mjs.map +1 -0
- package/dist/server-CTcDpxwW.mjs +1861 -0
- package/dist/server-CTcDpxwW.mjs.map +1 -0
- package/dist/server.d.mts +7 -0
- package/dist/server.d.mts.map +1 -0
- package/dist/server.mjs +11 -0
- package/dist/source-map-generator-DpO-ejrt.mjs +893 -0
- package/dist/source-map-generator-DpO-ejrt.mjs.map +1 -0
- package/dist/svelte-parser-COTNG92w.mjs +225 -0
- package/dist/svelte-parser-COTNG92w.mjs.map +1 -0
- package/dist/templates/index.d.mts +8 -0
- package/dist/templates/index.d.mts.map +1 -0
- package/dist/templates/index.mjs +2 -0
- package/dist/templates-3HWi-PTu.mjs +824 -0
- package/dist/templates-3HWi-PTu.mjs.map +1 -0
- package/dist/transaction-BsECnmL5.mjs +128 -0
- package/dist/transaction-BsECnmL5.mjs.map +1 -0
- package/dist/tsx-parser-Bf8Firrq.mjs +2 -0
- package/dist/tsx-parser-CYVyBWjn.mjs +234 -0
- package/dist/tsx-parser-CYVyBWjn.mjs.map +1 -0
- package/dist/util/detect.d.mts +20 -0
- package/dist/util/detect.d.mts.map +1 -0
- package/dist/util/detect.mjs +2 -0
- package/dist/util/fs.d.mts +12 -0
- package/dist/util/fs.d.mts.map +1 -0
- package/dist/util/fs.mjs +2 -0
- package/dist/util/id.d.mts +6 -0
- package/dist/util/id.d.mts.map +1 -0
- package/dist/util/id.mjs +2 -0
- package/dist/util/serializer.d.mts +14 -0
- package/dist/util/serializer.d.mts.map +1 -0
- package/dist/util/serializer.mjs +2 -0
- package/dist/validator-ku84AyFr.mjs +755 -0
- package/dist/validator-ku84AyFr.mjs.map +1 -0
- package/dist/vue-parser-CjS4YAoQ.mjs +225 -0
- package/dist/vue-parser-CjS4YAoQ.mjs.map +1 -0
- package/package.json +107 -43
- package/dist/fs-D83-Ii_y.mjs +0 -75
- package/dist/fs-D83-Ii_y.mjs.map +0 -1
- package/dist/index.d.mts.map +0 -1
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import { a as readJson, r as pathExists } from "./fs-BbuGnVcG.mjs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
//#region src/util/detect.ts
|
|
4
|
+
const STACK_META = {
|
|
5
|
+
nuxt: {
|
|
6
|
+
name: "Nuxt",
|
|
7
|
+
description: "Vue meta-framework with SSR/SSG"
|
|
8
|
+
},
|
|
9
|
+
next: {
|
|
10
|
+
name: "Next.js",
|
|
11
|
+
description: "React framework with SSR/SSG"
|
|
12
|
+
},
|
|
13
|
+
astro: {
|
|
14
|
+
name: "Astro",
|
|
15
|
+
description: "Content-first web framework"
|
|
16
|
+
},
|
|
17
|
+
sveltekit: {
|
|
18
|
+
name: "SvelteKit",
|
|
19
|
+
description: "Svelte meta-framework"
|
|
20
|
+
},
|
|
21
|
+
remix: {
|
|
22
|
+
name: "Remix",
|
|
23
|
+
description: "Full-stack React framework"
|
|
24
|
+
},
|
|
25
|
+
analog: {
|
|
26
|
+
name: "Analog",
|
|
27
|
+
description: "Angular meta-framework"
|
|
28
|
+
},
|
|
29
|
+
vue: {
|
|
30
|
+
name: "Vue",
|
|
31
|
+
description: "Progressive JavaScript framework"
|
|
32
|
+
},
|
|
33
|
+
react: {
|
|
34
|
+
name: "React",
|
|
35
|
+
description: "UI library for web and native"
|
|
36
|
+
},
|
|
37
|
+
svelte: {
|
|
38
|
+
name: "Svelte",
|
|
39
|
+
description: "Compile-time UI framework"
|
|
40
|
+
},
|
|
41
|
+
solid: {
|
|
42
|
+
name: "Solid",
|
|
43
|
+
description: "Reactive UI library"
|
|
44
|
+
},
|
|
45
|
+
angular: {
|
|
46
|
+
name: "Angular",
|
|
47
|
+
description: "Platform for web applications"
|
|
48
|
+
},
|
|
49
|
+
"react-native": {
|
|
50
|
+
name: "React Native",
|
|
51
|
+
description: "Cross-platform mobile framework"
|
|
52
|
+
},
|
|
53
|
+
expo: {
|
|
54
|
+
name: "Expo",
|
|
55
|
+
description: "React Native toolchain"
|
|
56
|
+
},
|
|
57
|
+
flutter: {
|
|
58
|
+
name: "Flutter",
|
|
59
|
+
description: "Cross-platform UI toolkit (Dart)"
|
|
60
|
+
},
|
|
61
|
+
node: {
|
|
62
|
+
name: "Node.js",
|
|
63
|
+
description: "Server-side JavaScript runtime"
|
|
64
|
+
},
|
|
65
|
+
express: {
|
|
66
|
+
name: "Express",
|
|
67
|
+
description: "Minimal Node.js web framework"
|
|
68
|
+
},
|
|
69
|
+
fastify: {
|
|
70
|
+
name: "Fastify",
|
|
71
|
+
description: "Fast Node.js web framework"
|
|
72
|
+
},
|
|
73
|
+
nestjs: {
|
|
74
|
+
name: "NestJS",
|
|
75
|
+
description: "Progressive Node.js framework"
|
|
76
|
+
},
|
|
77
|
+
django: {
|
|
78
|
+
name: "Django",
|
|
79
|
+
description: "Python web framework"
|
|
80
|
+
},
|
|
81
|
+
rails: {
|
|
82
|
+
name: "Rails",
|
|
83
|
+
description: "Ruby web framework"
|
|
84
|
+
},
|
|
85
|
+
laravel: {
|
|
86
|
+
name: "Laravel",
|
|
87
|
+
description: "PHP web framework"
|
|
88
|
+
},
|
|
89
|
+
go: {
|
|
90
|
+
name: "Go",
|
|
91
|
+
description: "Go programming language"
|
|
92
|
+
},
|
|
93
|
+
rust: {
|
|
94
|
+
name: "Rust",
|
|
95
|
+
description: "Rust programming language"
|
|
96
|
+
},
|
|
97
|
+
dotnet: {
|
|
98
|
+
name: ".NET",
|
|
99
|
+
description: "Microsoft .NET platform"
|
|
100
|
+
},
|
|
101
|
+
hugo: {
|
|
102
|
+
name: "Hugo",
|
|
103
|
+
description: "Go-based static site generator"
|
|
104
|
+
},
|
|
105
|
+
jekyll: {
|
|
106
|
+
name: "Jekyll",
|
|
107
|
+
description: "Ruby-based static site generator"
|
|
108
|
+
},
|
|
109
|
+
eleventy: {
|
|
110
|
+
name: "Eleventy",
|
|
111
|
+
description: "JavaScript static site generator"
|
|
112
|
+
},
|
|
113
|
+
electron: {
|
|
114
|
+
name: "Electron",
|
|
115
|
+
description: "Cross-platform desktop apps"
|
|
116
|
+
},
|
|
117
|
+
tauri: {
|
|
118
|
+
name: "Tauri",
|
|
119
|
+
description: "Lightweight desktop apps (Rust)"
|
|
120
|
+
},
|
|
121
|
+
other: {
|
|
122
|
+
name: "Other",
|
|
123
|
+
description: "Unknown or unsupported framework"
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
function inferPlatform(stack) {
|
|
127
|
+
switch (stack) {
|
|
128
|
+
case "nuxt":
|
|
129
|
+
case "next":
|
|
130
|
+
case "astro":
|
|
131
|
+
case "sveltekit":
|
|
132
|
+
case "remix":
|
|
133
|
+
case "analog":
|
|
134
|
+
case "vue":
|
|
135
|
+
case "react":
|
|
136
|
+
case "svelte":
|
|
137
|
+
case "solid":
|
|
138
|
+
case "angular": return "web";
|
|
139
|
+
case "react-native":
|
|
140
|
+
case "expo":
|
|
141
|
+
case "flutter": return "mobile";
|
|
142
|
+
case "node":
|
|
143
|
+
case "express":
|
|
144
|
+
case "fastify":
|
|
145
|
+
case "nestjs":
|
|
146
|
+
case "django":
|
|
147
|
+
case "rails":
|
|
148
|
+
case "laravel":
|
|
149
|
+
case "go":
|
|
150
|
+
case "rust":
|
|
151
|
+
case "dotnet": return "api";
|
|
152
|
+
case "electron":
|
|
153
|
+
case "tauri": return "desktop";
|
|
154
|
+
case "hugo":
|
|
155
|
+
case "jekyll":
|
|
156
|
+
case "eleventy": return "static";
|
|
157
|
+
default: return "other";
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Backward-compatible: returns just the StackType string */
|
|
161
|
+
async function detectStack(projectRoot) {
|
|
162
|
+
return (await detectStackInfo(projectRoot)).stack;
|
|
163
|
+
}
|
|
164
|
+
/** Rich detection: stack + platform + monorepo + features */
|
|
165
|
+
async function detectStackInfo(projectRoot) {
|
|
166
|
+
let stack = await detectFromDeps(projectRoot);
|
|
167
|
+
if (stack === "other") {
|
|
168
|
+
let dir = dirname(projectRoot);
|
|
169
|
+
for (let i = 0; i < 5; i++) {
|
|
170
|
+
if ((await readJson(join(dir, "package.json")))?.workspaces) {
|
|
171
|
+
const rootStack = await detectFromDeps(dir);
|
|
172
|
+
if (rootStack !== "other") {
|
|
173
|
+
stack = rootStack;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const parent = dirname(dir);
|
|
178
|
+
if (parent === dir) break;
|
|
179
|
+
dir = parent;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (stack === "other") stack = await detectNonJs(projectRoot);
|
|
183
|
+
const mono = await detectMonorepo(projectRoot);
|
|
184
|
+
const features = await detectFeatures(projectRoot);
|
|
185
|
+
const meta = STACK_META[stack];
|
|
186
|
+
return {
|
|
187
|
+
stack,
|
|
188
|
+
platform: inferPlatform(stack),
|
|
189
|
+
name: meta.name,
|
|
190
|
+
description: meta.description,
|
|
191
|
+
monorepo: mono.isMonorepo,
|
|
192
|
+
monorepoTool: mono.tool,
|
|
193
|
+
features
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
async function detectFromDeps(dir) {
|
|
197
|
+
const pkg = await readJson(join(dir, "package.json"));
|
|
198
|
+
if (!pkg) return "other";
|
|
199
|
+
const allDeps = {
|
|
200
|
+
...pkg.dependencies,
|
|
201
|
+
...pkg.devDependencies
|
|
202
|
+
};
|
|
203
|
+
if ("nuxt" in allDeps) return "nuxt";
|
|
204
|
+
if ("next" in allDeps) return "next";
|
|
205
|
+
if ("astro" in allDeps) return "astro";
|
|
206
|
+
if ("@sveltejs/kit" in allDeps) return "sveltekit";
|
|
207
|
+
if ("@remix-run/node" in allDeps || "remix" in allDeps) return "remix";
|
|
208
|
+
if ("@analogjs/platform" in allDeps) return "analog";
|
|
209
|
+
if ("expo" in allDeps) return "expo";
|
|
210
|
+
if ("react-native" in allDeps) return "react-native";
|
|
211
|
+
if ("vue" in allDeps) return "vue";
|
|
212
|
+
if ("svelte" in allDeps) return "svelte";
|
|
213
|
+
if ("solid-js" in allDeps) return "solid";
|
|
214
|
+
if ("@angular/core" in allDeps) return "angular";
|
|
215
|
+
if ("react" in allDeps) return "react";
|
|
216
|
+
if ("electron" in allDeps) return "electron";
|
|
217
|
+
if ("@tauri-apps/api" in allDeps) return "tauri";
|
|
218
|
+
if ("@nestjs/core" in allDeps) return "nestjs";
|
|
219
|
+
if ("fastify" in allDeps) return "fastify";
|
|
220
|
+
if ("express" in allDeps) return "express";
|
|
221
|
+
if ("@11ty/eleventy" in allDeps) return "eleventy";
|
|
222
|
+
if ("node" in (pkg.dependencies ?? {})) return "node";
|
|
223
|
+
return "other";
|
|
224
|
+
}
|
|
225
|
+
async function detectNonJs(projectRoot) {
|
|
226
|
+
if (await pathExists(join(projectRoot, "go.mod"))) return "go";
|
|
227
|
+
if (await pathExists(join(projectRoot, "Cargo.toml"))) return "rust";
|
|
228
|
+
for (const f of [
|
|
229
|
+
"requirements.txt",
|
|
230
|
+
"pyproject.toml",
|
|
231
|
+
"setup.py"
|
|
232
|
+
]) if (await pathExists(join(projectRoot, f))) {
|
|
233
|
+
try {
|
|
234
|
+
const { readText } = await import("./util/fs.mjs");
|
|
235
|
+
const content = await readText(join(projectRoot, f));
|
|
236
|
+
if (content?.includes("django") || content?.includes("Django")) return "django";
|
|
237
|
+
} catch {}
|
|
238
|
+
return "other";
|
|
239
|
+
}
|
|
240
|
+
if (await pathExists(join(projectRoot, "Gemfile"))) {
|
|
241
|
+
try {
|
|
242
|
+
const { readText } = await import("./util/fs.mjs");
|
|
243
|
+
if ((await readText(join(projectRoot, "Gemfile")))?.includes("rails")) return "rails";
|
|
244
|
+
} catch {}
|
|
245
|
+
return "other";
|
|
246
|
+
}
|
|
247
|
+
for (const pattern of ["*.csproj", "*.sln"]) {
|
|
248
|
+
if (pattern === "*.csproj" && await pathExists(join(projectRoot, "Program.cs"))) return "dotnet";
|
|
249
|
+
if (pattern === "*.sln" && await pathExists(join(projectRoot, "Program.cs"))) return "dotnet";
|
|
250
|
+
}
|
|
251
|
+
if (await pathExists(join(projectRoot, "composer.json"))) {
|
|
252
|
+
try {
|
|
253
|
+
if (((await readJson(join(projectRoot, "composer.json")))?.require)?.["laravel/framework"]) return "laravel";
|
|
254
|
+
} catch {}
|
|
255
|
+
return "other";
|
|
256
|
+
}
|
|
257
|
+
if (await pathExists(join(projectRoot, "pubspec.yaml"))) return "flutter";
|
|
258
|
+
if (await pathExists(join(projectRoot, "hugo.toml"))) return "hugo";
|
|
259
|
+
if (await pathExists(join(projectRoot, "config.toml"))) try {
|
|
260
|
+
const { readText } = await import("./util/fs.mjs");
|
|
261
|
+
const content = await readText(join(projectRoot, "config.toml"));
|
|
262
|
+
if (content?.includes("baseURL") || content?.includes("hugo")) return "hugo";
|
|
263
|
+
} catch {}
|
|
264
|
+
if (await pathExists(join(projectRoot, "_config.yml"))) return "jekyll";
|
|
265
|
+
return "other";
|
|
266
|
+
}
|
|
267
|
+
async function detectMonorepo(projectRoot) {
|
|
268
|
+
if (await pathExists(join(projectRoot, "pnpm-workspace.yaml"))) return {
|
|
269
|
+
isMonorepo: true,
|
|
270
|
+
tool: "pnpm workspaces"
|
|
271
|
+
};
|
|
272
|
+
if (await pathExists(join(projectRoot, "lerna.json"))) return {
|
|
273
|
+
isMonorepo: true,
|
|
274
|
+
tool: "Lerna"
|
|
275
|
+
};
|
|
276
|
+
if (await pathExists(join(projectRoot, "nx.json"))) return {
|
|
277
|
+
isMonorepo: true,
|
|
278
|
+
tool: "Nx"
|
|
279
|
+
};
|
|
280
|
+
if (await pathExists(join(projectRoot, "turbo.json"))) return {
|
|
281
|
+
isMonorepo: true,
|
|
282
|
+
tool: "Turborepo"
|
|
283
|
+
};
|
|
284
|
+
if ((await readJson(join(projectRoot, "package.json")))?.workspaces) return {
|
|
285
|
+
isMonorepo: true,
|
|
286
|
+
tool: "npm/yarn workspaces"
|
|
287
|
+
};
|
|
288
|
+
let dir = dirname(projectRoot);
|
|
289
|
+
for (let i = 0; i < 5; i++) {
|
|
290
|
+
if (await pathExists(join(dir, "pnpm-workspace.yaml"))) return {
|
|
291
|
+
isMonorepo: true,
|
|
292
|
+
tool: "pnpm workspaces"
|
|
293
|
+
};
|
|
294
|
+
if (await pathExists(join(dir, "lerna.json"))) return {
|
|
295
|
+
isMonorepo: true,
|
|
296
|
+
tool: "Lerna"
|
|
297
|
+
};
|
|
298
|
+
if (await pathExists(join(dir, "nx.json"))) return {
|
|
299
|
+
isMonorepo: true,
|
|
300
|
+
tool: "Nx"
|
|
301
|
+
};
|
|
302
|
+
if (await pathExists(join(dir, "turbo.json"))) return {
|
|
303
|
+
isMonorepo: true,
|
|
304
|
+
tool: "Turborepo"
|
|
305
|
+
};
|
|
306
|
+
if ((await readJson(join(dir, "package.json")))?.workspaces) return {
|
|
307
|
+
isMonorepo: true,
|
|
308
|
+
tool: "npm/yarn workspaces"
|
|
309
|
+
};
|
|
310
|
+
const parent = dirname(dir);
|
|
311
|
+
if (parent === dir) break;
|
|
312
|
+
dir = parent;
|
|
313
|
+
}
|
|
314
|
+
return { isMonorepo: false };
|
|
315
|
+
}
|
|
316
|
+
async function detectFeatures(projectRoot) {
|
|
317
|
+
const features = [];
|
|
318
|
+
const allDeps = await collectAllDeps(projectRoot);
|
|
319
|
+
if ("typescript" in allDeps || await pathExists(join(projectRoot, "tsconfig.json"))) features.push("TypeScript");
|
|
320
|
+
for (const lib of [
|
|
321
|
+
"vue-i18n",
|
|
322
|
+
"@nuxtjs/i18n",
|
|
323
|
+
"next-intl",
|
|
324
|
+
"react-intl",
|
|
325
|
+
"i18next",
|
|
326
|
+
"react-i18next"
|
|
327
|
+
]) if (lib in allDeps) {
|
|
328
|
+
features.push(`i18n (${lib})`);
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
if ("tailwindcss" in allDeps) features.push("Tailwind CSS");
|
|
332
|
+
else if ("sass" in allDeps || "scss" in allDeps) features.push("Sass/SCSS");
|
|
333
|
+
if ("vitest" in allDeps) features.push("Vitest");
|
|
334
|
+
else if ("jest" in allDeps) features.push("Jest");
|
|
335
|
+
if ("pinia" in allDeps) features.push("Pinia");
|
|
336
|
+
else if ("zustand" in allDeps) features.push("Zustand");
|
|
337
|
+
else if ("@reduxjs/toolkit" in allDeps || "redux" in allDeps) features.push("Redux");
|
|
338
|
+
return features;
|
|
339
|
+
}
|
|
340
|
+
async function collectAllDeps(projectRoot) {
|
|
341
|
+
const pkg = await readJson(join(projectRoot, "package.json"));
|
|
342
|
+
const allDeps = {
|
|
343
|
+
...pkg?.dependencies,
|
|
344
|
+
...pkg?.devDependencies
|
|
345
|
+
};
|
|
346
|
+
let dir = dirname(projectRoot);
|
|
347
|
+
for (let i = 0; i < 5; i++) {
|
|
348
|
+
const parentPkg = await readJson(join(dir, "package.json"));
|
|
349
|
+
if (parentPkg?.workspaces) {
|
|
350
|
+
Object.assign(allDeps, parentPkg.dependencies, parentPkg.devDependencies);
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
const parent = dirname(dir);
|
|
354
|
+
if (parent === dir) break;
|
|
355
|
+
dir = parent;
|
|
356
|
+
}
|
|
357
|
+
return allDeps;
|
|
358
|
+
}
|
|
359
|
+
//#endregion
|
|
360
|
+
export { detectStackInfo as n, inferPlatform as r, detectStack as t };
|
|
361
|
+
|
|
362
|
+
//# sourceMappingURL=detect-C8XmJ4S6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-C8XmJ4S6.mjs","names":[],"sources":["../src/util/detect.ts"],"sourcesContent":["import type { StackType, Platform } from '@contentrain/types'\nimport { join, dirname } from 'node:path'\nimport { readJson, pathExists } from './fs.js'\n\ninterface PackageJson {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n workspaces?: string[] | { packages: string[] }\n}\n\nexport interface StackInfo {\n stack: StackType\n platform: Platform\n name: string\n description: string\n monorepo: boolean\n monorepoTool?: string\n features: string[]\n}\n\nconst STACK_META: Record<StackType, { name: string; description: string }> = {\n // Meta-frameworks\n nuxt: { name: 'Nuxt', description: 'Vue meta-framework with SSR/SSG' },\n next: { name: 'Next.js', description: 'React framework with SSR/SSG' },\n astro: { name: 'Astro', description: 'Content-first web framework' },\n sveltekit: { name: 'SvelteKit', description: 'Svelte meta-framework' },\n remix: { name: 'Remix', description: 'Full-stack React framework' },\n analog: { name: 'Analog', description: 'Angular meta-framework' },\n // Plain frameworks\n vue: { name: 'Vue', description: 'Progressive JavaScript framework' },\n react: { name: 'React', description: 'UI library for web and native' },\n svelte: { name: 'Svelte', description: 'Compile-time UI framework' },\n solid: { name: 'Solid', description: 'Reactive UI library' },\n angular: { name: 'Angular', description: 'Platform for web applications' },\n // Mobile\n 'react-native': { name: 'React Native', description: 'Cross-platform mobile framework' },\n expo: { name: 'Expo', description: 'React Native toolchain' },\n flutter: { name: 'Flutter', description: 'Cross-platform UI toolkit (Dart)' },\n // Backend\n node: { name: 'Node.js', description: 'Server-side JavaScript runtime' },\n express: { name: 'Express', description: 'Minimal Node.js web framework' },\n fastify: { name: 'Fastify', description: 'Fast Node.js web framework' },\n nestjs: { name: 'NestJS', description: 'Progressive Node.js framework' },\n django: { name: 'Django', description: 'Python web framework' },\n rails: { name: 'Rails', description: 'Ruby web framework' },\n laravel: { name: 'Laravel', description: 'PHP web framework' },\n go: { name: 'Go', description: 'Go programming language' },\n rust: { name: 'Rust', description: 'Rust programming language' },\n dotnet: { name: '.NET', description: 'Microsoft .NET platform' },\n // Static\n hugo: { name: 'Hugo', description: 'Go-based static site generator' },\n jekyll: { name: 'Jekyll', description: 'Ruby-based static site generator' },\n eleventy: { name: 'Eleventy', description: 'JavaScript static site generator' },\n // Desktop\n electron: { name: 'Electron', description: 'Cross-platform desktop apps' },\n tauri: { name: 'Tauri', description: 'Lightweight desktop apps (Rust)' },\n // Catch-all\n other: { name: 'Other', description: 'Unknown or unsupported framework' },\n}\n\nexport function inferPlatform(stack: StackType): Platform {\n switch (stack) {\n case 'nuxt': case 'next': case 'astro': case 'sveltekit': case 'remix': case 'analog':\n case 'vue': case 'react': case 'svelte': case 'solid': case 'angular':\n return 'web'\n case 'react-native': case 'expo': case 'flutter':\n return 'mobile'\n case 'node': case 'express': case 'fastify': case 'nestjs':\n case 'django': case 'rails': case 'laravel': case 'go': case 'rust': case 'dotnet':\n return 'api'\n case 'electron': case 'tauri':\n return 'desktop'\n case 'hugo': case 'jekyll': case 'eleventy':\n return 'static'\n default:\n return 'other'\n }\n}\n\n/** Backward-compatible: returns just the StackType string */\nexport async function detectStack(projectRoot: string): Promise<StackType> {\n const info = await detectStackInfo(projectRoot)\n return info.stack\n}\n\n/** Rich detection: stack + platform + monorepo + features */\nexport async function detectStackInfo(projectRoot: string): Promise<StackInfo> {\n let stack = await detectFromDeps(projectRoot)\n\n // Walk up for monorepo root if local didn't match\n if (stack === 'other') {\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n const pkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (pkg?.workspaces) {\n const rootStack = await detectFromDeps(dir)\n if (rootStack !== 'other') {\n stack = rootStack\n break\n }\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n }\n\n // Non-JS detection if still 'other'\n if (stack === 'other') {\n stack = await detectNonJs(projectRoot)\n }\n\n const mono = await detectMonorepo(projectRoot)\n const features = await detectFeatures(projectRoot)\n const meta = STACK_META[stack]\n\n return {\n stack,\n platform: inferPlatform(stack),\n name: meta.name,\n description: meta.description,\n monorepo: mono.isMonorepo,\n monorepoTool: mono.tool,\n features,\n }\n}\n\nasync function detectFromDeps(dir: string): Promise<StackType> {\n const pkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (!pkg) return 'other'\n\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies }\n\n // Meta-frameworks (check BEFORE plain frameworks)\n if ('nuxt' in allDeps) return 'nuxt'\n if ('next' in allDeps) return 'next'\n if ('astro' in allDeps) return 'astro'\n if ('@sveltejs/kit' in allDeps) return 'sveltekit'\n if ('@remix-run/node' in allDeps || 'remix' in allDeps) return 'remix'\n if ('@analogjs/platform' in allDeps) return 'analog'\n\n // Mobile (check before plain react)\n if ('expo' in allDeps) return 'expo'\n if ('react-native' in allDeps) return 'react-native'\n\n // Plain frameworks\n if ('vue' in allDeps) return 'vue'\n if ('svelte' in allDeps) return 'svelte'\n if ('solid-js' in allDeps) return 'solid'\n if ('@angular/core' in allDeps) return 'angular'\n if ('react' in allDeps) return 'react'\n\n // Desktop\n if ('electron' in allDeps) return 'electron'\n if ('@tauri-apps/api' in allDeps) return 'tauri'\n\n // Backend (Node.js)\n if ('@nestjs/core' in allDeps) return 'nestjs'\n if ('fastify' in allDeps) return 'fastify'\n if ('express' in allDeps) return 'express'\n\n // Static site generators\n if ('@11ty/eleventy' in allDeps) return 'eleventy'\n\n // Generic Node.js (has package.json but no framework)\n if ('node' in (pkg.dependencies ?? {})) return 'node'\n\n return 'other'\n}\n\nasync function detectNonJs(projectRoot: string): Promise<StackType> {\n // Go\n if (await pathExists(join(projectRoot, 'go.mod'))) return 'go'\n\n // Rust\n if (await pathExists(join(projectRoot, 'Cargo.toml'))) return 'rust'\n\n // Python\n for (const f of ['requirements.txt', 'pyproject.toml', 'setup.py']) {\n if (await pathExists(join(projectRoot, f))) {\n // Check for Django\n try {\n const { readText } = await import('./fs.js')\n const content = await readText(join(projectRoot, f))\n if (content?.includes('django') || content?.includes('Django')) return 'django'\n } catch { /* ignore */ }\n return 'other' // Generic Python — no specific stack type yet\n }\n }\n\n // Ruby\n if (await pathExists(join(projectRoot, 'Gemfile'))) {\n try {\n const { readText } = await import('./fs.js')\n const content = await readText(join(projectRoot, 'Gemfile'))\n if (content?.includes('rails')) return 'rails'\n } catch { /* ignore */ }\n return 'other'\n }\n\n // .NET\n const dotnetFiles = ['*.csproj', '*.sln']\n for (const pattern of dotnetFiles) {\n if (pattern === '*.csproj' && await pathExists(join(projectRoot, 'Program.cs'))) return 'dotnet'\n if (pattern === '*.sln' && await pathExists(join(projectRoot, 'Program.cs'))) return 'dotnet'\n }\n\n // PHP / Laravel\n if (await pathExists(join(projectRoot, 'composer.json'))) {\n try {\n const composer = await readJson<Record<string, unknown>>(join(projectRoot, 'composer.json'))\n const require = composer?.require as Record<string, string> | undefined\n if (require?.['laravel/framework']) return 'laravel'\n } catch { /* ignore */ }\n return 'other'\n }\n\n // Flutter (Dart)\n if (await pathExists(join(projectRoot, 'pubspec.yaml'))) return 'flutter'\n\n // Hugo\n if (await pathExists(join(projectRoot, 'hugo.toml'))) return 'hugo'\n if (await pathExists(join(projectRoot, 'config.toml'))) {\n try {\n const { readText } = await import('./fs.js')\n const content = await readText(join(projectRoot, 'config.toml'))\n if (content?.includes('baseURL') || content?.includes('hugo')) return 'hugo'\n } catch { /* ignore */ }\n }\n\n // Jekyll\n if (await pathExists(join(projectRoot, '_config.yml'))) return 'jekyll'\n\n return 'other'\n}\n\nasync function detectMonorepo(projectRoot: string): Promise<{ isMonorepo: boolean; tool?: string }> {\n if (await pathExists(join(projectRoot, 'pnpm-workspace.yaml'))) return { isMonorepo: true, tool: 'pnpm workspaces' }\n if (await pathExists(join(projectRoot, 'lerna.json'))) return { isMonorepo: true, tool: 'Lerna' }\n if (await pathExists(join(projectRoot, 'nx.json'))) return { isMonorepo: true, tool: 'Nx' }\n if (await pathExists(join(projectRoot, 'turbo.json'))) return { isMonorepo: true, tool: 'Turborepo' }\n\n const pkg = await readJson<PackageJson>(join(projectRoot, 'package.json'))\n if (pkg?.workspaces) return { isMonorepo: true, tool: 'npm/yarn workspaces' }\n\n // Walk up\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n if (await pathExists(join(dir, 'pnpm-workspace.yaml'))) return { isMonorepo: true, tool: 'pnpm workspaces' }\n if (await pathExists(join(dir, 'lerna.json'))) return { isMonorepo: true, tool: 'Lerna' }\n if (await pathExists(join(dir, 'nx.json'))) return { isMonorepo: true, tool: 'Nx' }\n if (await pathExists(join(dir, 'turbo.json'))) return { isMonorepo: true, tool: 'Turborepo' }\n const parentPkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (parentPkg?.workspaces) return { isMonorepo: true, tool: 'npm/yarn workspaces' }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n\n return { isMonorepo: false }\n}\n\nasync function detectFeatures(projectRoot: string): Promise<string[]> {\n const features: string[] = []\n const allDeps = await collectAllDeps(projectRoot)\n\n if ('typescript' in allDeps || await pathExists(join(projectRoot, 'tsconfig.json'))) features.push('TypeScript')\n\n const i18nLibs = ['vue-i18n', '@nuxtjs/i18n', 'next-intl', 'react-intl', 'i18next', 'react-i18next']\n for (const lib of i18nLibs) {\n if (lib in allDeps) { features.push(`i18n (${lib})`); break }\n }\n\n if ('tailwindcss' in allDeps) features.push('Tailwind CSS')\n else if ('sass' in allDeps || 'scss' in allDeps) features.push('Sass/SCSS')\n\n if ('vitest' in allDeps) features.push('Vitest')\n else if ('jest' in allDeps) features.push('Jest')\n\n if ('pinia' in allDeps) features.push('Pinia')\n else if ('zustand' in allDeps) features.push('Zustand')\n else if ('@reduxjs/toolkit' in allDeps || 'redux' in allDeps) features.push('Redux')\n\n return features\n}\n\nasync function collectAllDeps(projectRoot: string): Promise<Record<string, string>> {\n const pkg = await readJson<PackageJson>(join(projectRoot, 'package.json'))\n const allDeps: Record<string, string> = { ...pkg?.dependencies, ...pkg?.devDependencies }\n\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n const parentPkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (parentPkg?.workspaces) {\n Object.assign(allDeps, parentPkg.dependencies, parentPkg.devDependencies)\n break\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n\n return allDeps\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { t as canonicalStringify } from "./serializer-Dueih-i2.mjs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { access, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
4
|
+
//#region src/util/fs.ts
|
|
5
|
+
async function pathExists(filePath) {
|
|
6
|
+
try {
|
|
7
|
+
await access(filePath);
|
|
8
|
+
return true;
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function readJson(filePath) {
|
|
14
|
+
try {
|
|
15
|
+
const raw = await readFile(filePath, "utf-8");
|
|
16
|
+
return JSON.parse(raw);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function readDir(dirPath) {
|
|
22
|
+
try {
|
|
23
|
+
return await readdir(dirPath);
|
|
24
|
+
} catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function writeJson(filePath, data, fieldOrder) {
|
|
29
|
+
await mkdir(join(filePath, ".."), { recursive: true });
|
|
30
|
+
await writeFile(filePath, canonicalStringify(data, fieldOrder), "utf-8");
|
|
31
|
+
}
|
|
32
|
+
async function ensureDir(dirPath) {
|
|
33
|
+
await mkdir(dirPath, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
async function readText(filePath) {
|
|
36
|
+
try {
|
|
37
|
+
return await readFile(filePath, "utf-8");
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function writeText(filePath, content) {
|
|
43
|
+
await mkdir(join(filePath, ".."), { recursive: true });
|
|
44
|
+
await writeFile(filePath, content, "utf-8");
|
|
45
|
+
}
|
|
46
|
+
function contentrainDir(projectRoot) {
|
|
47
|
+
return join(projectRoot, ".contentrain");
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { readJson as a, writeText as c, readDir as i, ensureDir as n, readText as o, pathExists as r, writeJson as s, contentrainDir as t };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=fs-BbuGnVcG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-BbuGnVcG.mjs","names":[],"sources":["../src/util/fs.ts"],"sourcesContent":["import { readFile, readdir, access, writeFile, mkdir } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { canonicalStringify } from './serializer.js'\n\nexport async function pathExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath)\n return true\n } catch {\n return false\n }\n}\n\nexport async function readJson<T>(filePath: string): Promise<T | null> {\n try {\n const raw = await readFile(filePath, 'utf-8')\n return JSON.parse(raw) as T\n } catch {\n return null\n }\n}\n\nexport async function readDir(dirPath: string): Promise<string[]> {\n try {\n return await readdir(dirPath)\n } catch {\n return []\n }\n}\n\nexport async function writeJson(filePath: string, data: unknown, fieldOrder?: string[]): Promise<void> {\n await mkdir(join(filePath, '..'), { recursive: true })\n await writeFile(filePath, canonicalStringify(data, fieldOrder), 'utf-8')\n}\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await mkdir(dirPath, { recursive: true })\n}\n\nexport async function readText(filePath: string): Promise<string | null> {\n try {\n return await readFile(filePath, 'utf-8')\n } catch {\n return null\n }\n}\n\nexport async function writeText(filePath: string, content: string): Promise<void> {\n await mkdir(join(filePath, '..'), { recursive: true })\n await writeFile(filePath, content, 'utf-8')\n}\n\nexport function contentrainDir(projectRoot: string): string {\n return join(projectRoot, '.contentrain')\n}\n"],"mappings":";;;;AAIA,eAAsB,WAAW,UAAoC;AACnE,KAAI;AACF,QAAM,OAAO,SAAS;AACtB,SAAO;SACD;AACN,SAAO;;;AAIX,eAAsB,SAAY,UAAqC;AACrE,KAAI;EACF,MAAM,MAAM,MAAM,SAAS,UAAU,QAAQ;AAC7C,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO;;;AAIX,eAAsB,QAAQ,SAAoC;AAChE,KAAI;AACF,SAAO,MAAM,QAAQ,QAAQ;SACvB;AACN,SAAO,EAAE;;;AAIb,eAAsB,UAAU,UAAkB,MAAe,YAAsC;AACrG,OAAM,MAAM,KAAK,UAAU,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACtD,OAAM,UAAU,UAAU,mBAAmB,MAAM,WAAW,EAAE,QAAQ;;AAG1E,eAAsB,UAAU,SAAgC;AAC9D,OAAM,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;;AAG3C,eAAsB,SAAS,UAA0C;AACvE,KAAI;AACF,SAAO,MAAM,SAAS,UAAU,QAAQ;SAClC;AACN,SAAO;;;AAIX,eAAsB,UAAU,UAAkB,SAAgC;AAChF,OAAM,MAAM,KAAK,UAAU,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACtD,OAAM,UAAU,UAAU,SAAS,QAAQ;;AAG7C,SAAgB,eAAe,aAA6B;AAC1D,QAAO,KAAK,aAAa,eAAe"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/git/branch-lifecycle.d.ts
|
|
2
|
+
interface CleanupResult {
|
|
3
|
+
deleted: number;
|
|
4
|
+
remaining: number;
|
|
5
|
+
deletedBranches: string[];
|
|
6
|
+
}
|
|
7
|
+
interface BranchHealthCheck {
|
|
8
|
+
total: number;
|
|
9
|
+
merged: number;
|
|
10
|
+
unmerged: number;
|
|
11
|
+
warning: boolean;
|
|
12
|
+
blocked: boolean;
|
|
13
|
+
message?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Lists all local contentrain/* branches, deletes those already merged
|
|
17
|
+
* into the base branch, and returns the count of remaining unmerged ones.
|
|
18
|
+
*/
|
|
19
|
+
declare function cleanupMergedBranches(projectRoot: string): Promise<CleanupResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Check branch health: count contentrain/* branches and return warning/blocked status.
|
|
22
|
+
* - 50+ branches: warning
|
|
23
|
+
* - 80+ branches: blocked
|
|
24
|
+
*/
|
|
25
|
+
declare function checkBranchHealth(projectRoot: string): Promise<BranchHealthCheck>;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { BranchHealthCheck, CleanupResult, checkBranchHealth, cleanupMergedBranches };
|
|
28
|
+
//# sourceMappingURL=branch-lifecycle.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-lifecycle.d.mts","names":[],"sources":["../../src/git/branch-lifecycle.ts"],"mappings":";UAGiB,aAAA;EACf,OAAA;EACA,SAAA;EACA,eAAA;AAAA;AAAA,UAGe,iBAAA;EACf,KAAA;EACA,MAAA;EACA,QAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;AAAA;;;;;iBAOoB,qBAAA,CAAsB,WAAA,WAAsB,OAAA,CAAQ,aAAA;;;;;AAA1E;iBA8DsB,iBAAA,CAAkB,WAAA,WAAsB,OAAA,CAAQ,iBAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/git/transaction.d.ts
|
|
2
|
+
interface ContextUpdate {
|
|
3
|
+
tool: string;
|
|
4
|
+
model: string;
|
|
5
|
+
locale?: string;
|
|
6
|
+
entries?: string[];
|
|
7
|
+
}
|
|
8
|
+
interface GitTransaction {
|
|
9
|
+
worktree: string;
|
|
10
|
+
branch: string;
|
|
11
|
+
write(callback: (worktreePath: string) => Promise<void>): Promise<void>;
|
|
12
|
+
commit(message: string): Promise<string>;
|
|
13
|
+
complete(contextUpdate?: ContextUpdate): Promise<{
|
|
14
|
+
action: 'auto-merged' | 'pending-review';
|
|
15
|
+
commit: string;
|
|
16
|
+
}>;
|
|
17
|
+
cleanup(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
declare function createTransaction(projectRoot: string, branchName: string, options?: {
|
|
20
|
+
workflowOverride?: 'review' | 'auto-merge';
|
|
21
|
+
}): Promise<GitTransaction>;
|
|
22
|
+
declare function buildBranchName(scope: string, target: string, locale?: string): string;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { ContextUpdate, GitTransaction, buildBranchName, createTransaction };
|
|
25
|
+
//# sourceMappingURL=transaction.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.mts","names":[],"sources":["../../src/git/transaction.ts"],"mappings":";UAQiB,aAAA;EACf,IAAA;EACA,KAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,UAGe,cAAA;EACf,QAAA;EACA,MAAA;EACA,KAAA,CAAM,QAAA,GAAW,YAAA,aAAyB,OAAA,SAAgB,OAAA;EAC1D,MAAA,CAAO,OAAA,WAAkB,OAAA;EACzB,QAAA,CAAS,aAAA,GAAgB,aAAA,GAAgB,OAAA;IAAU,MAAA;IAA0C,MAAA;EAAA;EAC7F,OAAA,IAAW,OAAA;AAAA;AAAA,iBAGS,iBAAA,CACpB,WAAA,UACA,UAAA,UACA,OAAA;EAAY,gBAAA;AAAA,IACX,OAAA,CAAQ,cAAA;AAAA,iBAuJK,eAAA,CAAgB,KAAA,UAAe,MAAA,UAAgB,MAAA"}
|