@cats-inc/cats-platform 0.1.1 → 0.1.5
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/.env.example +2 -2
- package/README.md +6 -0
- package/build/desktop/bootstrapPage.d.ts.map +1 -1
- package/build/desktop/bootstrapPage.js +81 -4
- package/build/desktop/bootstrapPage.js.map +1 -1
- package/build/desktop/config.d.ts +11 -1
- package/build/desktop/config.d.ts.map +1 -1
- package/build/desktop/config.js +5 -2
- package/build/desktop/config.js.map +1 -1
- package/build/desktop/contracts.d.ts +66 -11
- package/build/desktop/contracts.d.ts.map +1 -1
- package/build/desktop/contracts.js +50 -1
- package/build/desktop/contracts.js.map +1 -1
- package/build/desktop/hostState.d.ts +4 -3
- package/build/desktop/hostState.d.ts.map +1 -1
- package/build/desktop/hostState.js +22 -30
- package/build/desktop/hostState.js.map +1 -1
- package/build/desktop/hostVersion.d.ts +1 -0
- package/build/desktop/hostVersion.d.ts.map +1 -1
- package/build/desktop/hostVersion.js +29 -5
- package/build/desktop/hostVersion.js.map +1 -1
- package/build/desktop/main.js +234 -37
- package/build/desktop/main.js.map +1 -1
- package/build/desktop/packaging.d.ts.map +1 -1
- package/build/desktop/packaging.js +10 -4
- package/build/desktop/packaging.js.map +1 -1
- package/build/desktop/preload.cjs +29 -0
- package/build/desktop/preload.cjs.map +1 -1
- package/build/desktop/processSupervisor.d.ts +2 -0
- package/build/desktop/processSupervisor.d.ts.map +1 -1
- package/build/desktop/processSupervisor.js +28 -13
- package/build/desktop/processSupervisor.js.map +1 -1
- package/build/desktop/readiness.d.ts +2 -2
- package/build/desktop/readiness.d.ts.map +1 -1
- package/build/desktop/readiness.js +2 -2
- package/build/desktop/readiness.js.map +1 -1
- package/build/desktop/releaseDescriptor.d.ts +85 -0
- package/build/desktop/releaseDescriptor.d.ts.map +1 -0
- package/build/desktop/releaseDescriptor.js +246 -0
- package/build/desktop/releaseDescriptor.js.map +1 -0
- package/build/desktop/tray.d.ts +1 -0
- package/build/desktop/tray.d.ts.map +1 -1
- package/build/desktop/tray.js +26 -0
- package/build/desktop/tray.js.map +1 -1
- package/build/desktop/trayMenu.d.ts +22 -1
- package/build/desktop/trayMenu.d.ts.map +1 -1
- package/build/desktop/trayMenu.js +61 -0
- package/build/desktop/trayMenu.js.map +1 -1
- package/build/desktop/updateInstallHandoff.d.ts +30 -0
- package/build/desktop/updateInstallHandoff.d.ts.map +1 -0
- package/build/desktop/updateInstallHandoff.js +39 -0
- package/build/desktop/updateInstallHandoff.js.map +1 -0
- package/build/desktop/updateIpc.d.ts +42 -0
- package/build/desktop/updateIpc.d.ts.map +1 -0
- package/build/desktop/updateIpc.js +71 -0
- package/build/desktop/updateIpc.js.map +1 -0
- package/build/desktop/updateManager.d.ts +76 -0
- package/build/desktop/updateManager.d.ts.map +1 -0
- package/build/desktop/updateManager.js +342 -0
- package/build/desktop/updateManager.js.map +1 -0
- package/build/desktop/updateNotifications.d.ts +64 -0
- package/build/desktop/updateNotifications.d.ts.map +1 -0
- package/build/desktop/updateNotifications.js +143 -0
- package/build/desktop/updateNotifications.js.map +1 -0
- package/build/desktop/updaterAdapter.d.ts +72 -0
- package/build/desktop/updaterAdapter.d.ts.map +1 -0
- package/build/desktop/updaterAdapter.js +198 -0
- package/build/desktop/updaterAdapter.js.map +1 -0
- package/build/renderer/assets/{ActiveSessionPermissionChip-BYr8cDpb.js → ActiveSessionPermissionChip-BoDkKkmi.js} +1 -1
- package/build/renderer/assets/{App-BbuTWT6Y.js → App-Bs1eRarv.js} +1 -1
- package/build/renderer/assets/{App-B13AzNko.js → App-C4S1Wa9f.js} +1 -1
- package/build/renderer/assets/{App-n-RtGh42.js → App-CNJj5gi9.js} +1 -1
- package/build/renderer/assets/{WorkspaceAppRoutes-BktWrQK-.js → WorkspaceAppRoutes-CFAuhWGF.js} +1 -1
- package/build/renderer/assets/app-uJJx-k1S.js +43 -0
- package/build/renderer/assets/{conversationSidebarRecentEntries-BNPz3X1V.js → conversationSidebarRecentEntries-CPGopayy.js} +1 -1
- package/build/renderer/assets/{useDraftSessionChips-3z_Je4ju.js → useDraftSessionChips-BsOdYfWw.js} +1 -1
- package/build/renderer/index.html +1 -1
- package/build/server/app/renderer/settings/settingsDesktopErrorLabels.d.ts +5 -0
- package/build/server/app/renderer/settings/settingsDesktopErrorLabels.d.ts.map +1 -0
- package/build/server/app/renderer/settings/settingsDesktopErrorLabels.js +16 -0
- package/build/server/app/renderer/settings/settingsDesktopErrorLabels.js.map +1 -0
- package/build/server/app/renderer/settings/settingsDesktopPreferences.d.ts +11 -0
- package/build/server/app/renderer/settings/settingsDesktopPreferences.d.ts.map +1 -0
- package/build/server/app/renderer/settings/settingsDesktopPreferences.js +30 -0
- package/build/server/app/renderer/settings/settingsDesktopPreferences.js.map +1 -0
- package/build/server/app/renderer/settings/settingsDesktopUpdateLabels.d.ts +31 -0
- package/build/server/app/renderer/settings/settingsDesktopUpdateLabels.d.ts.map +1 -0
- package/build/server/app/renderer/settings/settingsDesktopUpdateLabels.js +101 -0
- package/build/server/app/renderer/settings/settingsDesktopUpdateLabels.js.map +1 -0
- package/build/server/app/server/index.js +1 -1
- package/build/server/app/server/index.js.map +1 -1
- package/build/server/app/server/platformSetupRoutes.d.ts.map +1 -1
- package/build/server/app/server/platformSetupRoutes.js +42 -5
- package/build/server/app/server/platformSetupRoutes.js.map +1 -1
- package/build/server/app/server/requestRouter.d.ts.map +1 -1
- package/build/server/app/server/requestRouter.js +2 -0
- package/build/server/app/server/requestRouter.js.map +1 -1
- package/build/server/design/components/runtimeChips.d.ts +1 -1
- package/build/server/design/components/runtimeChips.d.ts.map +1 -1
- package/build/server/design/components/runtimeChips.js +4 -1
- package/build/server/design/components/runtimeChips.js.map +1 -1
- package/build/server/index.js +12 -1
- package/build/server/index.js.map +1 -1
- package/build/server/platform/auth/sessionSecretProvisioning.d.ts +23 -0
- package/build/server/platform/auth/sessionSecretProvisioning.d.ts.map +1 -0
- package/build/server/platform/auth/sessionSecretProvisioning.js +291 -0
- package/build/server/platform/auth/sessionSecretProvisioning.js.map +1 -0
- package/build/server/products/code/livePreview/realProcessAdapter.d.ts.map +1 -1
- package/build/server/products/code/livePreview/realProcessAdapter.js +7 -1
- package/build/server/products/code/livePreview/realProcessAdapter.js.map +1 -1
- package/build/server/products/code/state/appExport.d.ts.map +1 -1
- package/build/server/products/code/state/appExport.js +2 -0
- package/build/server/products/code/state/appExport.js.map +1 -1
- package/build/server/shared/desktopRecoveryBridge.d.ts +46 -0
- package/build/server/shared/desktopRecoveryBridge.d.ts.map +1 -1
- package/build/server/shared/desktopRecoveryBridge.js +20 -0
- package/build/server/shared/desktopRecoveryBridge.js.map +1 -1
- package/build/server/shared/i18n/catalogs/en.d.ts.map +1 -1
- package/build/server/shared/i18n/catalogs/en.js +37 -0
- package/build/server/shared/i18n/catalogs/en.js.map +1 -1
- package/build/server/shared/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/build/server/shared/i18n/catalogs/zh-TW.js +35 -0
- package/build/server/shared/i18n/catalogs/zh-TW.js.map +1 -1
- package/build/server/shared/i18n/index.d.ts +35 -0
- package/build/server/shared/i18n/index.d.ts.map +1 -1
- package/build/server/shared/i18n/messageKeys.d.ts +35 -0
- package/build/server/shared/i18n/messageKeys.d.ts.map +1 -1
- package/build/server/shared/i18n/messageKeys.js +35 -0
- package/build/server/shared/i18n/messageKeys.js.map +1 -1
- package/build/server/shared/loadProjectEnvFile.d.ts.map +1 -1
- package/build/server/shared/loadProjectEnvFile.js +18 -19
- package/build/server/shared/loadProjectEnvFile.js.map +1 -1
- package/build/server/shared/platformChildProcessEnv.d.ts +2 -0
- package/build/server/shared/platformChildProcessEnv.d.ts.map +1 -0
- package/build/server/shared/platformChildProcessEnv.js +22 -0
- package/build/server/shared/platformChildProcessEnv.js.map +1 -0
- package/package.json +19 -27
- package/scripts/build-desktop-installer.mjs +438 -37
- package/scripts/build-test-ui.mjs +13 -2
- package/scripts/generate-desktop-release-descriptor.mjs +258 -0
- package/scripts/validate-release-assets.mjs +422 -0
- package/scripts/validate-release-version.mjs +217 -0
- package/scripts/windows/Test-WindowsInstallerSmoke.ps1 +55 -1
- package/build/desktop/update.d.ts +0 -24
- package/build/desktop/update.d.ts.map +0 -1
- package/build/desktop/update.js +0 -173
- package/build/desktop/update.js.map +0 -1
- package/build/renderer/assets/app-DnVQMpW_.js +0 -43
- package/build/server/app/renderer/settings/settingsDesktopStartupErrorLabels.d.ts +0 -5
- package/build/server/app/renderer/settings/settingsDesktopStartupErrorLabels.d.ts.map +0 -1
- package/build/server/app/renderer/settings/settingsDesktopStartupErrorLabels.js +0 -11
- package/build/server/app/renderer/settings/settingsDesktopStartupErrorLabels.js.map +0 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//
|
|
3
|
+
// Script: validate-release-version.mjs
|
|
4
|
+
// Description: Guard that a desktop release tag matches the package version in
|
|
5
|
+
// both package.json and package-lock.json before any platform
|
|
6
|
+
// build work starts.
|
|
7
|
+
//
|
|
8
|
+
// Usage: node scripts/validate-release-version.mjs [--tag <vX.Y.Z>]
|
|
9
|
+
//
|
|
10
|
+
// Options:
|
|
11
|
+
// --tag <vX.Y.Z> Release tag to validate. Defaults to GITHUB_REF_NAME.
|
|
12
|
+
// --json Emit the machine-readable result instead of prose.
|
|
13
|
+
// --help Show this help text.
|
|
14
|
+
//
|
|
15
|
+
// Exit codes:
|
|
16
|
+
// 0 the tag is a stable release tag and every version source agrees
|
|
17
|
+
// 1 the tag is malformed, missing, or disagrees with a version source
|
|
18
|
+
|
|
19
|
+
import process from 'node:process';
|
|
20
|
+
import { readFile } from 'node:fs/promises';
|
|
21
|
+
import { dirname, resolve } from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
|
|
24
|
+
const SCRIPT_PATH = fileURLToPath(import.meta.url);
|
|
25
|
+
const PROJECT_ROOT = resolve(dirname(SCRIPT_PATH), '..');
|
|
26
|
+
|
|
27
|
+
// SPEC-111 section 7 restricts Phase 1 releases to stable vMAJOR.MINOR.PATCH
|
|
28
|
+
// tags. Prerelease channel publishing is deferred until promotion and
|
|
29
|
+
// downgrade rules exist, so a suffix is rejected rather than silently
|
|
30
|
+
// accepted as stable.
|
|
31
|
+
const STABLE_RELEASE_TAG = /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
32
|
+
|
|
33
|
+
function printHelp() {
|
|
34
|
+
process.stdout.write(`Usage: node scripts/validate-release-version.mjs [options]
|
|
35
|
+
|
|
36
|
+
Options:
|
|
37
|
+
--tag <vX.Y.Z> Release tag to validate. Defaults to GITHUB_REF_NAME.
|
|
38
|
+
--json Emit the machine-readable result instead of prose.
|
|
39
|
+
--help Show this help text.
|
|
40
|
+
|
|
41
|
+
Validates that a stable desktop release tag matches the version recorded in
|
|
42
|
+
package.json, the package-lock.json root version, and the package-lock.json
|
|
43
|
+
root package entry.
|
|
44
|
+
`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function parseArgs(argv, env = process.env) {
|
|
48
|
+
let tag = typeof env.GITHUB_REF_NAME === 'string' ? env.GITHUB_REF_NAME.trim() : '';
|
|
49
|
+
let json = false;
|
|
50
|
+
|
|
51
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
52
|
+
const value = argv[index];
|
|
53
|
+
if (value === '--help' || value === '-h') {
|
|
54
|
+
return { help: true, tag, json };
|
|
55
|
+
}
|
|
56
|
+
if (value === '--tag') {
|
|
57
|
+
tag = (argv[index + 1] ?? '').trim();
|
|
58
|
+
index += 1;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (value === '--json') {
|
|
62
|
+
json = true;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
throw new Error(`Unknown option: ${value}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { help: false, tag, json };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function parseStableReleaseTag(tag) {
|
|
72
|
+
const candidate = typeof tag === 'string' ? tag.trim() : '';
|
|
73
|
+
|
|
74
|
+
if (candidate === '') {
|
|
75
|
+
return {
|
|
76
|
+
ok: false,
|
|
77
|
+
code: 'tag_missing',
|
|
78
|
+
message: 'No release tag was supplied. Pass --tag vX.Y.Z or set GITHUB_REF_NAME.',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!STABLE_RELEASE_TAG.test(candidate)) {
|
|
83
|
+
return {
|
|
84
|
+
ok: false,
|
|
85
|
+
code: 'tag_malformed',
|
|
86
|
+
message: `Release tag '${candidate}' is not a stable vMAJOR.MINOR.PATCH tag.`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { ok: true, tag: candidate, version: candidate.slice(1) };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Compares the tag version against every version source a release change is
|
|
95
|
+
* required to update. Returns one problem per disagreeing source so the
|
|
96
|
+
* operator sees the complete picture instead of only the first mismatch.
|
|
97
|
+
*/
|
|
98
|
+
export function collectVersionProblems({ version, packageJson, packageLockJson }) {
|
|
99
|
+
const problems = [];
|
|
100
|
+
|
|
101
|
+
const packageVersion = packageJson?.version;
|
|
102
|
+
if (typeof packageVersion !== 'string' || packageVersion.trim() === '') {
|
|
103
|
+
problems.push({
|
|
104
|
+
code: 'package_version_missing',
|
|
105
|
+
message: 'package.json does not declare a version.',
|
|
106
|
+
});
|
|
107
|
+
} else if (packageVersion !== version) {
|
|
108
|
+
problems.push({
|
|
109
|
+
code: 'package_version_mismatch',
|
|
110
|
+
message: `package.json version '${packageVersion}' does not equal tag version '${version}'.`,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const lockVersion = packageLockJson?.version;
|
|
115
|
+
if (typeof lockVersion !== 'string' || lockVersion.trim() === '') {
|
|
116
|
+
problems.push({
|
|
117
|
+
code: 'lock_version_missing',
|
|
118
|
+
message: 'package-lock.json does not declare a root version.',
|
|
119
|
+
});
|
|
120
|
+
} else if (lockVersion !== version) {
|
|
121
|
+
problems.push({
|
|
122
|
+
code: 'lock_version_mismatch',
|
|
123
|
+
message: `package-lock.json version '${lockVersion}' does not equal tag version '${version}'.`,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// npm records the root package a second time under packages[""]. A hand
|
|
128
|
+
// edited package.json leaves this entry stale, which would otherwise ship a
|
|
129
|
+
// release whose lockfile still advertises the previous version.
|
|
130
|
+
const lockRootVersion = packageLockJson?.packages?.['']?.version;
|
|
131
|
+
if (typeof lockRootVersion !== 'string' || lockRootVersion.trim() === '') {
|
|
132
|
+
problems.push({
|
|
133
|
+
code: 'lock_root_version_missing',
|
|
134
|
+
message: 'package-lock.json does not declare packages[""].version.',
|
|
135
|
+
});
|
|
136
|
+
} else if (lockRootVersion !== version) {
|
|
137
|
+
problems.push({
|
|
138
|
+
code: 'lock_root_version_mismatch',
|
|
139
|
+
message: `package-lock.json packages[""].version '${lockRootVersion}' does not equal `
|
|
140
|
+
+ `tag version '${version}'.`,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return problems;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function validateReleaseVersion({ tag, packageJson, packageLockJson }) {
|
|
148
|
+
const parsedTag = parseStableReleaseTag(tag);
|
|
149
|
+
if (!parsedTag.ok) {
|
|
150
|
+
return { ok: false, tag: null, version: null, problems: [parsedTag] };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const problems = collectVersionProblems({
|
|
154
|
+
version: parsedTag.version,
|
|
155
|
+
packageJson,
|
|
156
|
+
packageLockJson,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
ok: problems.length === 0,
|
|
161
|
+
tag: parsedTag.tag,
|
|
162
|
+
version: parsedTag.version,
|
|
163
|
+
problems,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function readJsonFile(path) {
|
|
168
|
+
const contents = await readFile(path, 'utf8');
|
|
169
|
+
return JSON.parse(contents);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export async function readVersionSources(projectRoot = PROJECT_ROOT) {
|
|
173
|
+
const [packageJson, packageLockJson] = await Promise.all([
|
|
174
|
+
readJsonFile(resolve(projectRoot, 'package.json')),
|
|
175
|
+
readJsonFile(resolve(projectRoot, 'package-lock.json')),
|
|
176
|
+
]);
|
|
177
|
+
|
|
178
|
+
return { packageJson, packageLockJson };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function main() {
|
|
182
|
+
const parsed = parseArgs(process.argv.slice(2));
|
|
183
|
+
if (parsed.help) {
|
|
184
|
+
printHelp();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const { packageJson, packageLockJson } = await readVersionSources();
|
|
189
|
+
const result = validateReleaseVersion({
|
|
190
|
+
tag: parsed.tag,
|
|
191
|
+
packageJson,
|
|
192
|
+
packageLockJson,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
if (parsed.json) {
|
|
196
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
197
|
+
} else if (result.ok) {
|
|
198
|
+
process.stdout.write(
|
|
199
|
+
`[validate-release-version] ${result.tag} matches package version ${result.version}.\n`,
|
|
200
|
+
);
|
|
201
|
+
} else {
|
|
202
|
+
for (const problem of result.problems) {
|
|
203
|
+
process.stderr.write(`[validate-release-version] ${problem.code}: ${problem.message}\n`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (!result.ok) {
|
|
208
|
+
process.exitCode = 1;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (resolve(process.argv[1] ?? '') === SCRIPT_PATH) {
|
|
213
|
+
void main().catch((error) => {
|
|
214
|
+
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
|
|
215
|
+
process.exitCode = 1;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
Checks that the installed Electron host, bundled Cats sidecar, bundled
|
|
7
7
|
cats-runtime sidecar, and packaged installer manifest are all present. By
|
|
8
8
|
default it then launches the installed app, waits for the desktop-host
|
|
9
|
-
state file to be refreshed, and validates the persisted readiness snapshot
|
|
9
|
+
state file to be refreshed, and validates the persisted readiness snapshot
|
|
10
|
+
plus first-run authentication-secret provisioning.
|
|
10
11
|
|
|
11
12
|
.PARAMETER InstallRoot
|
|
12
13
|
The installed Cats directory. Defaults to the NSIS per-user install path.
|
|
@@ -14,6 +15,10 @@
|
|
|
14
15
|
.PARAMETER HostStatePath
|
|
15
16
|
The persisted desktop-host state file written by the installed app.
|
|
16
17
|
|
|
18
|
+
.PARAMETER PlatformDir
|
|
19
|
+
The platform state/config root. Defaults to CATS_PLATFORM_DIR when set,
|
|
20
|
+
otherwise to the platform sibling inferred from HostStatePath.
|
|
21
|
+
|
|
17
22
|
.PARAMETER TimeoutSeconds
|
|
18
23
|
Maximum time to wait for the installed app to refresh the host-state file.
|
|
19
24
|
|
|
@@ -36,6 +41,7 @@
|
|
|
36
41
|
param(
|
|
37
42
|
[string]$InstallRoot = '',
|
|
38
43
|
[string]$HostStatePath = '',
|
|
44
|
+
[string]$PlatformDir = '',
|
|
39
45
|
[ValidateRange(5, 300)]
|
|
40
46
|
[int]$TimeoutSeconds = 60,
|
|
41
47
|
[switch]$SkipLaunch,
|
|
@@ -58,9 +64,47 @@ function Resolve-DefaultInstallRoot {
|
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
function Resolve-DefaultHostStatePath {
|
|
67
|
+
if (-not [string]::IsNullOrWhiteSpace($env:CATS_DESKTOP_DIR)) {
|
|
68
|
+
return Join-Path $env:CATS_DESKTOP_DIR 'state.json'
|
|
69
|
+
}
|
|
61
70
|
return Join-Path $env:USERPROFILE '.cats\desktop\state.json'
|
|
62
71
|
}
|
|
63
72
|
|
|
73
|
+
function Resolve-DefaultPlatformDir([string]$StatePath) {
|
|
74
|
+
if (-not [string]::IsNullOrWhiteSpace($env:CATS_PLATFORM_DIR)) {
|
|
75
|
+
return $env:CATS_PLATFORM_DIR
|
|
76
|
+
}
|
|
77
|
+
$desktopDir = Split-Path -Parent $StatePath
|
|
78
|
+
$catsRoot = Split-Path -Parent $desktopDir
|
|
79
|
+
return Join-Path $catsRoot 'platform'
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function Test-AuthSessionSecretProvisioned {
|
|
83
|
+
param(
|
|
84
|
+
[string]$ResolvedPlatformDir,
|
|
85
|
+
[string]$ResolvedDesktopDir
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
$generatedSecretPath = Join-Path $ResolvedPlatformDir 'config\auth-session-secret.local'
|
|
89
|
+
if (Test-Path -LiteralPath $generatedSecretPath -PathType Leaf) {
|
|
90
|
+
$generatedSecret = (Get-Content -LiteralPath $generatedSecretPath -Raw).Trim()
|
|
91
|
+
if ($generatedSecret.Length -ge 32 -and $generatedSecret -notmatch '\s') {
|
|
92
|
+
return $true
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (-not [string]::IsNullOrWhiteSpace($env:CATS_AUTH_SESSION_SECRET)) {
|
|
97
|
+
return $true
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
$desktopEnvPath = Join-Path $ResolvedDesktopDir '.env'
|
|
101
|
+
if (-not (Test-Path -LiteralPath $desktopEnvPath -PathType Leaf)) {
|
|
102
|
+
return $false
|
|
103
|
+
}
|
|
104
|
+
return [bool](Select-String -LiteralPath $desktopEnvPath `
|
|
105
|
+
-Pattern '^\s*CATS_AUTH_SESSION_SECRET\s*=\s*\S+' -Quiet)
|
|
106
|
+
}
|
|
107
|
+
|
|
64
108
|
function Assert-FileExists([string]$Path, [string]$Label) {
|
|
65
109
|
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
|
|
66
110
|
throw "Missing $Label at $Path"
|
|
@@ -121,6 +165,12 @@ function Assert-True([bool]$Condition, [string]$Message) {
|
|
|
121
165
|
|
|
122
166
|
$resolvedInstallRoot = if ($InstallRoot) { $InstallRoot } else { Resolve-DefaultInstallRoot }
|
|
123
167
|
$resolvedHostStatePath = if ($HostStatePath) { $HostStatePath } else { Resolve-DefaultHostStatePath }
|
|
168
|
+
$resolvedPlatformDir = if ($PlatformDir) {
|
|
169
|
+
$PlatformDir
|
|
170
|
+
} else {
|
|
171
|
+
Resolve-DefaultPlatformDir -StatePath $resolvedHostStatePath
|
|
172
|
+
}
|
|
173
|
+
$resolvedDesktopDir = Split-Path -Parent $resolvedHostStatePath
|
|
124
174
|
$exePath = Join-Path $resolvedInstallRoot 'Cats.exe'
|
|
125
175
|
$resourcesRoot = Join-Path $resolvedInstallRoot 'resources'
|
|
126
176
|
$packagingPlanPath = Join-Path $resourcesRoot 'desktop-package-plan.json'
|
|
@@ -227,6 +277,10 @@ try {
|
|
|
227
277
|
$appService = $persisted.snapshot.services | Where-Object { $_.name -eq 'cats-platform' } | Select-Object -First 1
|
|
228
278
|
Assert-True ($null -ne $runtimeService -and $runtimeService.ready -eq $true) 'cats-runtime sidecar reached ready status'
|
|
229
279
|
Assert-True ($null -ne $appService -and $appService.ready -eq $true) 'cats app sidecar reached ready status'
|
|
280
|
+
Assert-True (Test-AuthSessionSecretProvisioned `
|
|
281
|
+
-ResolvedPlatformDir $resolvedPlatformDir `
|
|
282
|
+
-ResolvedDesktopDir $resolvedDesktopDir) `
|
|
283
|
+
'desktop auth session secret is provisioned for first-admin setup'
|
|
230
284
|
Assert-True (($persisted.snapshot.progress.steps | Measure-Object).Count -ge 3) 'host snapshot includes bootstrap progress steps'
|
|
231
285
|
Assert-True ($persisted.snapshot.background.trayEnabled -is [bool]) 'host snapshot includes background lifecycle state'
|
|
232
286
|
Assert-True ($persisted.snapshot.packaging.strategy -eq 'electron-sidecar-bundle') 'host snapshot includes packaging metadata'
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { DesktopUpdateChannel, DesktopUpdateState } from './contracts.js';
|
|
2
|
-
export interface DesktopUpdateConfig {
|
|
3
|
-
channel: DesktopUpdateChannel;
|
|
4
|
-
manifestUrl: string | null;
|
|
5
|
-
allowedHosts: string[];
|
|
6
|
-
checkOnStartup: boolean;
|
|
7
|
-
autoDownload: boolean;
|
|
8
|
-
}
|
|
9
|
-
export interface DesktopUpdateManifest {
|
|
10
|
-
channel?: string;
|
|
11
|
-
version?: string;
|
|
12
|
-
summary?: string;
|
|
13
|
-
downloadUrl?: string;
|
|
14
|
-
sha256?: string;
|
|
15
|
-
}
|
|
16
|
-
interface CheckForDesktopUpdatesDependencies {
|
|
17
|
-
fetchImpl?: typeof fetch;
|
|
18
|
-
now?: () => Date;
|
|
19
|
-
}
|
|
20
|
-
export declare function createDefaultDesktopUpdateState(config: DesktopUpdateConfig): DesktopUpdateState;
|
|
21
|
-
export declare function resolveDesktopUpdateConfig(env?: NodeJS.ProcessEnv): DesktopUpdateConfig;
|
|
22
|
-
export declare function checkForDesktopUpdates(config: DesktopUpdateConfig, dependencies?: CheckForDesktopUpdatesDependencies): Promise<DesktopUpdateState>;
|
|
23
|
-
export {};
|
|
24
|
-
//# sourceMappingURL=update.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../desktop/host/update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAK/E,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAUD,UAAU,kCAAkC;IAC1C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAsGD,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,mBAAmB,GAC1B,kBAAkB,CAepB;AAED,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,mBAAmB,CASrB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,YAAY,GAAE,kCAAuC,GACpD,OAAO,CAAC,kBAAkB,CAAC,CA8D7B"}
|
package/build/desktop/update.js
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { DESKTOP_HOST_VERSION } from './hostVersion.js';
|
|
2
|
-
import { parseDesktopBoolean } from './env.js';
|
|
3
|
-
import { parseDesktopAllowedHosts, validateDesktopUrl } from './security.js';
|
|
4
|
-
function normalizeChannel(value) {
|
|
5
|
-
if (value === 'alpha' || value === 'beta' || value === 'stable') {
|
|
6
|
-
return value;
|
|
7
|
-
}
|
|
8
|
-
return 'stable';
|
|
9
|
-
}
|
|
10
|
-
function isObjectRecord(value) {
|
|
11
|
-
return typeof value === 'object' && value !== null;
|
|
12
|
-
}
|
|
13
|
-
function readOptionalManifestString(value, fieldName) {
|
|
14
|
-
if (value === undefined || value === null) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
if (typeof value !== 'string') {
|
|
18
|
-
throw new Error(`Update manifest field "${fieldName}" must be a string.`);
|
|
19
|
-
}
|
|
20
|
-
return value.trim() || null;
|
|
21
|
-
}
|
|
22
|
-
function readOptionalManifestSha256(value) {
|
|
23
|
-
const digest = readOptionalManifestString(value, 'sha256');
|
|
24
|
-
if (digest === null) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
if (!/^[a-f0-9]{64}$/iu.test(digest)) {
|
|
28
|
-
throw new Error('Update manifest field "sha256" must be a 64 character hex digest.');
|
|
29
|
-
}
|
|
30
|
-
return digest.toLowerCase();
|
|
31
|
-
}
|
|
32
|
-
function parseVersion(value) {
|
|
33
|
-
const cleaned = value.trim().replace(/^v/u, '').split('-')[0];
|
|
34
|
-
if (!cleaned) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
const parts = cleaned.split('.');
|
|
38
|
-
const numbers = parts.map((part) => Number.parseInt(part, 10));
|
|
39
|
-
if (numbers.some((part) => !Number.isInteger(part) || part < 0)) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
return numbers;
|
|
43
|
-
}
|
|
44
|
-
function compareVersions(left, right) {
|
|
45
|
-
const leftParts = parseVersion(left);
|
|
46
|
-
const rightParts = parseVersion(right);
|
|
47
|
-
if (!leftParts || !rightParts) {
|
|
48
|
-
return left.localeCompare(right);
|
|
49
|
-
}
|
|
50
|
-
const maxLength = Math.max(leftParts.length, rightParts.length);
|
|
51
|
-
for (let index = 0; index < maxLength; index += 1) {
|
|
52
|
-
const leftValue = leftParts[index] ?? 0;
|
|
53
|
-
const rightValue = rightParts[index] ?? 0;
|
|
54
|
-
if (leftValue === rightValue) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
return leftValue < rightValue ? -1 : 1;
|
|
58
|
-
}
|
|
59
|
-
return 0;
|
|
60
|
-
}
|
|
61
|
-
function normalizeDesktopUpdateManifest(payload, expectedChannel) {
|
|
62
|
-
if (!isObjectRecord(payload)) {
|
|
63
|
-
throw new Error('Update manifest must be a JSON object.');
|
|
64
|
-
}
|
|
65
|
-
const channel = readOptionalManifestString(payload.channel, 'channel');
|
|
66
|
-
if (channel !== null && channel !== 'alpha' && channel !== 'beta' && channel !== 'stable') {
|
|
67
|
-
throw new Error(`Update manifest channel is unsupported: ${channel}`);
|
|
68
|
-
}
|
|
69
|
-
if (channel !== null && channel !== expectedChannel) {
|
|
70
|
-
throw new Error(`Update manifest channel "${channel}" does not match configured channel "${expectedChannel}".`);
|
|
71
|
-
}
|
|
72
|
-
const version = readOptionalManifestString(payload.version, 'version');
|
|
73
|
-
if (!version) {
|
|
74
|
-
throw new Error('Update manifest is missing required field "version".');
|
|
75
|
-
}
|
|
76
|
-
if (!parseVersion(version)) {
|
|
77
|
-
throw new Error(`Update manifest version is invalid: ${version}`);
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
channel,
|
|
81
|
-
version,
|
|
82
|
-
summary: readOptionalManifestString(payload.summary, 'summary'),
|
|
83
|
-
downloadUrl: readOptionalManifestString(payload.downloadUrl, 'downloadUrl'),
|
|
84
|
-
sha256: readOptionalManifestSha256(payload.sha256),
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
export function createDefaultDesktopUpdateState(config) {
|
|
88
|
-
return {
|
|
89
|
-
channel: config.channel,
|
|
90
|
-
status: config.manifestUrl ? 'idle' : 'disabled',
|
|
91
|
-
currentVersion: DESKTOP_HOST_VERSION,
|
|
92
|
-
latestVersion: null,
|
|
93
|
-
summary: config.manifestUrl
|
|
94
|
-
? 'Update checks are idle until the host performs a manifest probe.'
|
|
95
|
-
: 'Update checks are disabled until a manifest URL is configured.',
|
|
96
|
-
lastCheckedAt: null,
|
|
97
|
-
manifestUrl: config.manifestUrl,
|
|
98
|
-
downloadUrl: null,
|
|
99
|
-
sha256: null,
|
|
100
|
-
error: null,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
export function resolveDesktopUpdateConfig(env = process.env) {
|
|
104
|
-
const manifestUrl = env.CATS_DESKTOP_UPDATE_MANIFEST_URL?.trim() || null;
|
|
105
|
-
return {
|
|
106
|
-
channel: normalizeChannel(env.CATS_DESKTOP_UPDATE_CHANNEL),
|
|
107
|
-
manifestUrl: manifestUrl ? validateDesktopUrl(manifestUrl, { httpsOnly: true }) : null,
|
|
108
|
-
allowedHosts: parseDesktopAllowedHosts(env.CATS_DESKTOP_UPDATE_ALLOWED_HOSTS),
|
|
109
|
-
checkOnStartup: parseDesktopBoolean(env.CATS_DESKTOP_UPDATE_CHECK_ON_STARTUP, false),
|
|
110
|
-
autoDownload: parseDesktopBoolean(env.CATS_DESKTOP_UPDATE_AUTO_DOWNLOAD, false),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
export async function checkForDesktopUpdates(config, dependencies = {}) {
|
|
114
|
-
const now = dependencies.now?.() ?? new Date();
|
|
115
|
-
if (!config.manifestUrl) {
|
|
116
|
-
return createDefaultDesktopUpdateState(config);
|
|
117
|
-
}
|
|
118
|
-
const fetchImpl = dependencies.fetchImpl ?? fetch;
|
|
119
|
-
try {
|
|
120
|
-
const validatedManifestUrl = validateDesktopUrl(config.manifestUrl, { httpsOnly: true });
|
|
121
|
-
const manifestUrl = new URL(validatedManifestUrl);
|
|
122
|
-
const response = await fetchImpl(validatedManifestUrl);
|
|
123
|
-
if (!response.ok) {
|
|
124
|
-
throw new Error(`HTTP ${response.status}`);
|
|
125
|
-
}
|
|
126
|
-
const manifest = normalizeDesktopUpdateManifest(await response.json(), config.channel);
|
|
127
|
-
const latestVersion = manifest.version;
|
|
128
|
-
const hasUpdate = compareVersions(DESKTOP_HOST_VERSION, latestVersion) < 0;
|
|
129
|
-
const status = hasUpdate ? 'update_available' : 'up_to_date';
|
|
130
|
-
if (hasUpdate && !manifest.downloadUrl) {
|
|
131
|
-
throw new Error('Update manifest is missing required field "downloadUrl" for a newer version.');
|
|
132
|
-
}
|
|
133
|
-
if (manifest.downloadUrl && !manifest.sha256) {
|
|
134
|
-
throw new Error('Update manifest is missing required field "sha256" for a download artifact.');
|
|
135
|
-
}
|
|
136
|
-
const downloadUrl = manifest.downloadUrl
|
|
137
|
-
? validateDesktopUrl(manifest.downloadUrl, {
|
|
138
|
-
httpsOnly: true,
|
|
139
|
-
allowedHosts: [manifestUrl.hostname, ...config.allowedHosts],
|
|
140
|
-
})
|
|
141
|
-
: null;
|
|
142
|
-
return {
|
|
143
|
-
channel: config.channel,
|
|
144
|
-
status,
|
|
145
|
-
currentVersion: DESKTOP_HOST_VERSION,
|
|
146
|
-
latestVersion,
|
|
147
|
-
summary: manifest.summary?.trim()
|
|
148
|
-
|| (hasUpdate
|
|
149
|
-
? `Update ${latestVersion} is available on the ${config.channel} channel.`
|
|
150
|
-
: `Cats desktop host is up to date on the ${config.channel} channel.`),
|
|
151
|
-
lastCheckedAt: now.toISOString(),
|
|
152
|
-
manifestUrl: validatedManifestUrl,
|
|
153
|
-
downloadUrl,
|
|
154
|
-
sha256: downloadUrl ? manifest.sha256 : null,
|
|
155
|
-
error: null,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
return {
|
|
160
|
-
channel: config.channel,
|
|
161
|
-
status: 'failed',
|
|
162
|
-
currentVersion: DESKTOP_HOST_VERSION,
|
|
163
|
-
latestVersion: null,
|
|
164
|
-
summary: 'The desktop host could not refresh its update manifest.',
|
|
165
|
-
lastCheckedAt: now.toISOString(),
|
|
166
|
-
manifestUrl: config.manifestUrl,
|
|
167
|
-
downloadUrl: null,
|
|
168
|
-
sha256: null,
|
|
169
|
-
error: error instanceof Error ? error.message : String(error),
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
//# sourceMappingURL=update.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../desktop/host/update.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AA+B7E,SAAS,gBAAgB,CAAC,KAAyB;IACjD,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,0BAA0B,CAAC,KAAc,EAAE,SAAiB;IACnE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,0BAA0B,SAAS,qBAAqB,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED,SAAS,0BAA0B,CAAC,KAAc;IAChD,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC3D,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC/D,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,KAAa;IAClD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAEvC,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAChE,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAClD,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,OAAO,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,8BAA8B,CACrC,OAAgB,EAChB,eAAqC;IAErC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACvE,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,2CAA2C,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACb,4BAA4B,OAAO,wCAAwC,eAAe,IAAI,CAC/F,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACvE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,OAAO;QACL,OAAO;QACP,OAAO;QACP,OAAO,EAAE,0BAA0B,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC;QAC/D,WAAW,EAAE,0BAA0B,CAAC,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC;QAC3E,MAAM,EAAE,0BAA0B,CAAC,OAAO,CAAC,MAAM,CAAC;KACnD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,MAA2B;IAE3B,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU;QAChD,cAAc,EAAE,oBAAoB;QACpC,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,MAAM,CAAC,WAAW;YACzB,CAAC,CAAC,kEAAkE;YACpE,CAAC,CAAC,gEAAgE;QACpE,aAAa,EAAE,IAAI;QACnB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,WAAW,GAAG,GAAG,CAAC,gCAAgC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;IACzE,OAAO;QACL,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAAC,2BAA2B,CAAC;QAC1D,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;QACtF,YAAY,EAAE,wBAAwB,CAAC,GAAG,CAAC,iCAAiC,CAAC;QAC7E,cAAc,EAAE,mBAAmB,CAAC,GAAG,CAAC,oCAAoC,EAAE,KAAK,CAAC;QACpF,YAAY,EAAE,mBAAmB,CAAC,GAAG,CAAC,iCAAiC,EAAE,KAAK,CAAC;KAChF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAA2B,EAC3B,eAAmD,EAAE;IAErD,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;IAE/C,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,OAAO,+BAA+B,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,IAAI,KAAK,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,oBAAoB,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,QAAQ,GAAG,8BAA8B,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACvF,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC;QACvC,MAAM,SAAS,GAAG,eAAe,CAAC,oBAAoB,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,YAAY,CAAC;QAC7D,IAAI,SAAS,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;QAClG,CAAC;QACD,IAAI,QAAQ,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC7C,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;QACjG,CAAC;QAED,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW;YACtC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,WAAW,EAAE;gBACzC,SAAS,EAAE,IAAI;gBACf,YAAY,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;aAC7D,CAAC;YACF,CAAC,CAAC,IAAI,CAAC;QAET,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM;YACN,cAAc,EAAE,oBAAoB;YACpC,aAAa;YACb,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE;mBAC5B,CAAC,SAAS;oBACX,CAAC,CAAC,UAAU,aAAa,wBAAwB,MAAM,CAAC,OAAO,WAAW;oBAC1E,CAAC,CAAC,0CAA0C,MAAM,CAAC,OAAO,WAAW,CAAC;YAC1E,aAAa,EAAE,GAAG,CAAC,WAAW,EAAE;YAChC,WAAW,EAAE,oBAAoB;YACjC,WAAW;YACX,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;YAC5C,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,QAAQ;YAChB,cAAc,EAAE,oBAAoB;YACpC,aAAa,EAAE,IAAI;YACnB,OAAO,EAAE,yDAAyD;YAClE,aAAa,EAAE,GAAG,CAAC,WAAW,EAAE;YAChC,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC;IACJ,CAAC;AACH,CAAC"}
|