@tapi-dev/sdk 0.1.24 → 0.1.26
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/dist/cli.d.ts +5 -0
- package/dist/cli.js +55 -4
- package/package.json +1 -1
package/dist/cli.d.ts
CHANGED
|
@@ -114,6 +114,11 @@ export declare function validateStudioManifest(input: unknown): StudioReleaseMan
|
|
|
114
114
|
export declare function validateServiceReleaseManifest(input: unknown): ServiceReleaseManifest;
|
|
115
115
|
export declare function compareVersions(left: string, right: string): number;
|
|
116
116
|
export declare function memoizeStudioInstallToken(options: StudioCliOptions, installToken?: string): string;
|
|
117
|
+
export declare function tryOpenExistingPortableStudioServer(options: StudioCliOptions, manifest: StudioReleaseManifest, fetchImpl?: FetchLike, openBrowserImpl?: (url: string) => void): Promise<{
|
|
118
|
+
opened: boolean;
|
|
119
|
+
baseUrl?: string;
|
|
120
|
+
reason?: string;
|
|
121
|
+
}>;
|
|
117
122
|
export declare function findPortablePlaywrightBrowsersDir(exePath: string): string | undefined;
|
|
118
123
|
export declare function waitForHttpOk(url: string, timeoutMs?: number, intervalMs?: number, fetchImpl?: FetchLike): Promise<void>;
|
|
119
124
|
export declare function chooseStudioPort(preferred?: number, options?: {
|
package/dist/cli.js
CHANGED
|
@@ -2126,6 +2126,10 @@ async function openStudio(options) {
|
|
|
2126
2126
|
if (!options.exePath) {
|
|
2127
2127
|
const portable = await ensurePortableStudioServer(options);
|
|
2128
2128
|
if (portable) {
|
|
2129
|
+
const existing = await tryOpenExistingPortableStudioServer(options, portable.manifest);
|
|
2130
|
+
if (existing.opened) {
|
|
2131
|
+
return 0;
|
|
2132
|
+
}
|
|
2129
2133
|
await launchPortableStudioServer(portable.exePath, options, portable.manifest);
|
|
2130
2134
|
return 0;
|
|
2131
2135
|
}
|
|
@@ -2160,6 +2164,34 @@ function findStudioExecutable(options) {
|
|
|
2160
2164
|
}
|
|
2161
2165
|
return getStudioExecutableCandidates().find((candidate) => existsSync(candidate));
|
|
2162
2166
|
}
|
|
2167
|
+
export async function tryOpenExistingPortableStudioServer(options, manifest, fetchImpl = fetch, openBrowserImpl = openBrowser) {
|
|
2168
|
+
const record = await readStudioInstanceRecord(options);
|
|
2169
|
+
if (!record) {
|
|
2170
|
+
return { opened: false, reason: "instance_record_missing" };
|
|
2171
|
+
}
|
|
2172
|
+
if ((record.manifestVersion || "") !== manifest.version) {
|
|
2173
|
+
return { opened: false, reason: "manifest_version_mismatch" };
|
|
2174
|
+
}
|
|
2175
|
+
try {
|
|
2176
|
+
const identityResponse = await fetchWithTimeout(`${record.baseUrl.replace(/\/+$/, "")}/api/studio/control/identity`, { headers: { Accept: "application/json" } }, 1_000, fetchImpl);
|
|
2177
|
+
if (!identityResponse.ok) {
|
|
2178
|
+
await unlinkIfExists(studioInstanceRecordPathForOptions(options));
|
|
2179
|
+
return { opened: false, reason: `identity_http_${identityResponse.status}` };
|
|
2180
|
+
}
|
|
2181
|
+
const identity = await readJsonBody(identityResponse);
|
|
2182
|
+
if (!studioInstanceIdentityMatches(identity, options)) {
|
|
2183
|
+
return { opened: false, reason: "identity_mismatch" };
|
|
2184
|
+
}
|
|
2185
|
+
const launchUrl = studioLaunchUrl(record.baseUrl, options);
|
|
2186
|
+
openBrowserImpl(launchUrl);
|
|
2187
|
+
console.log(`Opened existing Tapi Studio ${record.manifestVersion || manifest.version}: ${launchUrl}`);
|
|
2188
|
+
return { opened: true, baseUrl: record.baseUrl };
|
|
2189
|
+
}
|
|
2190
|
+
catch (error) {
|
|
2191
|
+
await unlinkIfExists(studioInstanceRecordPathForOptions(options));
|
|
2192
|
+
return { opened: false, reason: formatError(error) };
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2163
2195
|
async function ensurePortableStudioServer(options) {
|
|
2164
2196
|
const event = await createCliWideEvent("tapi_cli.studio_server_ensure", {
|
|
2165
2197
|
sdk_version: sdkVersion,
|
|
@@ -2259,8 +2291,7 @@ async function launchPortableStudioServer(exePath, options, manifest) {
|
|
|
2259
2291
|
env.PLAYWRIGHT_BROWSERS_PATH = playwrightBrowsersPath;
|
|
2260
2292
|
}
|
|
2261
2293
|
const url = `http://${host}:${port}`;
|
|
2262
|
-
const
|
|
2263
|
-
const launchUrl = launchQuery ? `${url}/?${launchQuery}` : url;
|
|
2294
|
+
const launchUrl = studioLaunchUrl(url, options);
|
|
2264
2295
|
let childPid = 0;
|
|
2265
2296
|
await withCliSpinner("Starting Tapi Studio", async () => {
|
|
2266
2297
|
const child = spawn(exePath, [], {
|
|
@@ -2289,6 +2320,11 @@ async function launchPortableStudioServer(exePath, options, manifest) {
|
|
|
2289
2320
|
openBrowser(launchUrl);
|
|
2290
2321
|
console.log(`Opened Tapi Studio ${manifest.version}: ${launchUrl}`);
|
|
2291
2322
|
}
|
|
2323
|
+
function studioLaunchUrl(baseUrl, options) {
|
|
2324
|
+
const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
|
|
2325
|
+
const launchQuery = options.launchUrlQuery ? options.launchUrlQuery.replace(/^\?+/, "") : "";
|
|
2326
|
+
return launchQuery ? `${normalizedBaseUrl}/?${launchQuery}` : normalizedBaseUrl;
|
|
2327
|
+
}
|
|
2292
2328
|
export function findPortablePlaywrightBrowsersDir(exePath) {
|
|
2293
2329
|
const exeDir = dirname(exePath);
|
|
2294
2330
|
const releaseDir = basename(exeDir).toLowerCase() === "tapi-studio-server"
|
|
@@ -2444,14 +2480,16 @@ async function runDoctor(options) {
|
|
|
2444
2480
|
console.log(`Studio cache: ${options.cacheDir}`);
|
|
2445
2481
|
console.log(`Workspace: ${options.workspaceRoot ?? "not found"}`);
|
|
2446
2482
|
console.log(`Project: ${options.projectId ?? "not set"}`);
|
|
2447
|
-
const exePath = options.exePath ?? getStudioExecutableCandidates().find((candidate) => existsSync(candidate));
|
|
2448
|
-
console.log(`Studio executable: ${exePath && existsSync(exePath) ? exePath : "not found"}`);
|
|
2449
2483
|
try {
|
|
2450
2484
|
const manifest = await withCliSpinner("Fetching latest Tapi Studio manifest", () => fetchStudioManifest(options.manifestUrl));
|
|
2451
2485
|
ensureCompatibleManifest(manifest);
|
|
2486
|
+
const exePath = findInstalledStudioExecutable(options, manifest);
|
|
2487
|
+
console.log(`Studio executable: ${exePath ?? "not found"}`);
|
|
2452
2488
|
console.log(`Latest Studio: ${manifest.version} (${manifest.platform})`);
|
|
2453
2489
|
}
|
|
2454
2490
|
catch (error) {
|
|
2491
|
+
const exePath = options.exePath ?? getStudioExecutableCandidates().find((candidate) => existsSync(candidate));
|
|
2492
|
+
console.log(`Studio executable: ${exePath && existsSync(exePath) ? exePath : "not found"}`);
|
|
2455
2493
|
console.log(`Latest Studio: unavailable (${formatError(error)})`);
|
|
2456
2494
|
return 1;
|
|
2457
2495
|
}
|
|
@@ -2920,6 +2958,19 @@ function isPortableStudioServerManifest(manifest) {
|
|
|
2920
2958
|
const kind = String(manifest.installerKind || "").toLowerCase();
|
|
2921
2959
|
return kind === "portable-server" || manifest.artifactName.toLowerCase().endsWith(".zip");
|
|
2922
2960
|
}
|
|
2961
|
+
function findInstalledStudioExecutable(options, manifest) {
|
|
2962
|
+
if (options.exePath) {
|
|
2963
|
+
return existsSync(options.exePath) ? options.exePath : undefined;
|
|
2964
|
+
}
|
|
2965
|
+
const legacyDesktopExe = getStudioExecutableCandidates().find((candidate) => existsSync(candidate));
|
|
2966
|
+
if (legacyDesktopExe) {
|
|
2967
|
+
return legacyDesktopExe;
|
|
2968
|
+
}
|
|
2969
|
+
if (!isPortableStudioServerManifest(manifest)) {
|
|
2970
|
+
return undefined;
|
|
2971
|
+
}
|
|
2972
|
+
return findPortableStudioServerExe(portableStudioServerReleaseDir(manifest, options.installDir), manifest);
|
|
2973
|
+
}
|
|
2923
2974
|
function portableStudioServerReleaseDir(manifest, releasesDir = getDefaultPortableStudioServerReleasesDir()) {
|
|
2924
2975
|
return join(releasesDir, safePathSegment(manifest.version));
|
|
2925
2976
|
}
|