@mintlify/previewing 4.0.850 → 4.0.852
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/__tests__/silentUpdateClient.test.js +16 -0
- package/dist/local-preview/index.js +3 -1
- package/dist/local-preview/setupNext.js +14 -1
- package/dist/local-preview/update.d.ts +2 -1
- package/dist/local-preview/update.js +138 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -18,10 +18,12 @@ describe('silentUpdateClient', () => {
|
|
|
18
18
|
it('has latest client version already', async () => {
|
|
19
19
|
const versionString = '0.0.100';
|
|
20
20
|
const clientVersion = undefined;
|
|
21
|
+
const localClientVersion = undefined;
|
|
21
22
|
const cliVersion = undefined;
|
|
22
23
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
23
24
|
versionString,
|
|
24
25
|
clientVersion,
|
|
26
|
+
localClientVersion,
|
|
25
27
|
cliVersion,
|
|
26
28
|
});
|
|
27
29
|
expect(tryDownloadTargetMintSpy).not.toHaveBeenCalled();
|
|
@@ -31,10 +33,12 @@ describe('silentUpdateClient', () => {
|
|
|
31
33
|
it('has no client version and downloads latest', async () => {
|
|
32
34
|
const versionString = null;
|
|
33
35
|
const clientVersion = undefined;
|
|
36
|
+
const localClientVersion = undefined;
|
|
34
37
|
const cliVersion = undefined;
|
|
35
38
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
36
39
|
versionString,
|
|
37
40
|
clientVersion,
|
|
41
|
+
localClientVersion,
|
|
38
42
|
cliVersion,
|
|
39
43
|
});
|
|
40
44
|
expect(tryDownloadTargetMintSpy).toHaveBeenCalledWith({
|
|
@@ -47,10 +51,12 @@ describe('silentUpdateClient', () => {
|
|
|
47
51
|
it('always downloads latest for locally linked cli', async () => {
|
|
48
52
|
const versionString = null;
|
|
49
53
|
const clientVersion = undefined;
|
|
54
|
+
const localClientVersion = undefined;
|
|
50
55
|
const cliVersion = LOCAL_LINKED_CLI_VERSION;
|
|
51
56
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
52
57
|
versionString,
|
|
53
58
|
clientVersion,
|
|
59
|
+
localClientVersion,
|
|
54
60
|
cliVersion,
|
|
55
61
|
});
|
|
56
62
|
expect(tryDownloadTargetMintSpy).toHaveBeenCalledWith({
|
|
@@ -63,10 +69,12 @@ describe('silentUpdateClient', () => {
|
|
|
63
69
|
it('compatible client version is latest and downloads latest', async () => {
|
|
64
70
|
const versionString = null;
|
|
65
71
|
const clientVersion = undefined;
|
|
72
|
+
const localClientVersion = undefined;
|
|
66
73
|
const cliVersion = '4.2.0';
|
|
67
74
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
68
75
|
versionString,
|
|
69
76
|
clientVersion,
|
|
77
|
+
localClientVersion,
|
|
70
78
|
cliVersion,
|
|
71
79
|
});
|
|
72
80
|
expect(tryDownloadTargetMintSpy).toHaveBeenCalledWith({
|
|
@@ -80,10 +88,12 @@ describe('silentUpdateClient', () => {
|
|
|
80
88
|
vi.mocked(client.getCompatibleClientVersion).mockResolvedValueOnce('0.0.99');
|
|
81
89
|
const versionString = '0.0.99';
|
|
82
90
|
const clientVersion = undefined;
|
|
91
|
+
const localClientVersion = undefined;
|
|
83
92
|
const cliVersion = '4.2.0';
|
|
84
93
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
85
94
|
versionString,
|
|
86
95
|
clientVersion,
|
|
96
|
+
localClientVersion,
|
|
87
97
|
cliVersion,
|
|
88
98
|
});
|
|
89
99
|
expect(tryDownloadTargetMintSpy).not.toHaveBeenCalled();
|
|
@@ -94,10 +104,12 @@ describe('silentUpdateClient', () => {
|
|
|
94
104
|
vi.mocked(client.getCompatibleClientVersion).mockResolvedValueOnce('0.0.99');
|
|
95
105
|
const versionString = '0.0.98';
|
|
96
106
|
const clientVersion = undefined;
|
|
107
|
+
const localClientVersion = undefined;
|
|
97
108
|
const cliVersion = '4.2.0';
|
|
98
109
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
99
110
|
versionString,
|
|
100
111
|
clientVersion,
|
|
112
|
+
localClientVersion,
|
|
101
113
|
cliVersion,
|
|
102
114
|
});
|
|
103
115
|
expect(tryDownloadTargetMintSpy).toHaveBeenCalledWith({
|
|
@@ -111,10 +123,12 @@ describe('silentUpdateClient', () => {
|
|
|
111
123
|
vi.mocked(client.getCompatibleClientVersion).mockResolvedValueOnce(undefined);
|
|
112
124
|
const versionString = '0.0.98';
|
|
113
125
|
const clientVersion = undefined;
|
|
126
|
+
const localClientVersion = undefined;
|
|
114
127
|
const cliVersion = '4.2.0';
|
|
115
128
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
116
129
|
versionString,
|
|
117
130
|
clientVersion,
|
|
131
|
+
localClientVersion,
|
|
118
132
|
cliVersion,
|
|
119
133
|
});
|
|
120
134
|
expect(tryDownloadTargetMintSpy).not.toHaveBeenCalled();
|
|
@@ -126,10 +140,12 @@ describe('silentUpdateClient', () => {
|
|
|
126
140
|
vi.mocked(client.tryDownloadTargetMint).mockResolvedValueOnce('some error');
|
|
127
141
|
const versionString = null;
|
|
128
142
|
const clientVersion = undefined;
|
|
143
|
+
const localClientVersion = undefined;
|
|
129
144
|
const cliVersion = '4.2.0';
|
|
130
145
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
131
146
|
versionString,
|
|
132
147
|
clientVersion,
|
|
148
|
+
localClientVersion,
|
|
133
149
|
cliVersion,
|
|
134
150
|
});
|
|
135
151
|
expect(tryDownloadTargetMintSpy).toHaveBeenCalledWith({
|
|
@@ -11,6 +11,7 @@ const dev = async (argv) => {
|
|
|
11
11
|
const hasInternet = await isOnline();
|
|
12
12
|
const localSchema = argv['local-schema'];
|
|
13
13
|
const clientVersion = argv['client-version'];
|
|
14
|
+
const localClientVersion = argv['local-client-version'];
|
|
14
15
|
const packageName = argv.packageName;
|
|
15
16
|
const groups = argv.groups;
|
|
16
17
|
const cliVersion = argv.cliVersion;
|
|
@@ -19,7 +20,7 @@ const dev = async (argv) => {
|
|
|
19
20
|
const versionString = (await pathExists(VERSION_PATH))
|
|
20
21
|
? fse.readFileSync(VERSION_PATH, 'utf8')
|
|
21
22
|
: null;
|
|
22
|
-
if (!versionString && !hasInternet) {
|
|
23
|
+
if (!versionString && !localClientVersion && !hasInternet) {
|
|
23
24
|
clearLogs();
|
|
24
25
|
addLog(_jsx(ErrorLog, { message: `running ${packageName} dev after updating requires an internet connection.` }));
|
|
25
26
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
@@ -29,6 +30,7 @@ const dev = async (argv) => {
|
|
|
29
30
|
const { needsUpdate, error } = await silentUpdateClient({
|
|
30
31
|
versionString,
|
|
31
32
|
clientVersion,
|
|
33
|
+
localClientVersion,
|
|
32
34
|
cliVersion,
|
|
33
35
|
});
|
|
34
36
|
if (error) {
|
|
@@ -24,7 +24,20 @@ import { CLIENT_PATH, NEXT_CONFIG_PATH, NEXT_ROUTER_SERVER_PATH, NEXT_SIDE_EFFEC
|
|
|
24
24
|
*/
|
|
25
25
|
export const setupNext = async () => {
|
|
26
26
|
const hostname = process.env.HOSTNAME || 'localhost';
|
|
27
|
-
|
|
27
|
+
let config;
|
|
28
|
+
try {
|
|
29
|
+
const configFile = fse.readFileSync(NEXT_CONFIG_PATH, 'utf8');
|
|
30
|
+
config = JSON.parse(configFile).config;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
if (err instanceof Error &&
|
|
34
|
+
'code' in err &&
|
|
35
|
+
err.code === 'ENOENT' &&
|
|
36
|
+
NEXT_CONFIG_PATH.includes('.next/required-server-files.json')) {
|
|
37
|
+
throw new Error(`Client not built. Run: cd <path>/apps/client && STANDALONE_BUILD=true NEXT_PUBLIC_ENV=cli yarn build`);
|
|
38
|
+
}
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
28
41
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(config);
|
|
29
42
|
// The server.js provided by next.js's standalone build does a similar import of this file.
|
|
30
43
|
// Not sure what side effects are being created, but want to change as little as possible.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export declare const silentUpdateClient: ({ versionString, clientVersion, cliVersion }: {
|
|
1
|
+
export declare const silentUpdateClient: ({ versionString, clientVersion, localClientVersion, cliVersion, }: {
|
|
2
2
|
versionString: string | null;
|
|
3
3
|
clientVersion: string | undefined;
|
|
4
|
+
localClientVersion: string | undefined;
|
|
4
5
|
cliVersion: string | undefined;
|
|
5
6
|
}) => Promise<{
|
|
6
7
|
needsUpdate: boolean;
|
|
@@ -1,30 +1,160 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
import fse from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { LOCAL_LINKED_CLI_VERSION, MINT_PATH, DOT_MINTLIFY, CLIENT_PATH } from '../constants.js';
|
|
6
|
+
import { clearLogs, addLog } from '../logging-state.js';
|
|
7
|
+
import { SpinnerLog } from '../logs.js';
|
|
8
|
+
import { getLatestClientVersion, tryDownloadTargetMint, getCompatibleClientVersion, } from './client.js';
|
|
9
|
+
const MINT_BACKUP_PATH = path.join(DOT_MINTLIFY, 'mint-backup');
|
|
10
|
+
const isCurrentlySymlinked = async () => {
|
|
11
|
+
if (!(await fse.pathExists(MINT_PATH)))
|
|
12
|
+
return false;
|
|
13
|
+
const stats = await fse.lstat(MINT_PATH);
|
|
14
|
+
return stats.isSymbolicLink();
|
|
15
|
+
};
|
|
16
|
+
const buildClient = async () => {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
clearLogs();
|
|
19
|
+
addLog(_jsx(SpinnerLog, { message: "building local client (this may take a few minutes)..." }));
|
|
20
|
+
const buildProcess = spawn('yarn', ['build'], {
|
|
21
|
+
cwd: CLIENT_PATH,
|
|
22
|
+
env: {
|
|
23
|
+
...process.env,
|
|
24
|
+
STANDALONE_BUILD: 'true',
|
|
25
|
+
NEXT_PUBLIC_ENV: 'cli',
|
|
26
|
+
NEXT_PUBLIC_IS_LOCAL_CLIENT: 'true',
|
|
27
|
+
},
|
|
28
|
+
stdio: 'pipe',
|
|
29
|
+
shell: true,
|
|
30
|
+
});
|
|
31
|
+
let stderr = '';
|
|
32
|
+
buildProcess.stderr.on('data', (data) => {
|
|
33
|
+
stderr += data.toString();
|
|
34
|
+
});
|
|
35
|
+
buildProcess.on('close', (code) => {
|
|
36
|
+
if (code === 0) {
|
|
37
|
+
resolve(undefined);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
resolve(`Client build failed (exit code ${code}): ${stderr.slice(-500)}`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
buildProcess.on('error', (err) => {
|
|
44
|
+
resolve(`Client build error: ${err.message}`);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
const restoreFromBackup = async () => {
|
|
49
|
+
try {
|
|
50
|
+
if (await isCurrentlySymlinked()) {
|
|
51
|
+
await fse.remove(MINT_PATH);
|
|
52
|
+
}
|
|
53
|
+
if (await fse.pathExists(MINT_BACKUP_PATH)) {
|
|
54
|
+
await fse.move(MINT_BACKUP_PATH, MINT_PATH);
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
return err instanceof Error ? err.message : 'unknown error';
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const symlinkLocalClient = async (targetPath) => {
|
|
63
|
+
try {
|
|
64
|
+
const resolvedPath = path.resolve(targetPath);
|
|
65
|
+
if (!(await fse.pathExists(resolvedPath))) {
|
|
66
|
+
return `Path does not exist: ${resolvedPath}`;
|
|
67
|
+
}
|
|
68
|
+
const stats = await fse.stat(resolvedPath);
|
|
69
|
+
if (!stats.isDirectory()) {
|
|
70
|
+
return `Path is not a directory: ${resolvedPath}`;
|
|
71
|
+
}
|
|
72
|
+
if (await fse.pathExists(MINT_PATH)) {
|
|
73
|
+
const existingStats = await fse.lstat(MINT_PATH);
|
|
74
|
+
if (existingStats.isSymbolicLink()) {
|
|
75
|
+
await fse.remove(MINT_PATH);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
if (await fse.pathExists(MINT_BACKUP_PATH)) {
|
|
79
|
+
await fse.remove(MINT_BACKUP_PATH);
|
|
80
|
+
}
|
|
81
|
+
await fse.move(MINT_PATH, MINT_BACKUP_PATH);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
await fse.ensureDir(path.dirname(MINT_PATH));
|
|
85
|
+
await fse.symlink(resolvedPath, MINT_PATH);
|
|
86
|
+
const buildError = await buildClient();
|
|
87
|
+
if (buildError) {
|
|
88
|
+
return buildError;
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
return err instanceof Error ? err.message : 'unknown error';
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
export const silentUpdateClient = async ({ versionString, clientVersion, localClientVersion, cliVersion, }) => {
|
|
97
|
+
// Handle local client symlink
|
|
98
|
+
if (localClientVersion) {
|
|
99
|
+
const error = await symlinkLocalClient(localClientVersion);
|
|
100
|
+
return { needsUpdate: false, error };
|
|
101
|
+
}
|
|
102
|
+
// If currently symlinked but not using local client, restore from backup
|
|
103
|
+
if (await isCurrentlySymlinked()) {
|
|
104
|
+
const restoreError = await restoreFromBackup();
|
|
105
|
+
if (restoreError) {
|
|
106
|
+
return { needsUpdate: false, error: restoreError };
|
|
107
|
+
}
|
|
108
|
+
// Re-read version string after restore
|
|
109
|
+
const newVersionString = (await fse.pathExists(path.join(MINT_PATH, 'mint-version.txt')))
|
|
110
|
+
? fse.readFileSync(path.join(MINT_PATH, 'mint-version.txt'), 'utf8')
|
|
111
|
+
: null;
|
|
112
|
+
// Continue with normal update logic using restored version
|
|
113
|
+
return silentUpdateClientInternal({
|
|
114
|
+
versionString: newVersionString,
|
|
115
|
+
clientVersion,
|
|
116
|
+
cliVersion,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return silentUpdateClientInternal({ versionString, clientVersion, cliVersion });
|
|
120
|
+
};
|
|
121
|
+
const silentUpdateClientInternal = async ({ versionString, clientVersion, cliVersion, }) => {
|
|
4
122
|
const latestClientVersion = await getLatestClientVersion();
|
|
5
123
|
const hasLatestClientVersion = latestClientVersion && versionString && versionString.trim() === latestClientVersion.trim();
|
|
6
124
|
if (clientVersion) {
|
|
7
125
|
// always download specific client version if provided
|
|
8
|
-
const error = await tryDownloadTargetMint({
|
|
126
|
+
const error = await tryDownloadTargetMint({
|
|
127
|
+
targetVersion: clientVersion,
|
|
128
|
+
existingVersion: versionString,
|
|
129
|
+
});
|
|
9
130
|
return { needsUpdate: false, error };
|
|
10
131
|
}
|
|
11
132
|
else if ((!versionString || cliVersion === LOCAL_LINKED_CLI_VERSION) && latestClientVersion) {
|
|
12
133
|
// if no version exists, download latest
|
|
13
|
-
const error = await tryDownloadTargetMint({
|
|
134
|
+
const error = await tryDownloadTargetMint({
|
|
135
|
+
targetVersion: latestClientVersion,
|
|
136
|
+
existingVersion: null,
|
|
137
|
+
});
|
|
14
138
|
return { needsUpdate: false, error };
|
|
15
139
|
}
|
|
16
140
|
else if (cliVersion && !hasLatestClientVersion) {
|
|
17
141
|
// if not on latest, check whether to download latest or max
|
|
18
142
|
const maxClientVersion = await getCompatibleClientVersion({ cliVersion });
|
|
19
143
|
const hasMaxClientVersion = maxClientVersion && versionString && versionString.trim() === maxClientVersion.trim();
|
|
20
|
-
if (maxClientVersion ===
|
|
144
|
+
if (maxClientVersion === 'latest' && latestClientVersion) {
|
|
21
145
|
// if latest, download latest
|
|
22
|
-
const error = await tryDownloadTargetMint({
|
|
146
|
+
const error = await tryDownloadTargetMint({
|
|
147
|
+
targetVersion: latestClientVersion,
|
|
148
|
+
existingVersion: versionString,
|
|
149
|
+
});
|
|
23
150
|
return { needsUpdate: false, error };
|
|
24
151
|
}
|
|
25
152
|
else if (maxClientVersion && !hasMaxClientVersion) {
|
|
26
153
|
// if maxxed out, needs update
|
|
27
|
-
const error = await tryDownloadTargetMint({
|
|
154
|
+
const error = await tryDownloadTargetMint({
|
|
155
|
+
targetVersion: maxClientVersion,
|
|
156
|
+
existingVersion: versionString,
|
|
157
|
+
});
|
|
28
158
|
return { needsUpdate: true, error };
|
|
29
159
|
}
|
|
30
160
|
else {
|