@syncular/cli 0.0.0-44 → 0.0.0-48
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/npm/install.mjs +26 -0
- package/npm/run.mjs +32 -0
- package/npm/shared.mjs +271 -0
- package/package.json +14 -15
- package/src/args.ts +0 -112
- 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 -700
- package/src/commands/auth.ts +0 -514
- package/src/commands/build.ts +0 -251
- package/src/commands/console.ts +0 -288
- package/src/commands/demo.ts +0 -1154
- package/src/commands/doctor.tsx +0 -133
- package/src/commands/migrate.ts +0 -312
- package/src/commands/project.ts +0 -437
- package/src/commands/target.ts +0 -62
- package/src/commands/typegen.ts +0 -406
- package/src/constants.ts +0 -4
- package/src/control-plane.ts +0 -23
- package/src/dev-logging.tsx +0 -415
- package/src/extensions/index.ts +0 -1
- package/src/extensions/manifest.ts +0 -37
- package/src/help.tsx +0 -236
- package/src/index.ts +0 -4
- package/src/interactive.tsx +0 -306
- package/src/main.tsx +0 -257
- 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/dev-logging.tsx
DELETED
|
@@ -1,415 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process';
|
|
2
|
-
import { dirname } from 'node:path';
|
|
3
|
-
import process from 'node:process';
|
|
4
|
-
import type {
|
|
5
|
-
SpaceDevLogEvent,
|
|
6
|
-
SpaceDevLogger,
|
|
7
|
-
} from '@syncular/cli-runtime-dev';
|
|
8
|
-
import { Box, renderToString, Text } from 'ink';
|
|
9
|
-
import type { ReactNode } from 'react';
|
|
10
|
-
import {
|
|
11
|
-
configureSyncTelemetry,
|
|
12
|
-
getSyncTelemetry,
|
|
13
|
-
type SyncTelemetry,
|
|
14
|
-
type SyncTelemetryEvent,
|
|
15
|
-
} from 'syncular/core';
|
|
16
|
-
|
|
17
|
-
function writeStdout(node: ReactNode): void {
|
|
18
|
-
const rendered = renderToString(node, {
|
|
19
|
-
columns: Math.max(process.stdout.columns ?? 120, 120),
|
|
20
|
-
});
|
|
21
|
-
process.stdout.write(rendered);
|
|
22
|
-
if (!rendered.endsWith('\n')) {
|
|
23
|
-
process.stdout.write('\n');
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function writeStderr(node: ReactNode): void {
|
|
28
|
-
const rendered = renderToString(node, {
|
|
29
|
-
columns: Math.max(process.stderr.columns ?? 120, 120),
|
|
30
|
-
});
|
|
31
|
-
process.stderr.write(rendered);
|
|
32
|
-
if (!rendered.endsWith('\n')) {
|
|
33
|
-
process.stderr.write('\n');
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function nowStamp(): string {
|
|
38
|
-
return new Date().toISOString().slice(11, 19);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function clearTerminalScreen(): void {
|
|
42
|
-
if (!process.stdout.isTTY) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
process.stdout.write('\x1b[2J\x1b[H');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function openInBrowser(url: string): Promise<void> {
|
|
49
|
-
await new Promise<void>((resolvePromise, rejectPromise) => {
|
|
50
|
-
let command = '';
|
|
51
|
-
let commandArgs: string[] = [];
|
|
52
|
-
|
|
53
|
-
if (process.platform === 'darwin') {
|
|
54
|
-
command = 'open';
|
|
55
|
-
commandArgs = [url];
|
|
56
|
-
} else if (process.platform === 'win32') {
|
|
57
|
-
command = 'cmd';
|
|
58
|
-
commandArgs = ['/c', 'start', '', url];
|
|
59
|
-
} else {
|
|
60
|
-
command = 'xdg-open';
|
|
61
|
-
commandArgs = [url];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const child = spawn(command, commandArgs, {
|
|
65
|
-
stdio: 'ignore',
|
|
66
|
-
detached: true,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
child.once('error', rejectPromise);
|
|
70
|
-
child.once('spawn', () => {
|
|
71
|
-
child.unref();
|
|
72
|
-
resolvePromise();
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function levelColor(
|
|
78
|
-
level: 'info' | 'warn' | 'error'
|
|
79
|
-
): 'cyan' | 'yellow' | 'redBright' {
|
|
80
|
-
if (level === 'error') return 'redBright';
|
|
81
|
-
if (level === 'warn') return 'yellow';
|
|
82
|
-
return 'cyan';
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function detectLevelFromSyncEvent(
|
|
86
|
-
event: SyncTelemetryEvent
|
|
87
|
-
): 'info' | 'warn' | 'error' {
|
|
88
|
-
const level = event.level ?? (event.error ? 'error' : 'info');
|
|
89
|
-
if (level === 'warn') return 'warn';
|
|
90
|
-
if (level === 'error' || level === 'fatal') return 'error';
|
|
91
|
-
return 'info';
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function summarizeSyncEvent(event: SyncTelemetryEvent): string {
|
|
95
|
-
if (event.event === 'sync.push') {
|
|
96
|
-
const status = typeof event.status === 'string' ? event.status : 'unknown';
|
|
97
|
-
const operationCount =
|
|
98
|
-
typeof event.operationCount === 'number' ? event.operationCount : 0;
|
|
99
|
-
const commitSeq =
|
|
100
|
-
typeof event.commitSeq === 'number' ? ` commit#${event.commitSeq}` : '';
|
|
101
|
-
const duration =
|
|
102
|
-
typeof event.durationMs === 'number' ? ` ${event.durationMs}ms` : '';
|
|
103
|
-
return `push ${status} ops=${operationCount}${commitSeq}${duration}`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (event.event === 'sync.pull') {
|
|
107
|
-
const subscriptionCount =
|
|
108
|
-
typeof event.subscriptionCount === 'number' ? event.subscriptionCount : 0;
|
|
109
|
-
const cursor =
|
|
110
|
-
typeof event.clientCursor === 'number'
|
|
111
|
-
? ` cursor=${event.clientCursor}`
|
|
112
|
-
: '';
|
|
113
|
-
const duration =
|
|
114
|
-
typeof event.durationMs === 'number' ? ` ${event.durationMs}ms` : '';
|
|
115
|
-
return `pull subs=${subscriptionCount}${cursor}${duration}`;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (event.event === 'sync.realtime.connect') {
|
|
119
|
-
return 'realtime connected';
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (event.event === 'sync.realtime.disconnect') {
|
|
123
|
-
return 'realtime disconnected';
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (event.event === 'sync.realtime.rejected') {
|
|
127
|
-
const reason =
|
|
128
|
-
typeof event.reason === 'string' ? ` reason=${event.reason}` : '';
|
|
129
|
-
return `realtime rejected${reason}`;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (event.event === 'sync.exception') {
|
|
133
|
-
return `exception ${String(event.error ?? 'unknown error')}`;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const duration =
|
|
137
|
-
typeof event.durationMs === 'number' ? ` ${event.durationMs}ms` : '';
|
|
138
|
-
return `${event.event}${duration}`;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function printSyncEventLine(args: {
|
|
142
|
-
level: 'info' | 'warn' | 'error';
|
|
143
|
-
eventName: string;
|
|
144
|
-
summary: string;
|
|
145
|
-
actorId?: string;
|
|
146
|
-
}): void {
|
|
147
|
-
const tag = args.level.toUpperCase();
|
|
148
|
-
const color = levelColor(args.level);
|
|
149
|
-
writeStdout(
|
|
150
|
-
<Box>
|
|
151
|
-
<Text dimColor>[{nowStamp()}] </Text>
|
|
152
|
-
<Text color={color} bold>
|
|
153
|
-
{tag.padEnd(5)}
|
|
154
|
-
</Text>
|
|
155
|
-
<Text color="magentaBright"> sync </Text>
|
|
156
|
-
<Text color="gray">{args.eventName} </Text>
|
|
157
|
-
<Text>{args.summary}</Text>
|
|
158
|
-
{args.actorId ? <Text dimColor> actor={args.actorId}</Text> : null}
|
|
159
|
-
</Box>
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function summarizeDevEvent(event: SpaceDevLogEvent): string {
|
|
164
|
-
if (event.type === 'reloading') {
|
|
165
|
-
return event.reason ?? 'source change';
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (event.type === 'watching') {
|
|
169
|
-
return event.watchRoot ?? '(watch root)';
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (event.type === 'startup_failed' || event.type === 'restart_failed') {
|
|
173
|
-
const detail = event.error ?? event.message;
|
|
174
|
-
const firstLine = detail.split('\n')[0];
|
|
175
|
-
return firstLine ? firstLine.trim() : 'runtime error';
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (event.type === 'starting') {
|
|
179
|
-
return `${event.reason ?? 'start'} -> ${event.host ?? '127.0.0.1'}:${String(event.port ?? 0)}`;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (event.type === 'stopping') {
|
|
183
|
-
return event.url ?? 'runtime server';
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (event.type === 'stopped') {
|
|
187
|
-
return event.url ?? 'runtime server';
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return event.message;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function renderDatabaseDetails(event: SpaceDevLogEvent): ReactNode {
|
|
194
|
-
if (!event.provider) {
|
|
195
|
-
return <Text color="gray">database: unknown</Text>;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (event.provider === 'sqlite') {
|
|
199
|
-
return (
|
|
200
|
-
<Text color="gray">
|
|
201
|
-
database: sqlite path={event.databaseDetails ?? '(unknown)'}
|
|
202
|
-
</Text>
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return (
|
|
207
|
-
<Text color="gray">
|
|
208
|
-
database: {event.provider}{' '}
|
|
209
|
-
{event.databaseDetails ? `(${event.databaseDetails})` : ''}
|
|
210
|
-
</Text>
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function renderStartedPanel(event: SpaceDevLogEvent): void {
|
|
215
|
-
const projectPath =
|
|
216
|
-
event.cwd || (event.modulePath ? dirname(event.modulePath) : '(unknown)');
|
|
217
|
-
const listenUrl =
|
|
218
|
-
event.url ||
|
|
219
|
-
`http://${event.host ?? '127.0.0.1'}:${String(event.port ?? 0)}`;
|
|
220
|
-
const consoleUrl = event.consoleUrl ?? `${listenUrl}/console`;
|
|
221
|
-
|
|
222
|
-
writeStdout(
|
|
223
|
-
<Box
|
|
224
|
-
flexDirection="column"
|
|
225
|
-
borderStyle="round"
|
|
226
|
-
borderColor="greenBright"
|
|
227
|
-
paddingX={1}
|
|
228
|
-
paddingY={0}
|
|
229
|
-
>
|
|
230
|
-
<Text color="greenBright" bold>
|
|
231
|
-
syncular dev started
|
|
232
|
-
</Text>
|
|
233
|
-
<Text color="gray">project: {projectPath}</Text>
|
|
234
|
-
<Text color="gray">module: {event.module ?? '(unknown)'}</Text>
|
|
235
|
-
<Text color="gray">listen: {listenUrl}</Text>
|
|
236
|
-
<Text color="gray">console: {consoleUrl}</Text>
|
|
237
|
-
{renderDatabaseDetails(event)}
|
|
238
|
-
</Box>
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function printDevEvent(event: SpaceDevLogEvent): void {
|
|
243
|
-
if (event.type === 'started') {
|
|
244
|
-
clearTerminalScreen();
|
|
245
|
-
renderStartedPanel(event);
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const color = levelColor(event.level);
|
|
250
|
-
const tag = event.level.toUpperCase();
|
|
251
|
-
writeStdout(
|
|
252
|
-
<Box flexDirection="column">
|
|
253
|
-
<Box>
|
|
254
|
-
<Text dimColor>[{nowStamp()}] </Text>
|
|
255
|
-
<Text color={color} bold>
|
|
256
|
-
{tag.padEnd(5)}
|
|
257
|
-
</Text>
|
|
258
|
-
<Text color="cyanBright"> dev </Text>
|
|
259
|
-
<Text color="gray">{event.type} </Text>
|
|
260
|
-
<Text>{summarizeDevEvent(event)}</Text>
|
|
261
|
-
</Box>
|
|
262
|
-
</Box>
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
export function createSpacesDevLogger(options?: {
|
|
267
|
-
openConsoleOnStarted?: boolean;
|
|
268
|
-
}): SpaceDevLogger {
|
|
269
|
-
let consoleOpened = false;
|
|
270
|
-
return {
|
|
271
|
-
info(message) {
|
|
272
|
-
printDevEvent({
|
|
273
|
-
level: 'info',
|
|
274
|
-
type: 'starting',
|
|
275
|
-
message,
|
|
276
|
-
});
|
|
277
|
-
},
|
|
278
|
-
error(message) {
|
|
279
|
-
writeStderr(
|
|
280
|
-
<Box>
|
|
281
|
-
<Text dimColor>[{nowStamp()}] </Text>
|
|
282
|
-
<Text color="redBright" bold>
|
|
283
|
-
ERROR
|
|
284
|
-
</Text>
|
|
285
|
-
<Text color="redBright"> dev </Text>
|
|
286
|
-
<Text>{message}</Text>
|
|
287
|
-
</Box>
|
|
288
|
-
);
|
|
289
|
-
},
|
|
290
|
-
event(event) {
|
|
291
|
-
printDevEvent(event);
|
|
292
|
-
if (options?.openConsoleOnStarted && event.type === 'started') {
|
|
293
|
-
if (consoleOpened) {
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
consoleOpened = true;
|
|
298
|
-
const listenUrl =
|
|
299
|
-
event.url ||
|
|
300
|
-
`http://${event.host ?? '127.0.0.1'}:${String(event.port ?? 0)}`;
|
|
301
|
-
const consoleUrl = event.consoleUrl ?? `${listenUrl}/console`;
|
|
302
|
-
|
|
303
|
-
void openInBrowser(consoleUrl).catch((error: unknown) => {
|
|
304
|
-
const message =
|
|
305
|
-
error instanceof Error ? error.message : String(error);
|
|
306
|
-
writeStderr(
|
|
307
|
-
<Box>
|
|
308
|
-
<Text dimColor>[{nowStamp()}] </Text>
|
|
309
|
-
<Text color="yellow">WARN </Text>
|
|
310
|
-
<Text color="yellow">dev </Text>
|
|
311
|
-
<Text>unable to open browser automatically: {message}</Text>
|
|
312
|
-
</Box>
|
|
313
|
-
);
|
|
314
|
-
writeStderr(
|
|
315
|
-
<Box>
|
|
316
|
-
<Text dimColor>[{nowStamp()}] </Text>
|
|
317
|
-
<Text color="yellow">WARN </Text>
|
|
318
|
-
<Text color="yellow">dev </Text>
|
|
319
|
-
<Text>open manually: {consoleUrl}</Text>
|
|
320
|
-
</Box>
|
|
321
|
-
);
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
export function configureSpacesDevTelemetry(): () => void {
|
|
329
|
-
const previousTelemetry = getSyncTelemetry();
|
|
330
|
-
let lastPullCursor: number | null = null;
|
|
331
|
-
let lastPullLogAt = 0;
|
|
332
|
-
let suppressedPullCount = 0;
|
|
333
|
-
|
|
334
|
-
const telemetry: SyncTelemetry = {
|
|
335
|
-
log(event) {
|
|
336
|
-
if (event.event === 'console.stats') {
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (event.event === 'sync.pull') {
|
|
341
|
-
const cursor =
|
|
342
|
-
typeof event.clientCursor === 'number' ? event.clientCursor : null;
|
|
343
|
-
const now = Date.now();
|
|
344
|
-
const isRepetitive =
|
|
345
|
-
cursor !== null &&
|
|
346
|
-
cursor === lastPullCursor &&
|
|
347
|
-
now - lastPullLogAt < 2_000;
|
|
348
|
-
|
|
349
|
-
if (isRepetitive) {
|
|
350
|
-
suppressedPullCount += 1;
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
lastPullCursor = cursor;
|
|
355
|
-
lastPullLogAt = now;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
const summary = summarizeSyncEvent(event);
|
|
359
|
-
const level = detectLevelFromSyncEvent(event);
|
|
360
|
-
const actorId =
|
|
361
|
-
typeof event.userId === 'string' && event.userId.length > 0
|
|
362
|
-
? event.userId
|
|
363
|
-
: undefined;
|
|
364
|
-
const eventName = event.event;
|
|
365
|
-
|
|
366
|
-
if (suppressedPullCount > 0 && event.event !== 'sync.pull') {
|
|
367
|
-
printSyncEventLine({
|
|
368
|
-
level: 'info',
|
|
369
|
-
eventName: 'sync.pull',
|
|
370
|
-
summary: `suppressed ${suppressedPullCount} repetitive pull logs`,
|
|
371
|
-
});
|
|
372
|
-
suppressedPullCount = 0;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
printSyncEventLine({
|
|
376
|
-
level,
|
|
377
|
-
eventName,
|
|
378
|
-
summary,
|
|
379
|
-
actorId,
|
|
380
|
-
});
|
|
381
|
-
},
|
|
382
|
-
tracer: previousTelemetry.tracer,
|
|
383
|
-
metrics: previousTelemetry.metrics,
|
|
384
|
-
captureException(error, context) {
|
|
385
|
-
const message =
|
|
386
|
-
error instanceof Error
|
|
387
|
-
? error.message
|
|
388
|
-
: `Unknown error: ${String(error)}`;
|
|
389
|
-
writeStderr(
|
|
390
|
-
<Box flexDirection="column">
|
|
391
|
-
<Box>
|
|
392
|
-
<Text dimColor>[{nowStamp()}] </Text>
|
|
393
|
-
<Text color="redBright" bold>
|
|
394
|
-
ERROR
|
|
395
|
-
</Text>
|
|
396
|
-
<Text color="magentaBright"> sync </Text>
|
|
397
|
-
<Text>{message}</Text>
|
|
398
|
-
</Box>
|
|
399
|
-
{context ? (
|
|
400
|
-
<Box paddingLeft={16}>
|
|
401
|
-
<Text color="gray">{JSON.stringify(context)}</Text>
|
|
402
|
-
</Box>
|
|
403
|
-
) : null}
|
|
404
|
-
</Box>
|
|
405
|
-
);
|
|
406
|
-
previousTelemetry.captureException(error, context);
|
|
407
|
-
},
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
configureSyncTelemetry(telemetry);
|
|
411
|
-
|
|
412
|
-
return () => {
|
|
413
|
-
configureSyncTelemetry(previousTelemetry);
|
|
414
|
-
};
|
|
415
|
-
}
|
package/src/extensions/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './manifest';
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { contractWorkerBuildpack } from '@syncular/cli-buildpack-contract-worker';
|
|
2
|
-
import type { ContractBuildpack } from '@syncular/cli-core';
|
|
3
|
-
import { spacesAppTemplate } from '@syncular/cli-template-spaces-app';
|
|
4
|
-
import { spacesDemoTemplate } from '@syncular/cli-template-spaces-demo';
|
|
5
|
-
import { syncularDemoTemplate } from '@syncular/cli-template-syncular-demo';
|
|
6
|
-
import { syncularLibrariesTemplate } from '@syncular/cli-template-syncular-libraries';
|
|
7
|
-
|
|
8
|
-
interface BuildpackExtensionManifestEntry {
|
|
9
|
-
packageName: string;
|
|
10
|
-
buildpack: ContractBuildpack;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const TEMPLATE_EXTENSION_MANIFEST = {
|
|
14
|
-
spacesApp: {
|
|
15
|
-
packageName: '@syncular/cli-template-spaces-app',
|
|
16
|
-
template: spacesAppTemplate,
|
|
17
|
-
},
|
|
18
|
-
spacesDemo: {
|
|
19
|
-
packageName: '@syncular/cli-template-spaces-demo',
|
|
20
|
-
template: spacesDemoTemplate,
|
|
21
|
-
},
|
|
22
|
-
syncularDemo: {
|
|
23
|
-
packageName: '@syncular/cli-template-syncular-demo',
|
|
24
|
-
template: syncularDemoTemplate,
|
|
25
|
-
},
|
|
26
|
-
syncularLibraries: {
|
|
27
|
-
packageName: '@syncular/cli-template-syncular-libraries',
|
|
28
|
-
template: syncularLibrariesTemplate,
|
|
29
|
-
},
|
|
30
|
-
} as const;
|
|
31
|
-
|
|
32
|
-
export const BUILDPACK_EXTENSION_MANIFEST = {
|
|
33
|
-
contractWorker: {
|
|
34
|
-
packageName: '@syncular/cli-buildpack-contract-worker',
|
|
35
|
-
buildpack: contractWorkerBuildpack,
|
|
36
|
-
},
|
|
37
|
-
} as const satisfies Record<string, BuildpackExtensionManifestEntry>;
|
package/src/help.tsx
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import process from 'node:process';
|
|
2
|
-
import { Box, renderToString, Text } from 'ink';
|
|
3
|
-
import type { ReactElement } from 'react';
|
|
4
|
-
import { listBuildpackIds } from './buildpacks';
|
|
5
|
-
import { USAGE_LINES } from './command-registry';
|
|
6
|
-
import { CLI_NAME, CLI_VERSION } from './constants';
|
|
7
|
-
import { listTemplateIds } from './templates';
|
|
8
|
-
|
|
9
|
-
interface HelpSection {
|
|
10
|
-
title: string;
|
|
11
|
-
lines: string[];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const TEMPLATE_ID_LIST = listTemplateIds().join('|');
|
|
15
|
-
const DEFAULT_BUILDPACK_ID = listBuildpackIds()[0] ?? 'contract-worker';
|
|
16
|
-
|
|
17
|
-
const HELP_SECTIONS: HelpSection[] = [
|
|
18
|
-
{
|
|
19
|
-
title: 'Auth Flags',
|
|
20
|
-
lines: [
|
|
21
|
-
'--control-plane <url> Control plane base URL',
|
|
22
|
-
'--token <jwt> Clerk CLI JWT token',
|
|
23
|
-
'--token-stdin Read token from stdin',
|
|
24
|
-
'--json whoami/create-space: print JSON output',
|
|
25
|
-
'--callback-host <host> Browser callback host for login (default: 127.0.0.1)',
|
|
26
|
-
'--callback-port <port> Browser callback port for login (default: random)',
|
|
27
|
-
'--auth-url <url> Browser auth bridge URL (default: <control-plane>/cli-login)',
|
|
28
|
-
'--timeout-seconds <n> Login browser wait timeout (default: 180)',
|
|
29
|
-
],
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
title: 'Create Space Flags',
|
|
33
|
-
lines: [
|
|
34
|
-
'--name <name> Space name',
|
|
35
|
-
'--database-provider <id> sqlite|neon|postgres (default: sqlite)',
|
|
36
|
-
'--connection-string <url> Required when database-provider is neon/postgres',
|
|
37
|
-
'--region <id> auto|enam|wnam|weur|eeur|apac|oc (default: auto)',
|
|
38
|
-
'--json Print response as JSON (console token redacted)',
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
title: 'Create Flags',
|
|
43
|
-
lines: [
|
|
44
|
-
`--template <id> Template id: ${TEMPLATE_ID_LIST}`,
|
|
45
|
-
'--dir <path> Scaffold target directory (template-specific default)',
|
|
46
|
-
'--name <name> Project display/name override (spaces-app only)',
|
|
47
|
-
'--targets <csv> syncular-libraries targets (server,react,vanilla,expo,react-native,electron,proxy-api)',
|
|
48
|
-
'--server-dialect <id> syncular-libraries server dialect sqlite|postgres',
|
|
49
|
-
'--react-dialect <id> syncular-libraries react dialect wa-sqlite|pglite|bun-sqlite|better-sqlite3|sqlite3',
|
|
50
|
-
'--vanilla-dialect <id> syncular-libraries vanilla dialect wa-sqlite|pglite|bun-sqlite|better-sqlite3|sqlite3',
|
|
51
|
-
'--electron-dialect <id> syncular-libraries electron dialect electron-sqlite|better-sqlite3',
|
|
52
|
-
'--force <true|false> Overwrite scaffold files (default: false)',
|
|
53
|
-
],
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
title: 'Dev Flags',
|
|
57
|
-
lines: [
|
|
58
|
-
'--host <host> Bind host (default: 127.0.0.1)',
|
|
59
|
-
'--port <port> Bind port (default: 4312)',
|
|
60
|
-
'--db-provider <kind> Local DB provider sqlite|neon|postgres',
|
|
61
|
-
'--db <path> Local sqlite db path override',
|
|
62
|
-
'--connection-string <url> Local Postgres/Neon connection string override',
|
|
63
|
-
'--watch <true|false> Watch source files and restart (default: true)',
|
|
64
|
-
'--open <true|false> Open embedded console in browser after start',
|
|
65
|
-
'--console-token <token> Bearer token for /api/console',
|
|
66
|
-
],
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
title: 'Shared Flags',
|
|
70
|
-
lines: [
|
|
71
|
-
'--space <id> Space id to deploy/verify/list/rollback',
|
|
72
|
-
'--target <id> Target profile spaces',
|
|
73
|
-
'--control-plane <url> Control plane base URL',
|
|
74
|
-
'--control-token <token> Bearer token for control-plane auth',
|
|
75
|
-
'--actor-id <id> Actor id fallback when token is missing (dev only)',
|
|
76
|
-
],
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
title: 'Migrate Status Flags',
|
|
80
|
-
lines: [
|
|
81
|
-
'--config <path> Config file path (default: syncular.config.json)',
|
|
82
|
-
],
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
title: 'Typegen Flags',
|
|
86
|
-
lines: [
|
|
87
|
-
'--config <path> Config file path (default: syncular.config.ts)',
|
|
88
|
-
'--out <path> Output file path (default: ./src/types.generated.ts)',
|
|
89
|
-
'--dialect <id> sqlite|postgres (default: sqlite)',
|
|
90
|
-
'--tables <csv> Restrict generation to table names',
|
|
91
|
-
'--extends-sync-client-db <true|false> Extend SyncClientDb (default: true)',
|
|
92
|
-
'--include-version-history <true|false> Include versioned DB interfaces (default: false)',
|
|
93
|
-
'--syncular-import-type <id> scoped|umbrella (default: umbrella)',
|
|
94
|
-
],
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
title: 'Migrate Up Flags',
|
|
98
|
-
lines: [
|
|
99
|
-
'--config <path> Config file path (default: syncular.config.json)',
|
|
100
|
-
'--on-checksum-mismatch <id> error|reset (default: error)',
|
|
101
|
-
'--dry-run <true|false> Plan migration without applying',
|
|
102
|
-
'--yes <true|false> Confirm reset mode when using --on-checksum-mismatch reset',
|
|
103
|
-
],
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
title: 'Console Flags',
|
|
107
|
-
lines: [
|
|
108
|
-
'--host <host> Bind host (default: 127.0.0.1)',
|
|
109
|
-
'--port <port> Bind port (default: 4310, 0 for random)',
|
|
110
|
-
'--open <true|false> Open browser after server starts',
|
|
111
|
-
'--server-url <url> Preconfigure console API server URL',
|
|
112
|
-
'--token <token> Preconfigure console API token',
|
|
113
|
-
'--token-env <name> Read console API token from env var',
|
|
114
|
-
],
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
title: 'Build Flags',
|
|
118
|
-
lines: [
|
|
119
|
-
'--target <id> Target profile spaces',
|
|
120
|
-
`--buildpack <id> Buildpack id (default: ${DEFAULT_BUILDPACK_ID})`,
|
|
121
|
-
'--config <path> Contract config path (target default)',
|
|
122
|
-
'--entry <path> Explicit worker entry override (advanced)',
|
|
123
|
-
'--out <path> Artifact output path',
|
|
124
|
-
'--manifest <path> Build manifest output path',
|
|
125
|
-
'--force <true|false> Overwrite output files (default: false)',
|
|
126
|
-
],
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
title: 'Eject Flags',
|
|
130
|
-
lines: [
|
|
131
|
-
'--target <id> Target profile spaces',
|
|
132
|
-
`--buildpack <id> Buildpack id (default: ${DEFAULT_BUILDPACK_ID})`,
|
|
133
|
-
'--config <path> Contract config path (target default)',
|
|
134
|
-
'--entry <path> Explicit worker entry override (advanced)',
|
|
135
|
-
'--out-dir <path> Eject output directory',
|
|
136
|
-
'--force <true|false> Overwrite output files (default: false)',
|
|
137
|
-
],
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
title: 'Target Flags',
|
|
141
|
-
lines: ['--set <id> Set default target profile (spaces)'],
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
title: 'Deploy Flags',
|
|
145
|
-
lines: [
|
|
146
|
-
'--target <id> Target profile spaces (default from state)',
|
|
147
|
-
'--config <path> Contract config path (target default)',
|
|
148
|
-
'--entry <path> Explicit worker entry override (advanced)',
|
|
149
|
-
'--script-name <name> Override target script name',
|
|
150
|
-
'--source <label> Deployment source label (spaces target only, default: syncular-cli)',
|
|
151
|
-
'--dry-run <true|false> Bundle + metadata validation only (no deploy)',
|
|
152
|
-
],
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
title: 'Verify Flags',
|
|
156
|
-
lines: [
|
|
157
|
-
'--target <id> Target profile spaces (default from state)',
|
|
158
|
-
'--base-url <url> Runtime base URL (default from control-plane runtime)',
|
|
159
|
-
],
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
title: 'Deployments Flags',
|
|
163
|
-
lines: [
|
|
164
|
-
'--limit <n> Number of deployment records to list (default: 20)',
|
|
165
|
-
],
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
title: 'Rollback Flags',
|
|
169
|
-
lines: [
|
|
170
|
-
'--to <deploymentId> Target deployment id to rollback to',
|
|
171
|
-
'--reason <text> Optional rollback reason',
|
|
172
|
-
],
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
title: 'Global Flags',
|
|
176
|
-
lines: [
|
|
177
|
-
'--interactive Force interactive TUI',
|
|
178
|
-
'--no-interactive Disable interactive TUI',
|
|
179
|
-
'--forms Enable interactive command input forms',
|
|
180
|
-
'--help Show help',
|
|
181
|
-
'--version Show version',
|
|
182
|
-
],
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
title: 'Env Fallbacks',
|
|
186
|
-
lines: [
|
|
187
|
-
'SPACES_CONTROL_PLANE_BASE_URL, SPACES_TEST_ACTOR_ID,',
|
|
188
|
-
'SPACES_CONTROL_PLANE_TOKEN, SPACES_CONTROL_TOKEN,',
|
|
189
|
-
'SYNCULAR_DB_PROVIDER, SPACES_SQLITE_PATH,',
|
|
190
|
-
'SYNCULAR_PG_CONNECTION_STRING, DATABASE_URL',
|
|
191
|
-
],
|
|
192
|
-
},
|
|
193
|
-
];
|
|
194
|
-
|
|
195
|
-
function HelpView(): ReactElement {
|
|
196
|
-
return (
|
|
197
|
-
<Box flexDirection="column">
|
|
198
|
-
<Text color="cyanBright" bold>
|
|
199
|
-
{CLI_NAME} CLI v{CLI_VERSION}
|
|
200
|
-
</Text>
|
|
201
|
-
<Text dimColor>
|
|
202
|
-
Interactive by default in TTY. Use --no-interactive for script mode.
|
|
203
|
-
</Text>
|
|
204
|
-
<Box marginTop={1} flexDirection="column">
|
|
205
|
-
<Text color="yellowBright" bold>
|
|
206
|
-
Usage
|
|
207
|
-
</Text>
|
|
208
|
-
{USAGE_LINES.map((line) => (
|
|
209
|
-
<Text key={line} color="cyan">
|
|
210
|
-
{line}
|
|
211
|
-
</Text>
|
|
212
|
-
))}
|
|
213
|
-
</Box>
|
|
214
|
-
{HELP_SECTIONS.map((section) => (
|
|
215
|
-
<Box key={section.title} marginTop={1} flexDirection="column">
|
|
216
|
-
<Text color="yellowBright" bold>
|
|
217
|
-
{section.title}
|
|
218
|
-
</Text>
|
|
219
|
-
{section.lines.map((line) => (
|
|
220
|
-
<Text key={`${section.title}:${line}`}>{line}</Text>
|
|
221
|
-
))}
|
|
222
|
-
</Box>
|
|
223
|
-
))}
|
|
224
|
-
</Box>
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export function printHelp(): void {
|
|
229
|
-
const rendered = renderToString(<HelpView />, {
|
|
230
|
-
columns: Math.max(process.stdout.columns ?? 140, 140),
|
|
231
|
-
});
|
|
232
|
-
process.stdout.write(rendered);
|
|
233
|
-
if (!rendered.endsWith('\n')) {
|
|
234
|
-
process.stdout.write('\n');
|
|
235
|
-
}
|
|
236
|
-
}
|
package/src/index.ts
DELETED