@capuchoo/cli 0.2.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 (111) hide show
  1. package/README.md +351 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +5 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +5 -0
  6. package/dist/base-command.d.ts +15 -0
  7. package/dist/base-command.d.ts.map +1 -0
  8. package/dist/base-command.js +61 -0
  9. package/dist/base-command.js.map +1 -0
  10. package/dist/commands/auth/login.d.ts +19 -0
  11. package/dist/commands/auth/login.d.ts.map +1 -0
  12. package/dist/commands/auth/login.js +74 -0
  13. package/dist/commands/auth/login.js.map +1 -0
  14. package/dist/commands/auth/logout.d.ts +6 -0
  15. package/dist/commands/auth/logout.d.ts.map +1 -0
  16. package/dist/commands/auth/logout.js +22 -0
  17. package/dist/commands/auth/logout.js.map +1 -0
  18. package/dist/commands/auth/whoami.d.ts +9 -0
  19. package/dist/commands/auth/whoami.d.ts.map +1 -0
  20. package/dist/commands/auth/whoami.js +77 -0
  21. package/dist/commands/auth/whoami.js.map +1 -0
  22. package/dist/commands/channel/list.d.ts +9 -0
  23. package/dist/commands/channel/list.d.ts.map +1 -0
  24. package/dist/commands/channel/list.js +47 -0
  25. package/dist/commands/channel/list.js.map +1 -0
  26. package/dist/commands/config/list.d.ts +9 -0
  27. package/dist/commands/config/list.d.ts.map +1 -0
  28. package/dist/commands/config/list.js +116 -0
  29. package/dist/commands/config/list.js.map +1 -0
  30. package/dist/commands/config/set.d.ts +11 -0
  31. package/dist/commands/config/set.d.ts.map +1 -0
  32. package/dist/commands/config/set.js +44 -0
  33. package/dist/commands/config/set.js.map +1 -0
  34. package/dist/commands/deploy/native.d.ts +23 -0
  35. package/dist/commands/deploy/native.d.ts.map +1 -0
  36. package/dist/commands/deploy/native.js +39 -0
  37. package/dist/commands/deploy/native.js.map +1 -0
  38. package/dist/commands/deploy/ota.d.ts +20 -0
  39. package/dist/commands/deploy/ota.d.ts.map +1 -0
  40. package/dist/commands/deploy/ota.js +20 -0
  41. package/dist/commands/deploy/ota.js.map +1 -0
  42. package/dist/commands/init.d.ts +17 -0
  43. package/dist/commands/init.d.ts.map +1 -0
  44. package/dist/commands/init.js +232 -0
  45. package/dist/commands/init.js.map +1 -0
  46. package/dist/commands/version/bump.d.ts +13 -0
  47. package/dist/commands/version/bump.d.ts.map +1 -0
  48. package/dist/commands/version/bump.js +52 -0
  49. package/dist/commands/version/bump.js.map +1 -0
  50. package/dist/commands/version/sync.d.ts +12 -0
  51. package/dist/commands/version/sync.d.ts.map +1 -0
  52. package/dist/commands/version/sync.js +81 -0
  53. package/dist/commands/version/sync.js.map +1 -0
  54. package/dist/deploy/execute.d.ts +48 -0
  55. package/dist/deploy/execute.d.ts.map +1 -0
  56. package/dist/deploy/execute.js +280 -0
  57. package/dist/deploy/execute.js.map +1 -0
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +2 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/pipeline/android.d.ts +37 -0
  63. package/dist/pipeline/android.d.ts.map +1 -0
  64. package/dist/pipeline/android.js +96 -0
  65. package/dist/pipeline/android.js.map +1 -0
  66. package/dist/pipeline/build.d.ts +69 -0
  67. package/dist/pipeline/build.d.ts.map +1 -0
  68. package/dist/pipeline/build.js +138 -0
  69. package/dist/pipeline/build.js.map +1 -0
  70. package/dist/pipeline/deploy.d.ts +74 -0
  71. package/dist/pipeline/deploy.d.ts.map +1 -0
  72. package/dist/pipeline/deploy.js +198 -0
  73. package/dist/pipeline/deploy.js.map +1 -0
  74. package/dist/pipeline/flavour.d.ts +66 -0
  75. package/dist/pipeline/flavour.d.ts.map +1 -0
  76. package/dist/pipeline/flavour.js +120 -0
  77. package/dist/pipeline/flavour.js.map +1 -0
  78. package/dist/pipeline/native-config.d.ts +43 -0
  79. package/dist/pipeline/native-config.d.ts.map +1 -0
  80. package/dist/pipeline/native-config.js +127 -0
  81. package/dist/pipeline/native-config.js.map +1 -0
  82. package/dist/pipeline/toolchain.d.ts +80 -0
  83. package/dist/pipeline/toolchain.d.ts.map +1 -0
  84. package/dist/pipeline/toolchain.js +146 -0
  85. package/dist/pipeline/toolchain.js.map +1 -0
  86. package/dist/pipeline/zip.d.ts +22 -0
  87. package/dist/pipeline/zip.d.ts.map +1 -0
  88. package/dist/pipeline/zip.js +188 -0
  89. package/dist/pipeline/zip.js.map +1 -0
  90. package/dist/services/cloud.d.ts +58 -0
  91. package/dist/services/cloud.d.ts.map +1 -0
  92. package/dist/services/cloud.js +89 -0
  93. package/dist/services/cloud.js.map +1 -0
  94. package/dist/utils/config.d.ts +52 -0
  95. package/dist/utils/config.d.ts.map +1 -0
  96. package/dist/utils/config.js +144 -0
  97. package/dist/utils/config.js.map +1 -0
  98. package/dist/utils/exec.d.ts +44 -0
  99. package/dist/utils/exec.d.ts.map +1 -0
  100. package/dist/utils/exec.js +136 -0
  101. package/dist/utils/exec.js.map +1 -0
  102. package/dist/utils/http.d.ts +37 -0
  103. package/dist/utils/http.d.ts.map +1 -0
  104. package/dist/utils/http.js +137 -0
  105. package/dist/utils/http.js.map +1 -0
  106. package/dist/utils/reporter.d.ts +48 -0
  107. package/dist/utils/reporter.d.ts.map +1 -0
  108. package/dist/utils/reporter.js +108 -0
  109. package/dist/utils/reporter.js.map +1 -0
  110. package/oclif.manifest.json +568 -0
  111. package/package.json +81 -0
@@ -0,0 +1,43 @@
1
+ import { type RunOptions } from "../utils/exec.js";
2
+ import type { ResolvedFlavour } from "./flavour.js";
3
+ /**
4
+ * Applies a flavour's identity and version to the native projects.
5
+ *
6
+ * The old pipeline ran `pnpm trapeze:<env>` and died if that script did not
7
+ * exist or Trapeze was not installed - which is the single most common way a
8
+ * deploy failed on a fresh checkout. Here Trapeze is *preferred* but optional:
9
+ *
10
+ * 1. Trapeze installed and a config exists for the flavour -> run Trapeze, so
11
+ * the app's own YAML stays authoritative (permissions, plist entries, and
12
+ * everything else this file does not model).
13
+ * 2. Otherwise -> apply the identity and version directly. That is the subset
14
+ * every flavour needs, and it is enough for a correct build.
15
+ *
16
+ * Either way the deploy proceeds, and the CLI says which path it took.
17
+ */
18
+ export type NativeConfigMethod = "trapeze" | "builtin";
19
+ export interface NativeConfigResult {
20
+ method: NativeConfigMethod;
21
+ /** Files the built-in path rewrote. Empty when Trapeze ran. */
22
+ changed: string[];
23
+ /** Why the built-in path was used, when it was. */
24
+ reason?: string;
25
+ }
26
+ export interface NativeConfigInput {
27
+ appDir: string;
28
+ androidDir: string;
29
+ iosDir: string;
30
+ flavour: ResolvedFlavour;
31
+ /** Environment for Trapeze's `vars:` block and for the built-in patcher. */
32
+ env: Record<string, string>;
33
+ platform: "android" | "ios";
34
+ runOptions: Omit<RunOptions, "cwd" | "env">;
35
+ }
36
+ export declare function applyNativeConfig(input: NativeConfigInput): Promise<NativeConfigResult>;
37
+ /**
38
+ * The bundle identifier iOS builds from lives in `project.pbxproj`, which is
39
+ * not safely editable with a regex. Trapeze does it properly, so the built-in
40
+ * path reports the limitation instead of pretending to have handled it.
41
+ */
42
+ export declare function builtinConfigLimitations(platform: "android" | "ios"): string[];
43
+ //# sourceMappingURL=native-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-config.d.ts","sourceRoot":"","sources":["../../src/pipeline/native-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAO,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,+DAA+D;IAC/D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,eAAe,CAAC;IACzB,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,QAAQ,EAAE,SAAS,GAAG,KAAK,CAAC;IAC5B,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;CAC7C;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmB7F;AA+GD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,GAAG,MAAM,EAAE,CAK9E"}
@@ -0,0 +1,127 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { run } from "../utils/exec.js";
4
+ import { resolveBin } from "./toolchain.js";
5
+ export async function applyNativeConfig(input) {
6
+ const trapezeBin = resolveBin("trapeze", input.appDir);
7
+ if (trapezeBin && input.flavour.trapezeConfig) {
8
+ // `-y` accepts the diff Trapeze prints; without it the command waits for
9
+ // input forever in CI.
10
+ await run(trapezeBin, ["run", input.flavour.trapezeConfig, "-y"], {
11
+ ...input.runOptions,
12
+ cwd: input.appDir,
13
+ env: input.env,
14
+ });
15
+ return { method: "trapeze", changed: [] };
16
+ }
17
+ const reason = !trapezeBin
18
+ ? "@trapezedev/configure is not installed"
19
+ : `no Trapeze config at ${input.flavour.config.trapezeConfig}`;
20
+ return { ...applyBuiltinConfig(input), reason };
21
+ }
22
+ function applyBuiltinConfig(input) {
23
+ const changed = [];
24
+ if (input.platform === "android") {
25
+ changed.push(...patchAndroid(input));
26
+ }
27
+ else {
28
+ changed.push(...patchIos(input));
29
+ }
30
+ return { method: "builtin", changed };
31
+ }
32
+ function readEnv(env, key) {
33
+ const value = env[key];
34
+ return value && value.length > 0 ? value : undefined;
35
+ }
36
+ function patchAndroid(input) {
37
+ const androidRoot = path.resolve(input.appDir, input.androidDir);
38
+ if (!fs.existsSync(androidRoot))
39
+ return [];
40
+ const appId = readEnv(input.env, "VITE_APP_ID");
41
+ const appName = readEnv(input.env, "VITE_APP_NAME");
42
+ const version = readEnv(input.env, "VITE_APP_VERSION");
43
+ const versionCode = readEnv(input.env, "VERSION_CODE");
44
+ const changed = [];
45
+ const gradleFile = path.join(androidRoot, "app", "build.gradle");
46
+ if (fs.existsSync(gradleFile)) {
47
+ let gradle = fs.readFileSync(gradleFile, "utf8");
48
+ const before = gradle;
49
+ if (appId) {
50
+ // Both forms appear in a Capacitor project: `namespace = "..."` and
51
+ // `applicationId "..."`. Quote style varies, so match either.
52
+ gradle = gradle.replace(/(\bnamespace\s*=\s*)["'][^"']*["']/, `$1"${appId}"`);
53
+ gradle = gradle.replace(/(\bapplicationId\s*=?\s*)["'][^"']*["']/, `$1"${appId}"`);
54
+ }
55
+ if (version) {
56
+ gradle = gradle.replace(/(\bversionName\s*=?\s*)["'][^"']*["']/, `$1"${version}"`);
57
+ }
58
+ if (versionCode) {
59
+ gradle = gradle.replace(/(\bversionCode\s*=?\s*)\d+/, `$1${versionCode}`);
60
+ }
61
+ if (gradle !== before) {
62
+ fs.writeFileSync(gradleFile, gradle);
63
+ changed.push(path.relative(input.appDir, gradleFile));
64
+ }
65
+ }
66
+ const stringsFile = path.join(androidRoot, "app", "src", "main", "res", "values", "strings.xml");
67
+ if (fs.existsSync(stringsFile)) {
68
+ let strings = fs.readFileSync(stringsFile, "utf8");
69
+ const before = strings;
70
+ if (appName) {
71
+ strings = replaceStringResource(strings, "app_name", appName);
72
+ strings = replaceStringResource(strings, "title_activity_main", appName);
73
+ }
74
+ if (appId) {
75
+ strings = replaceStringResource(strings, "package_name", appId);
76
+ strings = replaceStringResource(strings, "custom_url_scheme", appId);
77
+ }
78
+ if (strings !== before) {
79
+ fs.writeFileSync(stringsFile, strings);
80
+ changed.push(path.relative(input.appDir, stringsFile));
81
+ }
82
+ }
83
+ return changed;
84
+ }
85
+ /** Replaces one `<string name="x">…</string>` value, escaping XML metacharacters. */
86
+ function replaceStringResource(xml, name, value) {
87
+ const escaped = value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
88
+ const pattern = new RegExp(`(<string\\s+name=(?:"|')${name}(?:"|')\\s*>)([\\s\\S]*?)(</string>)`);
89
+ return xml.replace(pattern, `$1${escaped}$3`);
90
+ }
91
+ function patchIos(input) {
92
+ const iosRoot = path.resolve(input.appDir, input.iosDir);
93
+ const plist = path.join(iosRoot, "App", "App", "Info.plist");
94
+ if (!fs.existsSync(plist))
95
+ return [];
96
+ const appName = readEnv(input.env, "VITE_APP_NAME");
97
+ const version = readEnv(input.env, "VITE_APP_VERSION");
98
+ const build = readEnv(input.env, "BUILD_NUMBER");
99
+ let contents = fs.readFileSync(plist, "utf8");
100
+ const before = contents;
101
+ if (version)
102
+ contents = replacePlistString(contents, "CFBundleShortVersionString", version);
103
+ if (build)
104
+ contents = replacePlistString(contents, "CFBundleVersion", build);
105
+ if (appName)
106
+ contents = replacePlistString(contents, "CFBundleDisplayName", appName);
107
+ if (contents === before)
108
+ return [];
109
+ fs.writeFileSync(plist, contents);
110
+ return [path.relative(input.appDir, plist)];
111
+ }
112
+ function replacePlistString(xml, key, value) {
113
+ const pattern = new RegExp(`(<key>${key}</key>\\s*<string>)([\\s\\S]*?)(</string>)`);
114
+ return xml.replace(pattern, `$1${value}$3`);
115
+ }
116
+ /**
117
+ * The bundle identifier iOS builds from lives in `project.pbxproj`, which is
118
+ * not safely editable with a regex. Trapeze does it properly, so the built-in
119
+ * path reports the limitation instead of pretending to have handled it.
120
+ */
121
+ export function builtinConfigLimitations(platform) {
122
+ if (platform === "ios") {
123
+ return ["the iOS bundle identifier in project.pbxproj is not changed without Trapeze"];
124
+ }
125
+ return ["AndroidManifest permissions declared only in a Trapeze config are not applied"];
126
+ }
127
+ //# sourceMappingURL=native-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-config.js","sourceRoot":"","sources":["../../src/pipeline/native-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Locates the tools the deploy pipeline needs.
3
+ *
4
+ * The old pipeline assumed a great deal: that pnpm was the package manager,
5
+ * that the application defined scripts called `assets:<env>`, `build:<env>` and
6
+ * `trapeze:<env>`, and that `@capgo/cli` could be fetched from the network
7
+ * mid-deploy. Any of those being false failed the deploy halfway through, after
8
+ * the version had already been bumped.
9
+ *
10
+ * Nothing here shells out to a package manager to find a tool. A dependency's
11
+ * executable already lives in `node_modules/.bin`, and in a workspace it lives
12
+ * in the *root* `node_modules/.bin` too - so walking up from the app directory
13
+ * finds it whether the app is standalone or a workspace member.
14
+ */
15
+ export type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
16
+ export interface Toolchain {
17
+ /** Directory the application lives in. */
18
+ appDir: string;
19
+ /** Workspace root, or `appDir` when the app is standalone. */
20
+ workspaceRoot: string;
21
+ packageManager: PackageManager;
22
+ /** True when Vite+ drives this workspace. */
23
+ hasVitePlus: boolean;
24
+ }
25
+ /**
26
+ * Resolves a dependency executable to an absolute path.
27
+ *
28
+ * On Windows the runnable file is `<name>.cmd` (or `.exe`), not `<name>`, so
29
+ * both are probed. Returns null when the tool is not installed - callers decide
30
+ * whether that is fatal or a reason to skip a step.
31
+ */
32
+ export declare function resolveBin(name: string, from: string): string | null;
33
+ /**
34
+ * Detects the workspace root and package manager.
35
+ *
36
+ * Lockfile detection is deliberately last: a `packageManager` field is an
37
+ * explicit declaration, a lockfile is an artefact. When nothing is declared the
38
+ * fallback is npm, which every Node installation has.
39
+ */
40
+ export declare function detectToolchain(appDir: string): Toolchain;
41
+ /** Reads a script out of the application's package.json. */
42
+ export declare function readScript(appDir: string, name: string): string | null;
43
+ /** The argv for running a package.json script with the detected manager. */
44
+ export declare function scriptCommand(toolchain: Toolchain, script: string): {
45
+ file: string;
46
+ args: string[];
47
+ };
48
+ export interface ToolLookup {
49
+ /** Absolute path to the executable, when it is installed. */
50
+ bin: string | null;
51
+ /** Package that provides it, for the "not installed" message. */
52
+ packageName: string;
53
+ }
54
+ /**
55
+ * Tools the pipeline can use. Every one of them is optional: a missing tool
56
+ * makes the CLI skip or substitute that step, never abort the deploy.
57
+ */
58
+ export declare function lookupTools(appDir: string): {
59
+ vite: {
60
+ bin: string | null;
61
+ packageName: string;
62
+ };
63
+ vp: {
64
+ bin: string | null;
65
+ packageName: string;
66
+ };
67
+ capacitor: {
68
+ bin: string | null;
69
+ packageName: string;
70
+ };
71
+ assets: {
72
+ bin: string | null;
73
+ packageName: string;
74
+ };
75
+ trapeze: {
76
+ bin: string | null;
77
+ packageName: string;
78
+ };
79
+ };
80
+ //# sourceMappingURL=toolchain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolchain.d.ts","sourceRoot":"","sources":["../../src/pipeline/toolchain.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,SAAS;IACxB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,cAAc,CAAC;IAC/B,6CAA6C;IAC7C,WAAW,EAAE,OAAO,CAAC;CACtB;AAmBD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWpE;AAgBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAoCzD;AA8BD,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYtE;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,GACb;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAElC;AAED,MAAM,WAAW,UAAU;IACzB,6DAA6D;IAC7D,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;EAczC"}
@@ -0,0 +1,146 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ const BIN_DIR = path.join("node_modules", ".bin");
4
+ /** Directories that could hold a dependency executable, nearest first. */
5
+ function binDirs(from) {
6
+ const dirs = [];
7
+ let current = path.resolve(from);
8
+ for (;;) {
9
+ dirs.push(path.join(current, BIN_DIR));
10
+ const parent = path.dirname(current);
11
+ if (parent === current)
12
+ break;
13
+ current = parent;
14
+ }
15
+ return dirs;
16
+ }
17
+ /**
18
+ * Resolves a dependency executable to an absolute path.
19
+ *
20
+ * On Windows the runnable file is `<name>.cmd` (or `.exe`), not `<name>`, so
21
+ * both are probed. Returns null when the tool is not installed - callers decide
22
+ * whether that is fatal or a reason to skip a step.
23
+ */
24
+ export function resolveBin(name, from) {
25
+ const candidates = process.platform === "win32" ? [`${name}.cmd`, `${name}.exe`, name] : [name];
26
+ for (const dir of binDirs(from)) {
27
+ for (const candidate of candidates) {
28
+ const full = path.join(dir, candidate);
29
+ if (fs.existsSync(full))
30
+ return full;
31
+ }
32
+ }
33
+ return null;
34
+ }
35
+ /** Finds the nearest ancestor containing any of `markers`. */
36
+ function findUp(from, markers) {
37
+ let current = path.resolve(from);
38
+ for (;;) {
39
+ if (markers.some((marker) => fs.existsSync(path.join(current, marker)))) {
40
+ return current;
41
+ }
42
+ const parent = path.dirname(current);
43
+ if (parent === current)
44
+ return null;
45
+ current = parent;
46
+ }
47
+ }
48
+ /**
49
+ * Detects the workspace root and package manager.
50
+ *
51
+ * Lockfile detection is deliberately last: a `packageManager` field is an
52
+ * explicit declaration, a lockfile is an artefact. When nothing is declared the
53
+ * fallback is npm, which every Node installation has.
54
+ */
55
+ export function detectToolchain(appDir) {
56
+ const workspaceRoot = findUp(appDir, [
57
+ "pnpm-workspace.yaml",
58
+ "pnpm-lock.yaml",
59
+ "yarn.lock",
60
+ "bun.lock",
61
+ "bun.lockb",
62
+ "package-lock.json",
63
+ ]) ?? appDir;
64
+ let packageManager = "npm";
65
+ const declared = readPackageManagerField(workspaceRoot);
66
+ if (declared) {
67
+ packageManager = declared;
68
+ }
69
+ else if (fs.existsSync(path.join(workspaceRoot, "pnpm-lock.yaml")) ||
70
+ fs.existsSync(path.join(workspaceRoot, "pnpm-workspace.yaml"))) {
71
+ packageManager = "pnpm";
72
+ }
73
+ else if (fs.existsSync(path.join(workspaceRoot, "yarn.lock"))) {
74
+ packageManager = "yarn";
75
+ }
76
+ else if (fs.existsSync(path.join(workspaceRoot, "bun.lock")) ||
77
+ fs.existsSync(path.join(workspaceRoot, "bun.lockb"))) {
78
+ packageManager = "bun";
79
+ }
80
+ return {
81
+ appDir,
82
+ workspaceRoot,
83
+ packageManager,
84
+ hasVitePlus: resolveBin("vp", appDir) !== null,
85
+ };
86
+ }
87
+ function readPackageManagerField(root) {
88
+ const file = path.join(root, "package.json");
89
+ if (!fs.existsSync(file))
90
+ return null;
91
+ try {
92
+ const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
93
+ const fromField = pkg.packageManager?.split("@")[0];
94
+ if (isPackageManager(fromField))
95
+ return fromField;
96
+ const declared = pkg.devEngines?.packageManager;
97
+ const name = Array.isArray(declared) ? declared[0]?.name : declared?.name;
98
+ if (isPackageManager(name))
99
+ return name;
100
+ }
101
+ catch {
102
+ // A malformed package.json is the app's problem, not a reason to crash
103
+ // during tool detection.
104
+ }
105
+ return null;
106
+ }
107
+ function isPackageManager(value) {
108
+ return value === "pnpm" || value === "npm" || value === "yarn" || value === "bun";
109
+ }
110
+ /** Reads a script out of the application's package.json. */
111
+ export function readScript(appDir, name) {
112
+ const file = path.join(appDir, "package.json");
113
+ if (!fs.existsSync(file))
114
+ return null;
115
+ try {
116
+ const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
117
+ return pkg.scripts?.[name] ?? null;
118
+ }
119
+ catch {
120
+ return null;
121
+ }
122
+ }
123
+ /** The argv for running a package.json script with the detected manager. */
124
+ export function scriptCommand(toolchain, script) {
125
+ return { file: toolchain.packageManager, args: ["run", script] };
126
+ }
127
+ /**
128
+ * Tools the pipeline can use. Every one of them is optional: a missing tool
129
+ * makes the CLI skip or substitute that step, never abort the deploy.
130
+ */
131
+ export function lookupTools(appDir) {
132
+ return {
133
+ vite: { bin: resolveBin("vite", appDir), packageName: "vite" },
134
+ vp: { bin: resolveBin("vp", appDir), packageName: "vite-plus" },
135
+ capacitor: { bin: resolveBin("cap", appDir), packageName: "@capacitor/cli" },
136
+ assets: {
137
+ bin: resolveBin("capacitor-assets", appDir),
138
+ packageName: "@capacitor/assets",
139
+ },
140
+ trapeze: {
141
+ bin: resolveBin("trapeze", appDir),
142
+ packageName: "@trapezedev/configure",
143
+ },
144
+ };
145
+ }
146
+ //# sourceMappingURL=toolchain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolchain.js","sourceRoot":"","sources":["../../src/pipeline/toolchain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface BundleResult {
2
+ zipPath: string;
3
+ fileCount: number;
4
+ byteSize: number;
5
+ }
6
+ export interface BundleOptions {
7
+ /** Directory whose *contents* become the archive root. */
8
+ webDir: string;
9
+ /** Where to write the archive. */
10
+ outFile: string;
11
+ /** Fixed modification time, for reproducible archives. */
12
+ mtime?: Date;
13
+ }
14
+ /** Builds the OTA archive from a built web directory. */
15
+ export declare function createBundleZip(options: BundleOptions): BundleResult;
16
+ /**
17
+ * Names the archive after the app and version rather than dropping a bare
18
+ * `<version>.zip` in the project root, so a stray archive is identifiable and
19
+ * the gitignore rule can match it.
20
+ */
21
+ export declare function bundleFileName(appId: string, version: string): string;
22
+ //# sourceMappingURL=zip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../src/pipeline/zip.ts"],"names":[],"mappings":"AAgHA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,IAAI,CAAC;CACd;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAsGpE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrE"}
@@ -0,0 +1,188 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import zlib from "node:zlib";
4
+ /**
5
+ * Writes the OTA bundle archive.
6
+ *
7
+ * The pipeline used to run `npx @capgo/cli bundle zip <appId> --json` for this,
8
+ * which meant a deploy could not run offline, depended on a third-party CLI
9
+ * resolved at deploy time, and dropped the archive somewhere in the project
10
+ * root - after which `findLatestZip` picked *the newest .zip in the directory*,
11
+ * whatever it was, and deleted it on success.
12
+ *
13
+ * The archive format is dictated by `@capgo/capacitor-updater`, which unpacks
14
+ * it on the device. Two of its rules are easy to break and fail only on a real
15
+ * phone:
16
+ *
17
+ * 1. Entry names must use forward slashes. The Android unzip rejects any entry
18
+ * containing a backslash outright ("Windows path not supported"), so a
19
+ * naive `path.join` on Windows produces an archive that installs nowhere.
20
+ * 2. After unpacking, if the extracted directory holds exactly one entry and
21
+ * that entry is not `index.html`, the plugin treats it as a wrapper and
22
+ * descends into it. Writing the web assets at the archive root - which is
23
+ * what this does - keeps that logic out of the picture entirely.
24
+ *
25
+ * The plugin also validates that `index.html` exists at the bundle root, so
26
+ * that is checked before anything is written.
27
+ */
28
+ const LOCAL_HEADER = 0x04_03_4b_50;
29
+ const CENTRAL_HEADER = 0x02_01_4b_50;
30
+ const END_OF_CENTRAL_DIR = 0x06_05_4b_50;
31
+ const ZIP_VERSION = 20; // 2.0 - deflate
32
+ const DEFLATED = 8;
33
+ const MAX_ZIP_SIZE = 0xff_ff_ff_ff; // 4 GiB - beyond this ZIP64 is required.
34
+ /** Files that must never reach a device. */
35
+ const EXCLUDED = new Set([".DS_Store", "Thumbs.db", ".gitkeep", "capuchoo-deploy.log"]);
36
+ const CRC_TABLE = buildCrcTable();
37
+ function buildCrcTable() {
38
+ const table = new Int32Array(256);
39
+ for (let i = 0; i < 256; i++) {
40
+ let c = i;
41
+ for (let k = 0; k < 8; k++) {
42
+ c = c & 1 ? 0xed_b8_83_20 ^ (c >>> 1) : c >>> 1;
43
+ }
44
+ table[i] = c;
45
+ }
46
+ return table;
47
+ }
48
+ function crc32(buffer) {
49
+ let crc = -1;
50
+ for (const byte of buffer) {
51
+ crc = (crc >>> 8) ^ CRC_TABLE[(crc ^ byte) & 0xff];
52
+ }
53
+ return (crc ^ -1) >>> 0;
54
+ }
55
+ /**
56
+ * Encodes a timestamp as MS-DOS date and time.
57
+ *
58
+ * A fixed timestamp keeps the archive byte-for-byte reproducible: rebuilding
59
+ * the same bundle twice produces the same checksum, so the backend can tell a
60
+ * genuine change from a rebuild.
61
+ */
62
+ function dosDateTime(date) {
63
+ const time = (Math.floor(date.getSeconds() / 2) & 0x1f) |
64
+ ((date.getMinutes() & 0x3f) << 5) |
65
+ ((date.getHours() & 0x1f) << 11);
66
+ const day = (date.getDate() & 0x1f) |
67
+ (((date.getMonth() + 1) & 0x0f) << 5) |
68
+ (((date.getFullYear() - 1980) & 0x7f) << 9);
69
+ return { time, date: day };
70
+ }
71
+ /** Collects files under `root`, depth first, with forward-slash names. */
72
+ function collect(root, prefix = "") {
73
+ const entries = [];
74
+ for (const item of fs
75
+ .readdirSync(root, { withFileTypes: true })
76
+ .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))) {
77
+ if (EXCLUDED.has(item.name))
78
+ continue;
79
+ const absolute = path.join(root, item.name);
80
+ // Built with "/" explicitly rather than path.join, which would emit "\"
81
+ // on Windows and produce an archive the Android plugin refuses.
82
+ const name = prefix ? `${prefix}/${item.name}` : item.name;
83
+ if (item.isDirectory()) {
84
+ entries.push(...collect(absolute, name));
85
+ }
86
+ else if (item.isFile()) {
87
+ entries.push({ name, source: absolute });
88
+ }
89
+ // Symlinks are skipped: the plugin has no way to reproduce them and
90
+ // following one could pull in files from outside the web directory.
91
+ }
92
+ return entries;
93
+ }
94
+ /** Builds the OTA archive from a built web directory. */
95
+ export function createBundleZip(options) {
96
+ const { webDir, outFile } = options;
97
+ if (!fs.existsSync(webDir)) {
98
+ throw new Error(`Web directory "${webDir}" does not exist. The build step produced nothing to publish.`);
99
+ }
100
+ if (!fs.existsSync(path.join(webDir, "index.html"))) {
101
+ throw new Error(`"${webDir}" has no index.html at its root. ` +
102
+ "@capgo/capacitor-updater rejects a bundle without one, so this archive " +
103
+ "would download on every device and then fail to apply.");
104
+ }
105
+ const entries = collect(webDir);
106
+ if (entries.length === 0) {
107
+ throw new Error(`"${webDir}" is empty, so there is nothing to publish.`);
108
+ }
109
+ // 1980-01-01, the earliest representable MS-DOS timestamp.
110
+ const stamp = dosDateTime(options.mtime ?? new Date(Date.UTC(1980, 0, 1)));
111
+ const localParts = [];
112
+ const centralParts = [];
113
+ let offset = 0;
114
+ for (const entry of entries) {
115
+ const contents = fs.readFileSync(entry.source);
116
+ const compressed = zlib.deflateRawSync(contents, { level: 9 });
117
+ const nameBytes = Buffer.from(entry.name, "utf8");
118
+ const crc = crc32(contents);
119
+ const local = Buffer.alloc(30);
120
+ local.writeUInt32LE(LOCAL_HEADER, 0);
121
+ local.writeUInt16LE(ZIP_VERSION, 4);
122
+ // Bit 11 marks the name as UTF-8, which matters for non-ASCII asset names.
123
+ local.writeUInt16LE(0x08_00, 6);
124
+ local.writeUInt16LE(DEFLATED, 8);
125
+ local.writeUInt16LE(stamp.time, 10);
126
+ local.writeUInt16LE(stamp.date, 12);
127
+ local.writeUInt32LE(crc, 14);
128
+ local.writeUInt32LE(compressed.length, 18);
129
+ local.writeUInt32LE(contents.length, 22);
130
+ local.writeUInt16LE(nameBytes.length, 26);
131
+ local.writeUInt16LE(0, 28);
132
+ localParts.push(local, nameBytes, compressed);
133
+ const central = Buffer.alloc(46);
134
+ central.writeUInt32LE(CENTRAL_HEADER, 0);
135
+ central.writeUInt16LE(ZIP_VERSION, 4);
136
+ central.writeUInt16LE(ZIP_VERSION, 6);
137
+ central.writeUInt16LE(0x08_00, 8);
138
+ central.writeUInt16LE(DEFLATED, 10);
139
+ central.writeUInt16LE(stamp.time, 12);
140
+ central.writeUInt16LE(stamp.date, 14);
141
+ central.writeUInt32LE(crc, 16);
142
+ central.writeUInt32LE(compressed.length, 20);
143
+ central.writeUInt32LE(contents.length, 24);
144
+ central.writeUInt16LE(nameBytes.length, 28);
145
+ central.writeUInt16LE(0, 30); // extra
146
+ central.writeUInt16LE(0, 32); // comment
147
+ central.writeUInt16LE(0, 34); // disk number
148
+ central.writeUInt16LE(0, 36); // internal attributes
149
+ // Regular file, mode 0644, in the high word where Unix permissions live.
150
+ // `>>> 0` is required: the shift alone overflows into a negative int32,
151
+ // which writeUInt32LE rejects.
152
+ central.writeUInt32LE((0o10_0644 << 16) >>> 0, 38);
153
+ central.writeUInt32LE(offset, 42);
154
+ centralParts.push(central, nameBytes);
155
+ offset += local.length + nameBytes.length + compressed.length;
156
+ if (offset > MAX_ZIP_SIZE) {
157
+ throw new Error("The web bundle exceeds 4 GiB, which needs ZIP64. Reduce the bundle size.");
158
+ }
159
+ }
160
+ const centralDirectory = Buffer.concat(centralParts);
161
+ const end = Buffer.alloc(22);
162
+ end.writeUInt32LE(END_OF_CENTRAL_DIR, 0);
163
+ end.writeUInt16LE(0, 4); // this disk
164
+ end.writeUInt16LE(0, 6); // disk with central directory
165
+ end.writeUInt16LE(entries.length, 8);
166
+ end.writeUInt16LE(entries.length, 10);
167
+ end.writeUInt32LE(centralDirectory.length, 12);
168
+ end.writeUInt32LE(offset, 16);
169
+ end.writeUInt16LE(0, 20); // comment length
170
+ const archive = Buffer.concat([...localParts, centralDirectory, end]);
171
+ fs.mkdirSync(path.dirname(outFile), { recursive: true });
172
+ fs.writeFileSync(outFile, archive);
173
+ return {
174
+ zipPath: outFile,
175
+ fileCount: entries.length,
176
+ byteSize: archive.length,
177
+ };
178
+ }
179
+ /**
180
+ * Names the archive after the app and version rather than dropping a bare
181
+ * `<version>.zip` in the project root, so a stray archive is identifiable and
182
+ * the gitignore rule can match it.
183
+ */
184
+ export function bundleFileName(appId, version) {
185
+ const safe = `${appId}-${version}`.replaceAll(/[^\w.-]/g, "-");
186
+ return `capuchoo-bundle-${safe}.zip`;
187
+ }
188
+ //# sourceMappingURL=zip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip.js","sourceRoot":"","sources":["../../src/pipeline/zip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,YAAY,GAAG,aAAa,CAAC;AACnC,MAAM,cAAc,GAAG,aAAa,CAAC;AACrC,MAAM,kBAAkB,GAAG,aAAa,CAAC;AACzC,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,gBAAgB;AACxC,MAAM,QAAQ,GAAG,CAAC,CAAC;AACnB,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,yCAAyC;AAE7E,4CAA4C;AAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC;AAExF,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;AAElC,SAAS,aAAa;IACpB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;QACD,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,KAAK,CAAC,MAAc;IAC3B,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAE,CAAC;IACtD,CAAC;IACD,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,SAAS,WAAW,CAAC,IAAU;IAC7B,MAAM,IAAI,GACR,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;QAC1C,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACnC,MAAM,GAAG,GACP,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;QACvB,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAC7B,CAAC;AAQD,0EAA0E;AAC1E,SAAS,OAAO,CAAC,IAAY,EAAE,MAAM,GAAG,EAAE;IACxC,MAAM,OAAO,GAAY,EAAE,CAAC;IAE5B,KAAK,MAAM,IAAI,IAAI,EAAE;SAClB,WAAW,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SAC1C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAEtC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,wEAAwE;QACxE,gEAAgE;QAChE,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAE3D,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3C,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,oEAAoE;QACpE,oEAAoE;IACtE,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAiBD,yDAAyD;AACzD,MAAM,UAAU,eAAe,CAAC,OAAsB;IACpD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAEpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,+DAA+D,CACxF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACb,IAAI,MAAM,mCAAmC;YAC3C,yEAAyE;YACzE,wDAAwD,CAC3D,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,IAAI,MAAM,6CAA6C,CAAC,CAAC;IAC3E,CAAC;IAED,2DAA2D;IAC3D,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3E,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QAE5B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/B,KAAK,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QACrC,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACpC,2EAA2E;QAC3E,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAChC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACjC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpC,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC7B,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3C,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACzC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAE3B,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAE9C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjC,OAAO,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACtC,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACtC,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAClC,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/B,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ;QACtC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;QACxC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc;QAC5C,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB;QACpD,yEAAyE;QACzE,wEAAwE;QACxE,+BAA+B;QAC/B,OAAO,CAAC,aAAa,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAElC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAEtC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;QAC9D,IAAI,MAAM,GAAG,YAAY,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7B,GAAG,CAAC,aAAa,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;IACzC,GAAG,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY;IACrC,GAAG,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,8BAA8B;IACvD,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACrC,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACtC,GAAG,CAAC,aAAa,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/C,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC9B,GAAG,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB;IAE3C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,EAAE,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC;IAEtE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAEnC,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,OAAO,CAAC,MAAM;QACzB,QAAQ,EAAE,OAAO,CAAC,MAAM;KACzB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAG,GAAG,KAAK,IAAI,OAAO,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAC/D,OAAO,mBAAmB,IAAI,MAAM,CAAC;AACvC,CAAC"}