@dinoxx/dinox-cli 1.0.18 → 1.0.20

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.
Files changed (118) hide show
  1. package/README.md +807 -418
  2. package/dist/auth/userInfo.d.ts +2 -0
  3. package/dist/auth/userInfo.js +28 -11
  4. package/dist/cli.js +15 -1
  5. package/dist/commands/auth/index.d.ts +2 -0
  6. package/dist/commands/auth/index.js +217 -163
  7. package/dist/commands/boxes/index.d.ts +2 -0
  8. package/dist/commands/boxes/index.js +119 -75
  9. package/dist/commands/boxes/repo.d.ts +8 -0
  10. package/dist/commands/boxes/repo.js +41 -0
  11. package/dist/commands/config/index.d.ts +2 -0
  12. package/dist/commands/config/index.js +85 -36
  13. package/dist/commands/descriptor/register.d.ts +8 -0
  14. package/dist/commands/descriptor/register.js +113 -0
  15. package/dist/commands/descriptor/types.d.ts +37 -0
  16. package/dist/commands/descriptor/types.js +17 -0
  17. package/dist/commands/graph/index.d.ts +2 -0
  18. package/dist/commands/graph/index.js +143 -73
  19. package/dist/commands/info/index.d.ts +2 -0
  20. package/dist/commands/info/index.js +41 -14
  21. package/dist/commands/mcp/index.js +11 -10
  22. package/dist/commands/mcp/server.js +8 -4
  23. package/dist/commands/mcp/tools.js +30 -104
  24. package/dist/commands/mcp/types.d.ts +8 -1
  25. package/dist/commands/meta/index.d.ts +2 -0
  26. package/dist/commands/meta/index.js +64 -33
  27. package/dist/commands/meta/repo.d.ts +6 -0
  28. package/dist/commands/meta/repo.js +6 -0
  29. package/dist/commands/notes/actions.d.ts +10 -0
  30. package/dist/commands/notes/actions.js +403 -0
  31. package/dist/commands/notes/descriptors.d.ts +4 -0
  32. package/dist/commands/notes/descriptors.js +250 -0
  33. package/dist/commands/notes/dryRun.d.ts +31 -0
  34. package/dist/commands/notes/dryRun.js +130 -0
  35. package/dist/commands/notes/index.d.ts +2 -51
  36. package/dist/commands/notes/index.js +2 -581
  37. package/dist/commands/notes/repo.d.ts +9 -0
  38. package/dist/commands/notes/repo.js +56 -10
  39. package/dist/commands/notes/runtime.d.ts +28 -0
  40. package/dist/commands/notes/runtime.js +185 -0
  41. package/dist/commands/notes/searchOutput.d.ts +10 -2
  42. package/dist/commands/notes/searchOutput.js +14 -2
  43. package/dist/commands/notes/searchResponse.d.ts +51 -0
  44. package/dist/commands/notes/searchResponse.js +56 -0
  45. package/dist/commands/notes/searchSql.js +2 -0
  46. package/dist/commands/prompt/index.d.ts +2 -0
  47. package/dist/commands/prompt/index.js +122 -72
  48. package/dist/commands/prompt/repo.d.ts +7 -0
  49. package/dist/commands/prompt/repo.js +46 -0
  50. package/dist/commands/schema/commandMetadata.d.ts +2 -0
  51. package/dist/commands/schema/commandMetadata.js +18 -0
  52. package/dist/commands/schema/globalOptions.d.ts +3 -0
  53. package/dist/commands/schema/globalOptions.js +3 -0
  54. package/dist/commands/schema/index.d.ts +4 -0
  55. package/dist/commands/schema/index.js +109 -0
  56. package/dist/commands/schema/renderSkills.d.ts +6 -0
  57. package/dist/commands/schema/renderSkills.js +216 -0
  58. package/dist/commands/schema/spec.d.ts +6 -0
  59. package/dist/commands/schema/spec.js +40 -0
  60. package/dist/commands/schema/types.d.ts +47 -0
  61. package/dist/commands/schema/types.js +1 -0
  62. package/dist/commands/storage/index.d.ts +4 -0
  63. package/dist/commands/storage/index.js +292 -0
  64. package/dist/commands/storage/repo.d.ts +162 -0
  65. package/dist/commands/storage/repo.js +770 -0
  66. package/dist/commands/sync.d.ts +2 -0
  67. package/dist/commands/sync.js +41 -27
  68. package/dist/commands/tags/index.d.ts +2 -0
  69. package/dist/commands/tags/index.js +121 -79
  70. package/dist/commands/tags/repo.d.ts +7 -0
  71. package/dist/commands/tags/repo.js +52 -0
  72. package/dist/commands/todo/dryRun.d.ts +23 -0
  73. package/dist/commands/todo/dryRun.js +133 -0
  74. package/dist/commands/todo/index.d.ts +2 -0
  75. package/dist/commands/todo/index.js +285 -135
  76. package/dist/commands/todo/repo.d.ts +11 -0
  77. package/dist/commands/todo/repo.js +37 -9
  78. package/dist/commands/update.d.ts +3 -0
  79. package/dist/commands/update.js +35 -13
  80. package/dist/commands/writeDryRun.d.ts +62 -0
  81. package/dist/commands/writeDryRun.js +131 -0
  82. package/dist/config/paths.d.ts +2 -1
  83. package/dist/config/paths.js +11 -1
  84. package/dist/config/resolve.js +7 -5
  85. package/dist/constants/links.d.ts +1 -1
  86. package/dist/constants/links.js +1 -1
  87. package/dist/daemon/ensure.js +3 -2
  88. package/dist/daemon/index.js +17 -15
  89. package/dist/dinox.js +9 -13
  90. package/dist/powersync/runtime.d.ts +1 -1
  91. package/dist/powersync/runtime.js +5 -3
  92. package/dist/powersync/schema/index.d.ts +27 -0
  93. package/dist/powersync/schema/index.js +2 -0
  94. package/dist/powersync/schema/note.d.ts +1 -0
  95. package/dist/powersync/schema/note.js +1 -0
  96. package/dist/powersync/schema/projects.d.ts +3 -0
  97. package/dist/powersync/schema/projects.js +3 -0
  98. package/dist/powersync/schema/storage.d.ts +24 -0
  99. package/dist/powersync/schema/storage.js +24 -0
  100. package/dist/skills/check.d.ts +6 -0
  101. package/dist/skills/check.js +254 -0
  102. package/dist/utils/bidlinkCanonicalization.d.ts +2 -0
  103. package/dist/utils/bidlinkCanonicalization.js +161 -0
  104. package/dist/utils/dryRun.d.ts +13 -0
  105. package/dist/utils/dryRun.js +69 -0
  106. package/dist/utils/output.d.ts +19 -0
  107. package/dist/utils/output.js +155 -1
  108. package/dist/utils/terminalSanitization.d.ts +2 -0
  109. package/dist/utils/terminalSanitization.js +33 -0
  110. package/dist/utils/tiptapMarkdown.d.ts +4 -1
  111. package/dist/utils/tiptapMarkdown.js +285 -113
  112. package/dist/utils/tiptapMarkdownSchema.d.ts +37 -0
  113. package/dist/utils/tiptapMarkdownSchema.js +577 -0
  114. package/dist/utils/tiptapMarkdownSchemaUtils.d.ts +74 -0
  115. package/dist/utils/tiptapMarkdownSchemaUtils.js +394 -0
  116. package/dist/utils/updateNotice.d.ts +7 -0
  117. package/dist/utils/updateNotice.js +64 -0
  118. package/package.json +25 -3
@@ -5,6 +5,8 @@ export type AuthIdentity = {
5
5
  email: string | null;
6
6
  syncedAt: string;
7
7
  };
8
+ export declare function buildPendingAuthConfig(rawConfig: DinoxConfig, authorization: string): DinoxConfig;
9
+ export declare function mergeAuthIdentityIntoConfig(rawConfig: DinoxConfig, authorization: string, identity: AuthIdentity): DinoxConfig;
8
10
  export declare function fetchUserInfoWithAuthorization(input: {
9
11
  authorization: string;
10
12
  config: ResolvedDinoxConfig;
@@ -3,6 +3,33 @@ import { DinoxError } from '../utils/errors.js';
3
3
  import { createTimeoutSignal, mergeAbortSignals } from '../utils/abort.js';
4
4
  import { toAuthorizationHeaderValue } from '../utils/authToken.js';
5
5
  const AUTH_CODE_OK = '000000';
6
+ export function buildPendingAuthConfig(rawConfig, authorization) {
7
+ return {
8
+ ...rawConfig,
9
+ auth: {
10
+ ...(rawConfig.auth ?? {}),
11
+ authorization,
12
+ userId: undefined,
13
+ username: undefined,
14
+ email: undefined,
15
+ userInfoSyncedAt: undefined,
16
+ },
17
+ };
18
+ }
19
+ export function mergeAuthIdentityIntoConfig(rawConfig, authorization, identity) {
20
+ const pendingConfig = buildPendingAuthConfig(rawConfig, authorization);
21
+ return {
22
+ ...pendingConfig,
23
+ auth: {
24
+ ...(pendingConfig.auth ?? {}),
25
+ authorization,
26
+ userId: identity.userId,
27
+ username: identity.username,
28
+ email: identity.email,
29
+ userInfoSyncedAt: identity.syncedAt,
30
+ },
31
+ };
32
+ }
6
33
  function normalizeOptionalString(value) {
7
34
  if (typeof value !== 'string') {
8
35
  return undefined;
@@ -105,17 +132,7 @@ export async function refreshAndPersistAuthIdentity(rawConfig, resolvedConfig) {
105
132
  authorization,
106
133
  config: resolvedConfig,
107
134
  });
108
- const nextConfig = {
109
- ...rawConfig,
110
- auth: {
111
- ...(rawConfig.auth ?? {}),
112
- authorization: rawConfig.auth?.authorization ?? authorization,
113
- userId: identity.userId,
114
- username: identity.username,
115
- email: identity.email,
116
- userInfoSyncedAt: identity.syncedAt,
117
- },
118
- };
135
+ const nextConfig = mergeAuthIdentityIntoConfig(rawConfig, authorization, identity);
119
136
  await saveConfig(nextConfig);
120
137
  return identity;
121
138
  }
package/dist/cli.js CHANGED
@@ -9,12 +9,16 @@ import { registerMCPCommands } from './commands/mcp/index.js';
9
9
  import { registerMetaCommands } from './commands/meta/index.js';
10
10
  import { registerNoteCommands } from './commands/notes/index.js';
11
11
  import { registerPromptCommands } from './commands/prompt/index.js';
12
+ import { registerSchemaCommands } from './commands/schema/index.js';
12
13
  import { registerSyncCommand } from './commands/sync.js';
14
+ import { registerStorageCommands } from './commands/storage/index.js';
13
15
  import { registerUpdateCommand } from './commands/update.js';
14
16
  import { registerTagsCommand } from './commands/tags/index.js';
15
17
  import { registerTodoCommands } from './commands/todo/index.js';
16
18
  import { getPackageVersion } from './utils/version.js';
19
+ import { clearRequestedStructuredOutputFormat, resolveStructuredOutputFormat, setRequestedStructuredOutputFormat, } from './utils/output.js';
17
20
  export function createCli() {
21
+ clearRequestedStructuredOutputFormat();
18
22
  const program = new Command();
19
23
  program
20
24
  .name('dino')
@@ -22,10 +26,18 @@ export function createCli() {
22
26
  .version(getPackageVersion())
23
27
  .showHelpAfterError();
24
28
  program
25
- .option('--json', 'output machine-readable YAML')
29
+ .option('--json', 'legacy machine-readable YAML output (equivalent to --format yaml)')
30
+ .option('--format <format>', 'structured output format: yaml | json')
26
31
  .option('--offline', 'skip connect/sync and only use local cache')
27
32
  .option('--sync-timeout <ms>', 'override sync/connect timeout (milliseconds)')
28
33
  .option('--verbose', 'enable verbose logging');
34
+ program.hook('preAction', (_thisCommand, actionCommand) => {
35
+ const options = actionCommand.optsWithGlobals?.() ?? {};
36
+ setRequestedStructuredOutputFormat(resolveStructuredOutputFormat(options));
37
+ });
38
+ program.hook('postAction', () => {
39
+ clearRequestedStructuredOutputFormat();
40
+ });
29
41
  registerAuthCommands(program);
30
42
  registerBoxesCommand(program);
31
43
  registerConfigCommands(program);
@@ -37,6 +49,8 @@ export function createCli() {
37
49
  registerSyncCommand(program);
38
50
  registerUpdateCommand(program);
39
51
  registerPromptCommands(program);
52
+ registerSchemaCommands(program);
53
+ registerStorageCommands(program);
40
54
  registerTagsCommand(program);
41
55
  registerTodoCommands(program);
42
56
  registerNoteCommands(program);
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import type { CommandGroupDescriptor } from '../descriptor/types.js';
3
+ export declare const authCommandGroup: CommandGroupDescriptor;
2
4
  export declare function registerAuthCommands(program: Command): void;
@@ -1,183 +1,237 @@
1
1
  import fs from 'node:fs/promises';
2
+ import { buildPendingAuthConfig, fetchUserInfoWithAuthorization, mergeAuthIdentityIntoConfig, } from '../../auth/userInfo.js';
3
+ import { getLegacyPowerSyncDbPath, getPowerSyncDbPath } from '../../config/paths.js';
2
4
  import { loadConfig, saveConfig } from '../../config/store.js';
3
5
  import { resolveConfig } from '../../config/resolve.js';
4
- import { getPowerSyncDbPath } from '../../config/paths.js';
5
- import { redactAuthorization } from '../../utils/redact.js';
6
- import { DinoxError } from '../../utils/errors.js';
7
- import { printYaml } from '../../utils/output.js';
8
- import { parseSyncTimeoutMs } from '../../utils/syncTimeout.js';
9
- import { normalizeAuthToken } from '../../utils/authToken.js';
10
- import { refreshAndPersistAuthIdentity } from '../../auth/userInfo.js';
11
- import { connectPowerSync, getStatusSnapshot } from '../../powersync/runtime.js';
12
6
  import { fetchCredentialsWithAuthorization } from '../../powersync/connector.js';
7
+ import { connectPowerSync, getStatusSnapshot } from '../../powersync/runtime.js';
13
8
  import { runSingleSyncPass } from '../../powersync/syncPass.js';
9
+ import { registerCommandGroup } from '../descriptor/register.js';
10
+ import { FORMAT_OPTIONS, OFFLINE_OPTIONS, SYNC_TIMEOUT_OPTIONS } from '../schema/globalOptions.js';
11
+ import { normalizeAuthToken } from '../../utils/authToken.js';
12
+ import { DinoxError } from '../../utils/errors.js';
13
+ import { getRequestedStructuredOutputFormat, printHumanReadableLine, printSuccess, } from '../../utils/output.js';
14
+ import { redactAuthorization } from '../../utils/redact.js';
15
+ import { parseSyncTimeoutMs } from '../../utils/syncTimeout.js';
16
+ const AUTH_LOGIN_GLOBAL_OPTIONS = [...FORMAT_OPTIONS, ...SYNC_TIMEOUT_OPTIONS];
17
+ const AUTH_STATUS_GLOBAL_OPTIONS = [...FORMAT_OPTIONS, ...OFFLINE_OPTIONS, ...SYNC_TIMEOUT_OPTIONS];
14
18
  async function removeSqliteArtifacts(dbPath) {
15
- const artifacts = ['', '-wal', '-shm'];
16
- for (const suffix of artifacts) {
19
+ for (const suffix of ['', '-wal', '-shm']) {
17
20
  await fs.rm(`${dbPath}${suffix}`, { force: true }).catch(() => undefined);
18
21
  }
19
22
  }
20
- export function registerAuthCommands(program) {
21
- const auth = program
22
- .command('auth')
23
- .description('Authentication and PowerSync connectivity commands');
24
- auth
25
- .command('login')
26
- .description('Save login token and verify PowerSync connectivity')
27
- .argument('<token>', 'login token (pass the raw token string, without Bearer prefix)')
28
- .action(async (token, _options, command) => {
29
- const rawToken = normalizeAuthToken(token);
30
- if (!rawToken) {
31
- throw new DinoxError('Token is required');
32
- }
33
- const config = await loadConfig();
34
- config.auth = { ...(config.auth ?? {}), authorization: rawToken };
35
- await saveConfig(config);
36
- const resolved = resolveConfig(config);
37
- const globals = command.optsWithGlobals?.() ?? {};
38
- const timeoutMs = parseSyncTimeoutMs(globals.syncTimeout) ?? resolved.sync.timeoutMs;
39
- const jsonOutput = Boolean(globals.json);
40
- // 1) Token exchange sanity check.
41
- await fetchCredentialsWithAuthorization({
42
- authorization: rawToken,
43
- endpoint: resolved.powersync.endpoint,
44
- credentialsUrl: resolved.powersync.tokenEndpoint,
45
- timeoutMs,
46
- });
47
- // 1.5) Fetch and persist user identity.
48
- const identity = await refreshAndPersistAuthIdentity(config, resolved);
49
- // 2) Connect + initial sync.
50
- const { db, dbPath, stale } = await connectPowerSync({
51
- config: resolved,
52
- offline: false,
53
- timeoutMs,
54
- });
55
- try {
56
- await runSingleSyncPass(db, timeoutMs);
57
- const status = getStatusSnapshot(db);
58
- const result = {
59
- ok: true,
60
- verified: true,
61
- endpoint: resolved.powersync.endpoint,
62
- dbPath,
63
- stale,
64
- lastSyncedAt: status.lastSyncedAt,
65
- userId: identity.userId,
66
- };
67
- if (jsonOutput) {
68
- printYaml(result);
69
- }
70
- else {
71
- console.log('Login verified.');
72
- console.log(`- endpoint: ${result.endpoint}`);
73
- console.log(`- db: ${result.dbPath}`);
74
- console.log(`- userId: ${result.userId}`);
75
- if (result.lastSyncedAt) {
76
- console.log(`- lastSyncedAt: ${result.lastSyncedAt}`);
77
- }
78
- if (stale) {
79
- console.log('- warning: initial sync timed out; local cache may be stale');
80
- }
81
- }
82
- }
83
- finally {
84
- await db.close().catch(() => undefined);
85
- }
23
+ async function runAuthLogin(context) {
24
+ const token = context.args.token;
25
+ const rawToken = normalizeAuthToken(token);
26
+ if (!rawToken) {
27
+ throw new DinoxError('Token is required');
28
+ }
29
+ const previousConfig = await loadConfig();
30
+ const pendingConfig = buildPendingAuthConfig(previousConfig, rawToken);
31
+ const resolved = resolveConfig(pendingConfig);
32
+ const timeoutMs = parseSyncTimeoutMs(context.globals.syncTimeout) ?? resolved.sync.timeoutMs;
33
+ const structuredOutput = getRequestedStructuredOutputFormat() !== null;
34
+ await fetchCredentialsWithAuthorization({
35
+ authorization: rawToken,
36
+ endpoint: resolved.powersync.endpoint,
37
+ credentialsUrl: resolved.powersync.tokenEndpoint,
38
+ timeoutMs,
86
39
  });
87
- auth
88
- .command('logout')
89
- .description('Clear saved login token')
90
- .option('--clear-local-db', 'delete the local PowerSync SQLite database')
91
- .action(async (options) => {
92
- const config = await loadConfig();
93
- if (config.auth) {
94
- config.auth.authorization = undefined;
95
- config.auth.userId = undefined;
96
- config.auth.username = undefined;
97
- config.auth.email = undefined;
98
- config.auth.userInfoSyncedAt = undefined;
99
- }
100
- await saveConfig(config);
101
- if (options.clearLocalDb) {
102
- const dbPath = getPowerSyncDbPath();
103
- await removeSqliteArtifacts(dbPath);
104
- }
40
+ const identity = await fetchUserInfoWithAuthorization({
41
+ authorization: rawToken,
42
+ config: resolved,
43
+ timeoutMs,
105
44
  });
106
- auth
107
- .command('status')
108
- .description('Show current login and sync status')
109
- .action(async (_options, command) => {
110
- const config = await loadConfig();
111
- const resolved = resolveConfig(config);
112
- const globals = command.optsWithGlobals?.() ?? {};
113
- const offline = Boolean(globals.offline);
114
- const jsonOutput = Boolean(globals.json);
115
- const timeoutMs = parseSyncTimeoutMs(globals.syncTimeout) ?? resolved.sync.timeoutMs;
116
- const dbPath = getPowerSyncDbPath();
117
- const base = {
118
- loggedIn: Boolean(resolved.auth.authorization),
119
- authorization: redactAuthorization(resolved.auth.authorization),
120
- userId: resolved.auth.userId ?? null,
121
- username: resolved.auth.username ?? null,
122
- email: resolved.auth.email ?? null,
123
- powersync: {
124
- endpoint: resolved.powersync.endpoint ?? null,
125
- tokenEndpoint: resolved.powersync.tokenEndpoint ?? null,
126
- uploadBaseUrl: resolved.powersync.uploadBaseUrl ?? null,
127
- uploadV4Path: resolved.powersync.uploadV4Path,
128
- uploadV2Path: resolved.powersync.uploadV2Path,
129
- },
45
+ const verifiedConfig = mergeAuthIdentityIntoConfig(previousConfig, rawToken, identity);
46
+ const verifiedResolved = resolveConfig(verifiedConfig);
47
+ const { db, dbPath, stale } = await connectPowerSync({
48
+ config: verifiedResolved,
49
+ offline: false,
50
+ timeoutMs,
51
+ });
52
+ try {
53
+ await runSingleSyncPass(db, timeoutMs);
54
+ await saveConfig(verifiedConfig);
55
+ const status = getStatusSnapshot(db);
56
+ const result = {
57
+ ok: true,
58
+ verified: true,
59
+ endpoint: verifiedResolved.powersync.endpoint,
130
60
  dbPath,
61
+ stale,
62
+ lastSyncedAt: status.lastSyncedAt,
63
+ userId: identity.userId,
131
64
  };
132
- if (offline || !resolved.auth.authorization || !resolved.powersync.endpoint || !resolved.powersync.tokenEndpoint) {
133
- const payload = { ...base, offline: true };
134
- if (jsonOutput) {
135
- printYaml(payload);
136
- }
137
- else {
138
- console.log(`loggedIn: ${payload.loggedIn ? 'yes' : 'no'}`);
139
- if (payload.userId) {
140
- console.log(`userId: ${payload.userId}`);
141
- }
142
- console.log(`db: ${payload.dbPath}`);
143
- console.log(`powersync.endpoint: ${payload.powersync.endpoint ?? '(unset)'}`);
144
- console.log(`powersync.tokenEndpoint: ${payload.powersync.tokenEndpoint ?? '(unset)'}`);
145
- console.log(`powersync.uploadBaseUrl: ${payload.powersync.uploadBaseUrl ?? '(unset)'}`);
146
- }
65
+ if (structuredOutput) {
66
+ printSuccess(result);
147
67
  return;
148
68
  }
149
- const { db, stale } = await connectPowerSync({
150
- config: resolved,
151
- offline: false,
152
- timeoutMs,
69
+ printHumanReadableLine('Login verified.');
70
+ printHumanReadableLine(`- endpoint: ${result.endpoint}`);
71
+ printHumanReadableLine(`- db: ${result.dbPath}`);
72
+ printHumanReadableLine(`- userId: ${result.userId}`);
73
+ if (result.lastSyncedAt) {
74
+ printHumanReadableLine(`- lastSyncedAt: ${result.lastSyncedAt}`);
75
+ }
76
+ if (stale) {
77
+ printHumanReadableLine('- warning: initial sync timed out; local cache may be stale');
78
+ }
79
+ }
80
+ finally {
81
+ await db.close().catch(() => undefined);
82
+ }
83
+ }
84
+ async function runAuthLogout(context) {
85
+ const options = context.options;
86
+ const config = await loadConfig();
87
+ const currentUserId = config.auth?.userId;
88
+ if (config.auth) {
89
+ config.auth.authorization = undefined;
90
+ config.auth.userId = undefined;
91
+ config.auth.username = undefined;
92
+ config.auth.email = undefined;
93
+ config.auth.userInfoSyncedAt = undefined;
94
+ }
95
+ await saveConfig(config);
96
+ if (options.clearLocalDb) {
97
+ await removeSqliteArtifacts(getPowerSyncDbPath(currentUserId));
98
+ await removeSqliteArtifacts(getLegacyPowerSyncDbPath());
99
+ }
100
+ if (getRequestedStructuredOutputFormat()) {
101
+ printSuccess({
102
+ ok: true,
103
+ loggedOut: true,
104
+ clearedLocalDb: Boolean(options.clearLocalDb),
153
105
  });
154
- try {
155
- const status = getStatusSnapshot(db);
156
- const payload = { ...base, offline: false, stale, status };
157
- if (jsonOutput) {
158
- printYaml(payload);
159
- }
160
- else {
161
- console.log(`loggedIn: ${payload.loggedIn ? 'yes' : 'no'}`);
162
- if (payload.userId) {
163
- console.log(`userId: ${payload.userId}`);
164
- }
165
- console.log(`db: ${payload.dbPath}`);
166
- console.log(`connected: ${payload.status.connected ? 'yes' : 'no'}`);
167
- if (payload.status.lastSyncedAt) {
168
- console.log(`lastSyncedAt: ${payload.status.lastSyncedAt}`);
169
- }
170
- console.log(`dataFlow: downloading=${payload.status.dataFlowStatus.downloading} uploading=${payload.status.dataFlowStatus.uploading}`);
171
- if (payload.stale) {
172
- console.log('warning: sync timed out; local cache may be stale');
173
- }
174
- }
106
+ }
107
+ }
108
+ async function runAuthStatus(context) {
109
+ const config = await loadConfig();
110
+ const resolved = resolveConfig(config);
111
+ const offline = Boolean(context.globals.offline);
112
+ const structuredOutput = getRequestedStructuredOutputFormat() !== null;
113
+ const timeoutMs = parseSyncTimeoutMs(context.globals.syncTimeout) ?? resolved.sync.timeoutMs;
114
+ const dbPath = getPowerSyncDbPath(resolved.auth.userId);
115
+ const base = {
116
+ loggedIn: Boolean(resolved.auth.authorization),
117
+ authorization: redactAuthorization(resolved.auth.authorization),
118
+ userId: resolved.auth.userId ?? null,
119
+ username: resolved.auth.username ?? null,
120
+ email: resolved.auth.email ?? null,
121
+ powersync: {
122
+ endpoint: resolved.powersync.endpoint ?? null,
123
+ tokenEndpoint: resolved.powersync.tokenEndpoint ?? null,
124
+ uploadBaseUrl: resolved.powersync.uploadBaseUrl ?? null,
125
+ uploadV4Path: resolved.powersync.uploadV4Path,
126
+ uploadV2Path: resolved.powersync.uploadV2Path,
127
+ },
128
+ dbPath,
129
+ };
130
+ if (offline || !resolved.auth.authorization || !resolved.powersync.endpoint || !resolved.powersync.tokenEndpoint) {
131
+ const payload = { ...base, offline: true };
132
+ if (structuredOutput) {
133
+ printSuccess(payload);
134
+ return;
175
135
  }
176
- finally {
177
- await db.close().catch(() => undefined);
136
+ printHumanReadableLine(`loggedIn: ${payload.loggedIn ? 'yes' : 'no'}`);
137
+ if (payload.userId) {
138
+ printHumanReadableLine(`userId: ${payload.userId}`);
178
139
  }
140
+ printHumanReadableLine(`db: ${payload.dbPath}`);
141
+ printHumanReadableLine(`powersync.endpoint: ${payload.powersync.endpoint ?? '(unset)'}`);
142
+ printHumanReadableLine(`powersync.tokenEndpoint: ${payload.powersync.tokenEndpoint ?? '(unset)'}`);
143
+ printHumanReadableLine(`powersync.uploadBaseUrl: ${payload.powersync.uploadBaseUrl ?? '(unset)'}`);
144
+ return;
145
+ }
146
+ const { db, stale } = await connectPowerSync({
147
+ config: resolved,
148
+ offline: false,
149
+ timeoutMs,
179
150
  });
180
- auth.action((_options, command) => {
181
- command.outputHelp();
182
- });
151
+ try {
152
+ const status = getStatusSnapshot(db);
153
+ const payload = { ...base, offline: false, stale, status };
154
+ if (structuredOutput) {
155
+ printSuccess(payload);
156
+ return;
157
+ }
158
+ printHumanReadableLine(`loggedIn: ${payload.loggedIn ? 'yes' : 'no'}`);
159
+ if (payload.userId) {
160
+ printHumanReadableLine(`userId: ${payload.userId}`);
161
+ }
162
+ printHumanReadableLine(`db: ${payload.dbPath}`);
163
+ printHumanReadableLine(`connected: ${payload.status.connected ? 'yes' : 'no'}`);
164
+ if (payload.status.lastSyncedAt) {
165
+ printHumanReadableLine(`lastSyncedAt: ${payload.status.lastSyncedAt}`);
166
+ }
167
+ printHumanReadableLine(`dataFlow: downloading=${payload.status.dataFlowStatus.downloading} uploading=${payload.status.dataFlowStatus.uploading}`);
168
+ if (payload.stale) {
169
+ printHumanReadableLine('warning: sync timed out; local cache may be stale');
170
+ }
171
+ }
172
+ finally {
173
+ await db.close().catch(() => undefined);
174
+ }
175
+ }
176
+ export const authCommandGroup = {
177
+ name: 'auth',
178
+ description: 'Authentication and PowerSync connectivity commands',
179
+ commands: [
180
+ {
181
+ name: 'login',
182
+ description: 'Save login token and verify PowerSync connectivity',
183
+ arguments: [{ syntax: '<token>', description: 'Login token (without Bearer prefix)' }],
184
+ schema: {
185
+ path: 'auth.login',
186
+ risk: 'write',
187
+ auth: 'optional',
188
+ globalOptions: AUTH_LOGIN_GLOBAL_OPTIONS,
189
+ output: {
190
+ type: 'structured',
191
+ summary: 'Login verification result',
192
+ fields: ['verified', 'endpoint', 'dbPath', 'stale', 'lastSyncedAt', 'userId'],
193
+ },
194
+ examples: ['dino auth login "<token>" --format json'],
195
+ },
196
+ action: runAuthLogin,
197
+ },
198
+ {
199
+ name: 'logout',
200
+ description: 'Clear saved login token and optionally remove the local cache',
201
+ options: [{ flags: '--clear-local-db', description: 'Delete the local PowerSync SQLite database' }],
202
+ schema: {
203
+ path: 'auth.logout',
204
+ risk: 'write',
205
+ auth: 'optional',
206
+ globalOptions: FORMAT_OPTIONS,
207
+ output: {
208
+ type: 'structured',
209
+ summary: 'Logout acknowledgement',
210
+ fields: ['loggedOut', 'clearedLocalDb'],
211
+ },
212
+ examples: ['dino auth logout --format json', 'dino auth logout --clear-local-db --format json'],
213
+ },
214
+ action: runAuthLogout,
215
+ },
216
+ {
217
+ name: 'status',
218
+ description: 'Show current login, local cache, and sync status',
219
+ schema: {
220
+ path: 'auth.status',
221
+ risk: 'read',
222
+ auth: 'optional',
223
+ globalOptions: AUTH_STATUS_GLOBAL_OPTIONS,
224
+ output: {
225
+ type: 'structured',
226
+ summary: 'Auth and connectivity status envelope',
227
+ fields: ['loggedIn', 'authorization', 'userId', 'username', 'email', 'powersync', 'dbPath', 'offline', 'stale', 'status'],
228
+ },
229
+ examples: ['dino auth status --format json', 'dino auth status --offline --format json'],
230
+ },
231
+ action: runAuthStatus,
232
+ },
233
+ ],
234
+ };
235
+ export function registerAuthCommands(program) {
236
+ registerCommandGroup(program, authCommandGroup);
183
237
  }
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import type { CommandGroupDescriptor } from '../descriptor/types.js';
3
+ export declare const boxCommandGroup: CommandGroupDescriptor;
2
4
  export declare function registerBoxesCommand(program: Command): void;