@syncular/cli 0.0.0-102 → 0.0.0-113
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/package.json +12 -15
- package/src/args.ts +0 -113
- package/src/auth-storage.ts +0 -57
- package/src/buildpacks/index.ts +0 -2
- package/src/buildpacks/registry.ts +0 -47
- package/src/buildpacks/types.ts +0 -1
- package/src/command-registry.ts +0 -685
- package/src/commands/auth.ts +0 -426
- package/src/commands/build.ts +0 -210
- package/src/commands/console.ts +0 -252
- package/src/commands/demo.ts +0 -1151
- package/src/commands/doctor.tsx +0 -133
- package/src/commands/migrate.ts +0 -271
- package/src/commands/project.ts +0 -381
- package/src/commands/target.ts +0 -62
- package/src/commands/typegen.ts +0 -404
- package/src/constants.ts +0 -7
- package/src/control-plane-token.ts +0 -46
- package/src/control-plane.ts +0 -62
- package/src/dev-logging.tsx +0 -415
- package/src/extensions/index.ts +0 -1
- package/src/extensions/manifest.ts +0 -37
- package/src/flags.ts +0 -92
- package/src/help.tsx +0 -239
- package/src/index.ts +0 -4
- package/src/interactive.tsx +0 -306
- package/src/main.tsx +0 -268
- package/src/output.tsx +0 -47
- package/src/paths.ts +0 -11
- package/src/spaces-config.ts +0 -2
- package/src/targets/index.ts +0 -13
- package/src/targets/state.ts +0 -99
- package/src/targets/types.ts +0 -8
- package/src/templates/index.ts +0 -2
- package/src/templates/registry.ts +0 -42
- package/src/templates/syncular-types.ts +0 -10
- package/src/types.ts +0 -67
- package/src/update-check.ts +0 -296
package/src/update-check.ts
DELETED
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { homedir, platform } from 'node:os';
|
|
3
|
-
import { dirname, join } from 'node:path';
|
|
4
|
-
import process from 'node:process';
|
|
5
|
-
import { CLI_VERSION } from './constants';
|
|
6
|
-
|
|
7
|
-
const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
8
|
-
const UPDATE_CHECK_TIMEOUT_MS = 1200;
|
|
9
|
-
const UPDATE_STATE_FILE = 'update-check.json';
|
|
10
|
-
const NPM_LATEST_URL = 'https://registry.npmjs.org/@syncular%2fcli/latest';
|
|
11
|
-
|
|
12
|
-
interface UpdateCheckState {
|
|
13
|
-
lastCheckedAt?: string;
|
|
14
|
-
latestVersion?: string;
|
|
15
|
-
notifiedVersion?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface ParsedVersion {
|
|
19
|
-
major: number;
|
|
20
|
-
minor: number;
|
|
21
|
-
patch: number;
|
|
22
|
-
prerelease: string[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function parseVersion(input: string): ParsedVersion | null {
|
|
26
|
-
const [core, prereleaseRaw = ''] = input.trim().split('-', 2);
|
|
27
|
-
const coreParts = core.split('.');
|
|
28
|
-
if (coreParts.length !== 3) {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const major = Number.parseInt(coreParts[0] ?? '', 10);
|
|
33
|
-
const minor = Number.parseInt(coreParts[1] ?? '', 10);
|
|
34
|
-
const patch = Number.parseInt(coreParts[2] ?? '', 10);
|
|
35
|
-
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const prerelease =
|
|
40
|
-
prereleaseRaw.length > 0 ? prereleaseRaw.split('.').filter(Boolean) : [];
|
|
41
|
-
|
|
42
|
-
return { major, minor, patch, prerelease };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function comparePrereleaseIdentifier(left: string, right: string): number {
|
|
46
|
-
const leftIsNumeric = /^\d+$/.test(left);
|
|
47
|
-
const rightIsNumeric = /^\d+$/.test(right);
|
|
48
|
-
|
|
49
|
-
if (leftIsNumeric && rightIsNumeric) {
|
|
50
|
-
return Number.parseInt(left, 10) - Number.parseInt(right, 10);
|
|
51
|
-
}
|
|
52
|
-
if (leftIsNumeric) {
|
|
53
|
-
return -1;
|
|
54
|
-
}
|
|
55
|
-
if (rightIsNumeric) {
|
|
56
|
-
return 1;
|
|
57
|
-
}
|
|
58
|
-
return left.localeCompare(right);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function compareVersions(left: string, right: string): number {
|
|
62
|
-
const leftParsed = parseVersion(left);
|
|
63
|
-
const rightParsed = parseVersion(right);
|
|
64
|
-
|
|
65
|
-
if (!leftParsed || !rightParsed) {
|
|
66
|
-
return left.localeCompare(right, undefined, { numeric: true });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (leftParsed.major !== rightParsed.major) {
|
|
70
|
-
return leftParsed.major - rightParsed.major;
|
|
71
|
-
}
|
|
72
|
-
if (leftParsed.minor !== rightParsed.minor) {
|
|
73
|
-
return leftParsed.minor - rightParsed.minor;
|
|
74
|
-
}
|
|
75
|
-
if (leftParsed.patch !== rightParsed.patch) {
|
|
76
|
-
return leftParsed.patch - rightParsed.patch;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
leftParsed.prerelease.length === 0 &&
|
|
81
|
-
rightParsed.prerelease.length === 0
|
|
82
|
-
) {
|
|
83
|
-
return 0;
|
|
84
|
-
}
|
|
85
|
-
if (leftParsed.prerelease.length === 0) {
|
|
86
|
-
return 1;
|
|
87
|
-
}
|
|
88
|
-
if (rightParsed.prerelease.length === 0) {
|
|
89
|
-
return -1;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const length = Math.max(
|
|
93
|
-
leftParsed.prerelease.length,
|
|
94
|
-
rightParsed.prerelease.length
|
|
95
|
-
);
|
|
96
|
-
for (let index = 0; index < length; index += 1) {
|
|
97
|
-
const leftPart = leftParsed.prerelease[index];
|
|
98
|
-
const rightPart = rightParsed.prerelease[index];
|
|
99
|
-
|
|
100
|
-
if (!leftPart && !rightPart) {
|
|
101
|
-
return 0;
|
|
102
|
-
}
|
|
103
|
-
if (!leftPart) {
|
|
104
|
-
return -1;
|
|
105
|
-
}
|
|
106
|
-
if (!rightPart) {
|
|
107
|
-
return 1;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const comparison = comparePrereleaseIdentifier(leftPart, rightPart);
|
|
111
|
-
if (comparison !== 0) {
|
|
112
|
-
return comparison;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return 0;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function resolveCacheDirectory(): string {
|
|
120
|
-
const override = process.env.SYNCULAR_CLI_CACHE_DIR?.trim();
|
|
121
|
-
if (override) {
|
|
122
|
-
return override;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const xdgCache = process.env.XDG_CACHE_HOME?.trim();
|
|
126
|
-
if (xdgCache) {
|
|
127
|
-
return join(xdgCache, 'syncular', 'cli');
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const osPlatform = platform();
|
|
131
|
-
if (osPlatform === 'darwin') {
|
|
132
|
-
return join(homedir(), 'Library', 'Caches', 'syncular', 'cli');
|
|
133
|
-
}
|
|
134
|
-
if (osPlatform === 'win32') {
|
|
135
|
-
const localAppData = process.env.LOCALAPPDATA?.trim();
|
|
136
|
-
if (localAppData) {
|
|
137
|
-
return join(localAppData, 'syncular', 'cli');
|
|
138
|
-
}
|
|
139
|
-
return join(homedir(), 'AppData', 'Local', 'syncular', 'cli');
|
|
140
|
-
}
|
|
141
|
-
return join(homedir(), '.cache', 'syncular', 'cli');
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function resolveStatePath(): string {
|
|
145
|
-
return join(resolveCacheDirectory(), UPDATE_STATE_FILE);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function readUpdateCheckState(): UpdateCheckState {
|
|
149
|
-
try {
|
|
150
|
-
const state = JSON.parse(
|
|
151
|
-
readFileSync(resolveStatePath(), 'utf8')
|
|
152
|
-
) as UpdateCheckState;
|
|
153
|
-
return state;
|
|
154
|
-
} catch {
|
|
155
|
-
return {};
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function writeUpdateCheckState(state: UpdateCheckState): void {
|
|
160
|
-
try {
|
|
161
|
-
const statePath = resolveStatePath();
|
|
162
|
-
mkdirSync(dirname(statePath), { recursive: true });
|
|
163
|
-
writeFileSync(statePath, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
|
|
164
|
-
} catch {
|
|
165
|
-
// Ignore cache write failures.
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function resolveCurrentVersion(): string | null {
|
|
170
|
-
const fromNpmWrapper = process.env.SYNCULAR_CLI_NPM_VERSION?.trim();
|
|
171
|
-
if (fromNpmWrapper && fromNpmWrapper.length > 0) {
|
|
172
|
-
return fromNpmWrapper;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const fallback = CLI_VERSION.trim();
|
|
176
|
-
if (fallback.length === 0 || fallback === '0.0.0') {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
return fallback;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function shouldCheckNow(state: UpdateCheckState, nowMs: number): boolean {
|
|
183
|
-
if (!state.lastCheckedAt) {
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const lastCheckedMs = Date.parse(state.lastCheckedAt);
|
|
188
|
-
if (Number.isNaN(lastCheckedMs)) {
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return nowMs - lastCheckedMs >= UPDATE_CHECK_INTERVAL_MS;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
async function fetchLatestPublishedVersion(): Promise<string | null> {
|
|
196
|
-
const controller = new AbortController();
|
|
197
|
-
const timeout = setTimeout(() => controller.abort(), UPDATE_CHECK_TIMEOUT_MS);
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
const response = await fetch(NPM_LATEST_URL, {
|
|
201
|
-
headers: {
|
|
202
|
-
accept: 'application/json',
|
|
203
|
-
'user-agent': '@syncular/cli',
|
|
204
|
-
},
|
|
205
|
-
signal: controller.signal,
|
|
206
|
-
});
|
|
207
|
-
if (!response.ok) {
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const payload = (await response.json()) as { version?: unknown };
|
|
212
|
-
const version =
|
|
213
|
-
typeof payload.version === 'string' ? payload.version.trim() : '';
|
|
214
|
-
return version.length > 0 ? version : null;
|
|
215
|
-
} catch {
|
|
216
|
-
return null;
|
|
217
|
-
} finally {
|
|
218
|
-
clearTimeout(timeout);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function shouldNotify(
|
|
223
|
-
state: UpdateCheckState,
|
|
224
|
-
currentVersion: string,
|
|
225
|
-
latestVersion: string
|
|
226
|
-
): boolean {
|
|
227
|
-
if (compareVersions(latestVersion, currentVersion) <= 0) {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
return state.notifiedVersion !== latestVersion;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function printUpdateNotice(
|
|
234
|
-
currentVersion: string,
|
|
235
|
-
latestVersion: string
|
|
236
|
-
): void {
|
|
237
|
-
console.error('');
|
|
238
|
-
console.error(
|
|
239
|
-
`[syncular] Update available: ${currentVersion} -> ${latestVersion}`
|
|
240
|
-
);
|
|
241
|
-
console.error('[syncular] Run: npm i -g @syncular/cli@latest');
|
|
242
|
-
console.error('');
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
export async function maybeNotifyAboutUpdate(
|
|
246
|
-
flags: Set<string>
|
|
247
|
-
): Promise<void> {
|
|
248
|
-
if (flags.has('--no-update-check')) {
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
if (process.env.SYNCULAR_CLI_DISABLE_UPDATE_CHECK === '1') {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
if (!process.stdout.isTTY && !process.stderr.isTTY) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const currentVersion = resolveCurrentVersion();
|
|
259
|
-
if (!currentVersion) {
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const nowMs = Date.now();
|
|
264
|
-
const state = readUpdateCheckState();
|
|
265
|
-
let latestVersion =
|
|
266
|
-
typeof state.latestVersion === 'string' ? state.latestVersion : null;
|
|
267
|
-
|
|
268
|
-
if (shouldCheckNow(state, nowMs)) {
|
|
269
|
-
const fetchedVersion = await fetchLatestPublishedVersion();
|
|
270
|
-
state.lastCheckedAt = new Date(nowMs).toISOString();
|
|
271
|
-
|
|
272
|
-
if (fetchedVersion) {
|
|
273
|
-
latestVersion = fetchedVersion;
|
|
274
|
-
state.latestVersion = fetchedVersion;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
writeUpdateCheckState(state);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (!latestVersion) {
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
if (!shouldNotify(state, currentVersion, latestVersion)) {
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
printUpdateNotice(currentVersion, latestVersion);
|
|
288
|
-
state.notifiedVersion = latestVersion;
|
|
289
|
-
if (!state.lastCheckedAt) {
|
|
290
|
-
state.lastCheckedAt = new Date(nowMs).toISOString();
|
|
291
|
-
}
|
|
292
|
-
if (!state.latestVersion) {
|
|
293
|
-
state.latestVersion = latestVersion;
|
|
294
|
-
}
|
|
295
|
-
writeUpdateCheckState(state);
|
|
296
|
-
}
|