@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/src/main.tsx DELETED
@@ -1,268 +0,0 @@
1
- import process from 'node:process';
2
- import { render } from 'ink';
3
- import { parseArgs, shouldRunInteractive } from './args';
4
- import { runLogin, runLogout, runWhoAmI } from './commands/auth';
5
- import { runBuild, runEject } from './commands/build';
6
- import { runConsole } from './commands/console';
7
- import {
8
- runCreateSpace,
9
- runDeploy,
10
- runDeployments,
11
- runRollback,
12
- runVerify,
13
- } from './commands/demo';
14
- import { runDoctor } from './commands/doctor';
15
- import { runMigrateStatus, runMigrateUp } from './commands/migrate';
16
- import { runCreate, runDev } from './commands/project';
17
- import { runTarget } from './commands/target';
18
- import { runTypegen } from './commands/typegen';
19
- import { printHelp } from './help';
20
- import { InteractiveApp } from './interactive';
21
- import { printError, printHeader } from './output';
22
- import type { ParsedArgs } from './types';
23
- import { maybeNotifyAboutUpdate } from './update-check';
24
-
25
- type CommandRunner = (flagValues: Map<string, string>) => Promise<number>;
26
- type LogError = (message: string) => void;
27
-
28
- export interface NonInteractiveHandlers {
29
- printHelp: () => void;
30
- printHeader: () => void;
31
- printError: LogError;
32
- runDoctor: () => Promise<number>;
33
- runConsole: CommandRunner;
34
- runLogin: CommandRunner;
35
- runLogout: CommandRunner;
36
- runWhoAmI: CommandRunner;
37
- runCreateSpace: CommandRunner;
38
- runCreate: CommandRunner;
39
- runDev: CommandRunner;
40
- runTypegen: CommandRunner;
41
- runMigrateStatus: CommandRunner;
42
- runMigrateUp: CommandRunner;
43
- runBuild: CommandRunner;
44
- runEject: CommandRunner;
45
- runTarget: CommandRunner;
46
- runDeploy: CommandRunner;
47
- runVerify: CommandRunner;
48
- runDeployments: CommandRunner;
49
- runRollback: CommandRunner;
50
- }
51
-
52
- const defaultNonInteractiveHandlers: NonInteractiveHandlers = {
53
- printHelp,
54
- printHeader,
55
- printError,
56
- runDoctor,
57
- runConsole,
58
- runLogin,
59
- runLogout,
60
- runWhoAmI,
61
- runCreateSpace,
62
- runCreate,
63
- runDev,
64
- runTypegen,
65
- runMigrateStatus,
66
- runMigrateUp,
67
- runBuild,
68
- runEject,
69
- runTarget,
70
- runDeploy,
71
- runVerify,
72
- runDeployments,
73
- runRollback,
74
- };
75
-
76
- interface RootRoute {
77
- command:
78
- | 'doctor'
79
- | 'console'
80
- | 'login'
81
- | 'logout'
82
- | 'whoami'
83
- | 'create-space'
84
- | 'create'
85
- | 'dev'
86
- | 'typegen'
87
- | 'migrate-status'
88
- | 'migrate-up'
89
- | 'build'
90
- | 'eject'
91
- | 'target'
92
- | 'deploy'
93
- | 'verify'
94
- | 'deployments'
95
- | 'rollback';
96
- run(
97
- handlers: NonInteractiveHandlers,
98
- flagValues: Map<string, string>
99
- ): Promise<number>;
100
- }
101
-
102
- const ROOT_ROUTES: RootRoute[] = [
103
- { command: 'doctor', run: (handlers) => handlers.runDoctor() },
104
- { command: 'console', run: (handlers, flags) => handlers.runConsole(flags) },
105
- { command: 'login', run: (handlers, flags) => handlers.runLogin(flags) },
106
- { command: 'logout', run: (handlers, flags) => handlers.runLogout(flags) },
107
- { command: 'whoami', run: (handlers, flags) => handlers.runWhoAmI(flags) },
108
- {
109
- command: 'create-space',
110
- run: (handlers, flags) => handlers.runCreateSpace(flags),
111
- },
112
- { command: 'create', run: (handlers, flags) => handlers.runCreate(flags) },
113
- { command: 'dev', run: (handlers, flags) => handlers.runDev(flags) },
114
- { command: 'typegen', run: (handlers, flags) => handlers.runTypegen(flags) },
115
- {
116
- command: 'migrate-status',
117
- run: (handlers, flags) => handlers.runMigrateStatus(flags),
118
- },
119
- {
120
- command: 'migrate-up',
121
- run: (handlers, flags) => handlers.runMigrateUp(flags),
122
- },
123
- { command: 'build', run: (handlers, flags) => handlers.runBuild(flags) },
124
- { command: 'eject', run: (handlers, flags) => handlers.runEject(flags) },
125
- { command: 'target', run: (handlers, flags) => handlers.runTarget(flags) },
126
- { command: 'deploy', run: (handlers, flags) => handlers.runDeploy(flags) },
127
- { command: 'verify', run: (handlers, flags) => handlers.runVerify(flags) },
128
- {
129
- command: 'deployments',
130
- run: (handlers, flags) => handlers.runDeployments(flags),
131
- },
132
- {
133
- command: 'rollback',
134
- run: (handlers, flags) => handlers.runRollback(flags),
135
- },
136
- ];
137
-
138
- function findRootRoute(command: ParsedArgs['command']): RootRoute | null {
139
- return ROOT_ROUTES.find((route) => route.command === command) ?? null;
140
- }
141
-
142
- export async function runNonInteractive(
143
- args: ParsedArgs,
144
- handlers: NonInteractiveHandlers = defaultNonInteractiveHandlers
145
- ): Promise<number> {
146
- if (args.flags.has('--help')) {
147
- handlers.printHelp();
148
- return 0;
149
- }
150
-
151
- if (args.flags.has('--version')) {
152
- handlers.printHeader();
153
- return 0;
154
- }
155
-
156
- if (args.command === 'help') {
157
- handlers.printHelp();
158
- return 0;
159
- }
160
-
161
- if (args.command === 'version') {
162
- handlers.printHeader();
163
- return 0;
164
- }
165
-
166
- const rootRoute = findRootRoute(args.command);
167
- if (rootRoute) {
168
- if (args.subcommand !== null) {
169
- handlers.printError(
170
- `Unexpected positional argument for "${rootRoute.command}": ${args.subcommand}`
171
- );
172
- handlers.printHelp();
173
- return 1;
174
- }
175
- return rootRoute.run(handlers, args.flagValues);
176
- }
177
-
178
- if (args.command === 'interactive') {
179
- handlers.printError('Interactive mode requires a TTY.');
180
- return 1;
181
- }
182
-
183
- if (args.command === null && args.positionals.length > 0) {
184
- handlers.printError(`Unknown command: ${args.positionals[0]}`);
185
- handlers.printHelp();
186
- return 1;
187
- }
188
-
189
- handlers.printHelp();
190
- return 0;
191
- }
192
-
193
- async function runInteractive(
194
- initialCommand: ParsedArgs['command'],
195
- allowForms: boolean
196
- ): Promise<string[] | null> {
197
- return new Promise((resolve) => {
198
- let settled = false;
199
- const app = render(
200
- <InteractiveApp
201
- initialCommand={initialCommand}
202
- allowForms={allowForms}
203
- onSubmit={(argv) => {
204
- if (settled) {
205
- return;
206
- }
207
- settled = true;
208
- resolve(argv);
209
- app.unmount();
210
- }}
211
- />
212
- );
213
-
214
- void app.waitUntilExit().then(() => {
215
- if (settled) {
216
- return;
217
- }
218
- settled = true;
219
- resolve(null);
220
- });
221
- });
222
- }
223
-
224
- export async function main(): Promise<void> {
225
- const argv = process.argv.slice(2);
226
- let args = parseArgs(argv);
227
-
228
- const helpOrVersionRequested =
229
- args.flags.has('--help') ||
230
- args.flags.has('--version') ||
231
- args.command === 'help' ||
232
- args.command === 'version';
233
-
234
- const interactiveRequested =
235
- args.flags.has('--interactive') ||
236
- args.command === 'interactive' ||
237
- (args.command === null && args.positionals.length === 0) ||
238
- (args.command === 'create' && !args.flagValues.has('--template'));
239
-
240
- if (
241
- !helpOrVersionRequested &&
242
- interactiveRequested &&
243
- shouldRunInteractive(args)
244
- ) {
245
- const selectedArgv = await runInteractive(
246
- args.command,
247
- args.flags.has('--forms')
248
- );
249
- if (selectedArgv === null) {
250
- process.exit(0);
251
- }
252
-
253
- args = parseArgs(selectedArgv);
254
- }
255
-
256
- const finalHelpOrVersionRequested =
257
- args.flags.has('--help') ||
258
- args.flags.has('--version') ||
259
- args.command === 'help' ||
260
- args.command === 'version';
261
-
262
- if (!finalHelpOrVersionRequested) {
263
- await maybeNotifyAboutUpdate(args.flags);
264
- }
265
-
266
- const exitCode = await runNonInteractive(args);
267
- process.exit(exitCode);
268
- }
package/src/output.tsx DELETED
@@ -1,47 +0,0 @@
1
- import process from 'node:process';
2
- import { Box, renderToString, Text } from 'ink';
3
- import type { ReactElement } from 'react';
4
- import { CLI_NAME, CLI_VERSION } from './constants';
5
-
6
- function printInk(view: ReactElement): void {
7
- const rendered = renderToString(view, {
8
- columns: Math.max(process.stdout.columns ?? 120, 120),
9
- });
10
- process.stdout.write(rendered);
11
- if (!rendered.endsWith('\n')) {
12
- process.stdout.write('\n');
13
- }
14
- }
15
-
16
- export function printHeader(): void {
17
- printInk(
18
- <Text color="cyanBright" bold>
19
- {CLI_NAME} CLI v{CLI_VERSION}
20
- </Text>
21
- );
22
- }
23
-
24
- export function printInfo(message: string): void {
25
- printInk(
26
- <Box>
27
- <Text color="cyan">info </Text>
28
- <Text>{message}</Text>
29
- </Box>
30
- );
31
- }
32
-
33
- export function printError(message: string): void {
34
- const rendered = renderToString(
35
- <Box>
36
- <Text color="redBright">error </Text>
37
- <Text>{message}</Text>
38
- </Box>,
39
- {
40
- columns: Math.max(process.stderr.columns ?? 120, 120),
41
- }
42
- );
43
- process.stderr.write(rendered);
44
- if (!rendered.endsWith('\n')) {
45
- process.stderr.write('\n');
46
- }
47
- }
package/src/paths.ts DELETED
@@ -1,11 +0,0 @@
1
- import { dirname, resolve } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
3
-
4
- export function resolveRepoRoot(): string {
5
- const commandDir = dirname(fileURLToPath(import.meta.url));
6
- return resolve(commandDir, '..', '..', '..');
7
- }
8
-
9
- export function resolveDefaultSyncularConfigPath(cwd: string): string {
10
- return resolve(cwd, 'syncular.config.ts');
11
- }
@@ -1,2 +0,0 @@
1
- export const DEFAULT_CONTROL_PLANE_API_BASE =
2
- 'https://api.spaces.syncular.dev/api/control';
@@ -1,13 +0,0 @@
1
- import { listTargetIds } from './state';
2
- import type { TargetDefinition } from './types';
3
-
4
- export * from './state';
5
- export * from './types';
6
-
7
- export function listTargetDefinitions(): TargetDefinition[] {
8
- return listTargetIds().map((id) => ({
9
- id,
10
- description: 'Managed deploys for Spaces.',
11
- defaultBuildpackId: 'contract-worker',
12
- }));
13
- }
@@ -1,99 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
- import { resolve } from 'node:path';
4
- import { resolveDefaultSyncularConfigPath } from '../paths';
5
- import type { TargetId } from './types';
6
- import { TARGET_IDS } from './types';
7
-
8
- const TARGET_STATE_RELATIVE_PATH = '.syncular/target.json';
9
- const DEFAULT_TARGET_ID: TargetId = 'spaces';
10
-
11
- interface StoredTargetState {
12
- target: TargetId;
13
- }
14
-
15
- export function listTargetIds(): readonly TargetId[] {
16
- return TARGET_IDS;
17
- }
18
-
19
- export function isTargetId(value: string): value is TargetId {
20
- return TARGET_IDS.includes(value as TargetId);
21
- }
22
-
23
- export function resolveTargetStatePath(cwd: string): string {
24
- return resolve(cwd, TARGET_STATE_RELATIVE_PATH);
25
- }
26
-
27
- export async function readStoredTargetId(
28
- cwd: string
29
- ): Promise<TargetId | null> {
30
- const statePath = resolveTargetStatePath(cwd);
31
- if (!existsSync(statePath)) {
32
- return null;
33
- }
34
-
35
- try {
36
- const raw = await readFile(statePath, 'utf8');
37
- const parsed = JSON.parse(raw) as Partial<StoredTargetState>;
38
- if (typeof parsed.target !== 'string' || !isTargetId(parsed.target)) {
39
- return null;
40
- }
41
- return parsed.target;
42
- } catch {
43
- return null;
44
- }
45
- }
46
-
47
- export async function writeStoredTargetId(args: {
48
- cwd: string;
49
- targetId: TargetId;
50
- }): Promise<string> {
51
- const statePath = resolveTargetStatePath(args.cwd);
52
- await mkdir(resolve(args.cwd, '.syncular'), { recursive: true });
53
- await writeFile(
54
- statePath,
55
- `${JSON.stringify({ target: args.targetId } satisfies StoredTargetState, null, 2)}\n`,
56
- 'utf8'
57
- );
58
- return statePath;
59
- }
60
-
61
- export async function resolveEffectiveTargetId(args: {
62
- cwd: string;
63
- explicitTargetId: string | null;
64
- }): Promise<{
65
- source: 'flag' | 'state' | 'default';
66
- targetId: TargetId;
67
- }> {
68
- if (args.explicitTargetId) {
69
- if (!isTargetId(args.explicitTargetId)) {
70
- throw new Error(
71
- `Unsupported --target "${args.explicitTargetId}". Supported targets: ${TARGET_IDS.join(', ')}.`
72
- );
73
- }
74
- return {
75
- source: 'flag',
76
- targetId: args.explicitTargetId,
77
- };
78
- }
79
-
80
- const storedTargetId = await readStoredTargetId(args.cwd);
81
- if (storedTargetId) {
82
- return {
83
- source: 'state',
84
- targetId: storedTargetId,
85
- };
86
- }
87
-
88
- return {
89
- source: 'default',
90
- targetId: DEFAULT_TARGET_ID,
91
- };
92
- }
93
-
94
- export function resolveTargetDefaultConfigPath(args: {
95
- cwd: string;
96
- targetId: TargetId;
97
- }): string {
98
- return resolveDefaultSyncularConfigPath(args.cwd);
99
- }
@@ -1,8 +0,0 @@
1
- export const TARGET_IDS = ['spaces'] as const;
2
- export type TargetId = (typeof TARGET_IDS)[number];
3
-
4
- export interface TargetDefinition {
5
- id: TargetId;
6
- description: string;
7
- defaultBuildpackId: 'contract-worker';
8
- }
@@ -1,2 +0,0 @@
1
- export * from './registry';
2
- export * from './syncular-types';
@@ -1,42 +0,0 @@
1
- import { TEMPLATE_EXTENSION_MANIFEST } from '../extensions';
2
-
3
- type TemplateManifest = typeof TEMPLATE_EXTENSION_MANIFEST;
4
- function buildTemplateRegistry(manifest: TemplateManifest) {
5
- const entries = Object.entries(manifest);
6
- const seenTemplateIds = new Set<string>();
7
-
8
- for (const [registryKey, manifestEntry] of entries) {
9
- const templateId = manifestEntry.template.id;
10
- if (templateId.length === 0) {
11
- throw new Error(`Template "${registryKey}" has an empty id.`);
12
- }
13
-
14
- if (seenTemplateIds.has(templateId)) {
15
- throw new Error(`Duplicate template id in manifest: "${templateId}".`);
16
- }
17
- seenTemplateIds.add(templateId);
18
- }
19
-
20
- return Object.freeze(
21
- Object.fromEntries(
22
- entries.map(([registryKey, manifestEntry]) => [
23
- registryKey,
24
- manifestEntry.template,
25
- ])
26
- )
27
- ) as {
28
- [K in keyof TemplateManifest]: TemplateManifest[K]['template'];
29
- };
30
- }
31
-
32
- export const templateRegistry = buildTemplateRegistry(
33
- TEMPLATE_EXTENSION_MANIFEST
34
- );
35
-
36
- const TEMPLATE_IDS = Object.freeze(
37
- Object.values(templateRegistry).map((template) => template.id)
38
- ) as readonly string[];
39
-
40
- export function listTemplateIds(): readonly string[] {
41
- return TEMPLATE_IDS;
42
- }
@@ -1,10 +0,0 @@
1
- export type {
2
- SyncularClientDialect,
3
- SyncularElectronDialect,
4
- SyncularLibrariesTarget,
5
- SyncularServerDialect,
6
- } from '@syncular/cli-template-syncular-libraries';
7
- export {
8
- DEFAULT_SYNCULAR_LIBRARIES_TARGETS,
9
- SYNCULAR_LIBRARIES_TARGETS,
10
- } from '@syncular/cli-template-syncular-libraries';
package/src/types.ts DELETED
@@ -1,67 +0,0 @@
1
- export type RootCommand =
2
- | 'help'
3
- | 'version'
4
- | 'doctor'
5
- | 'console'
6
- | 'login'
7
- | 'logout'
8
- | 'whoami'
9
- | 'create-space'
10
- | 'create'
11
- | 'dev'
12
- | 'typegen'
13
- | 'migrate-status'
14
- | 'migrate-up'
15
- | 'build'
16
- | 'eject'
17
- | 'target'
18
- | 'deploy'
19
- | 'verify'
20
- | 'rollback'
21
- | 'deployments'
22
- | 'interactive';
23
-
24
- export interface ParsedArgs {
25
- command: RootCommand | null;
26
- subcommand: string | null;
27
- flags: Set<string>;
28
- flagValues: Map<string, string>;
29
- positionals: string[];
30
- }
31
-
32
- export interface InteractiveField {
33
- id: string;
34
- label: string;
35
- kind?: 'string' | 'number' | 'boolean';
36
- placeholder?: string;
37
- required?: boolean;
38
- defaultValue?: string;
39
- }
40
-
41
- export interface InteractiveCommand {
42
- id:
43
- | 'doctor'
44
- | 'console'
45
- | 'create'
46
- | 'create-space'
47
- | 'dev'
48
- | 'typegen'
49
- | 'migrate-status'
50
- | 'migrate-up'
51
- | 'build'
52
- | 'eject'
53
- | 'target'
54
- | 'deploy'
55
- | 'verify'
56
- | 'deployments'
57
- | 'rollback'
58
- | 'login'
59
- | 'logout'
60
- | 'whoami'
61
- | 'help'
62
- | 'quit';
63
- label: string;
64
- description: string;
65
- fields?: InteractiveField[];
66
- buildArgv(values: Record<string, string>): string[] | null;
67
- }