@prisma-next/cli 0.3.0-dev.6 → 0.3.0-dev.63

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 (180) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +314 -80
  3. package/dist/cli-errors-JlPTsazx.mjs +3 -0
  4. package/dist/cli.d.mts +1 -0
  5. package/dist/cli.js +1 -2376
  6. package/dist/cli.mjs +198 -0
  7. package/dist/cli.mjs.map +1 -0
  8. package/dist/client-PimzSD1f.mjs +981 -0
  9. package/dist/client-PimzSD1f.mjs.map +1 -0
  10. package/dist/commands/contract-emit.d.mts +7 -0
  11. package/dist/commands/contract-emit.d.mts.map +1 -0
  12. package/dist/commands/contract-emit.mjs +150 -0
  13. package/dist/commands/contract-emit.mjs.map +1 -0
  14. package/dist/commands/db-init.d.mts +7 -0
  15. package/dist/commands/db-init.d.mts.map +1 -0
  16. package/dist/commands/db-init.mjs +132 -0
  17. package/dist/commands/db-init.mjs.map +1 -0
  18. package/dist/commands/db-introspect.d.mts +7 -0
  19. package/dist/commands/db-introspect.d.mts.map +1 -0
  20. package/dist/commands/db-introspect.mjs +117 -0
  21. package/dist/commands/db-introspect.mjs.map +1 -0
  22. package/dist/commands/db-schema-verify.d.mts +7 -0
  23. package/dist/commands/db-schema-verify.d.mts.map +1 -0
  24. package/dist/commands/db-schema-verify.mjs +119 -0
  25. package/dist/commands/db-schema-verify.mjs.map +1 -0
  26. package/dist/commands/db-sign.d.mts +7 -0
  27. package/dist/commands/db-sign.d.mts.map +1 -0
  28. package/dist/commands/db-sign.mjs +141 -0
  29. package/dist/commands/db-sign.mjs.map +1 -0
  30. package/dist/commands/db-update.d.mts +7 -0
  31. package/dist/commands/db-update.d.mts.map +1 -0
  32. package/dist/commands/db-update.mjs +121 -0
  33. package/dist/commands/db-update.mjs.map +1 -0
  34. package/dist/commands/db-verify.d.mts +7 -0
  35. package/dist/commands/db-verify.d.mts.map +1 -0
  36. package/dist/commands/db-verify.mjs +132 -0
  37. package/dist/commands/db-verify.mjs.map +1 -0
  38. package/dist/commands/migration-apply.d.mts +23 -0
  39. package/dist/commands/migration-apply.d.mts.map +1 -0
  40. package/dist/commands/migration-apply.mjs +249 -0
  41. package/dist/commands/migration-apply.mjs.map +1 -0
  42. package/dist/commands/migration-plan.d.mts +25 -0
  43. package/dist/commands/migration-plan.d.mts.map +1 -0
  44. package/dist/commands/migration-plan.mjs +266 -0
  45. package/dist/commands/migration-plan.mjs.map +1 -0
  46. package/dist/commands/migration-show.d.mts +28 -0
  47. package/dist/commands/migration-show.d.mts.map +1 -0
  48. package/dist/commands/migration-show.mjs +138 -0
  49. package/dist/commands/migration-show.mjs.map +1 -0
  50. package/dist/commands/migration-status.d.mts +35 -0
  51. package/dist/commands/migration-status.d.mts.map +1 -0
  52. package/dist/commands/migration-status.mjs +259 -0
  53. package/dist/commands/migration-status.mjs.map +1 -0
  54. package/dist/commands/migration-verify.d.mts +16 -0
  55. package/dist/commands/migration-verify.d.mts.map +1 -0
  56. package/dist/commands/migration-verify.mjs +86 -0
  57. package/dist/commands/migration-verify.mjs.map +1 -0
  58. package/dist/config-loader-PPf4CtDj.mjs +43 -0
  59. package/dist/config-loader-PPf4CtDj.mjs.map +1 -0
  60. package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
  61. package/dist/config-loader.d.mts.map +1 -0
  62. package/dist/config-loader.mjs +3 -0
  63. package/dist/exports/config-types.d.mts +2 -0
  64. package/dist/exports/config-types.mjs +3 -0
  65. package/dist/exports/control-api.d.mts +621 -0
  66. package/dist/exports/control-api.d.mts.map +1 -0
  67. package/dist/exports/control-api.mjs +97 -0
  68. package/dist/exports/control-api.mjs.map +1 -0
  69. package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +10 -5
  70. package/dist/exports/index.d.mts.map +1 -0
  71. package/dist/exports/index.mjs +130 -0
  72. package/dist/exports/index.mjs.map +1 -0
  73. package/dist/extract-sql-ddl-BmlKvk4o.mjs +26 -0
  74. package/dist/extract-sql-ddl-BmlKvk4o.mjs.map +1 -0
  75. package/dist/framework-components-CjV_jD8f.mjs +59 -0
  76. package/dist/framework-components-CjV_jD8f.mjs.map +1 -0
  77. package/dist/migration-command-scaffold-DfY_F3ev.mjs +97 -0
  78. package/dist/migration-command-scaffold-DfY_F3ev.mjs.map +1 -0
  79. package/dist/progress-adapter-DENrzF6I.mjs +49 -0
  80. package/dist/progress-adapter-DENrzF6I.mjs.map +1 -0
  81. package/dist/result-handler-iA9JtUC7.mjs +1186 -0
  82. package/dist/result-handler-iA9JtUC7.mjs.map +1 -0
  83. package/package.json +75 -38
  84. package/src/cli.ts +43 -0
  85. package/src/commands/contract-emit.ts +221 -111
  86. package/src/commands/db-init.ts +217 -426
  87. package/src/commands/db-introspect.ts +148 -185
  88. package/src/commands/db-schema-verify.ts +162 -149
  89. package/src/commands/db-sign.ts +215 -202
  90. package/src/commands/db-update.ts +220 -0
  91. package/src/commands/db-verify.ts +193 -156
  92. package/src/commands/migration-apply.ts +431 -0
  93. package/src/commands/migration-plan.ts +446 -0
  94. package/src/commands/migration-show.ts +255 -0
  95. package/src/commands/migration-status.ts +436 -0
  96. package/src/commands/migration-verify.ts +151 -0
  97. package/src/config-loader.ts +13 -3
  98. package/src/control-api/client.ts +605 -0
  99. package/src/control-api/errors.ts +9 -0
  100. package/src/control-api/operations/contract-emit.ts +161 -0
  101. package/src/control-api/operations/db-init.ts +286 -0
  102. package/src/control-api/operations/db-update.ts +221 -0
  103. package/src/control-api/operations/extract-sql-ddl.ts +47 -0
  104. package/src/control-api/operations/migration-apply.ts +195 -0
  105. package/src/control-api/operations/migration-helpers.ts +49 -0
  106. package/src/control-api/types.ts +687 -0
  107. package/src/exports/config-types.ts +3 -3
  108. package/src/exports/control-api.ts +53 -0
  109. package/src/load-ts-contract.ts +16 -11
  110. package/src/utils/cli-errors.ts +3 -1
  111. package/src/utils/command-helpers.ts +92 -3
  112. package/src/utils/framework-components.ts +11 -30
  113. package/src/utils/migration-command-scaffold.ts +190 -0
  114. package/src/utils/output.ts +363 -25
  115. package/src/utils/progress-adapter.ts +86 -0
  116. package/dist/chunk-464LNZCE.js +0 -134
  117. package/dist/chunk-464LNZCE.js.map +0 -1
  118. package/dist/chunk-BZMBKEEQ.js +0 -997
  119. package/dist/chunk-BZMBKEEQ.js.map +0 -1
  120. package/dist/chunk-HWYQOCAJ.js +0 -47
  121. package/dist/chunk-HWYQOCAJ.js.map +0 -1
  122. package/dist/chunk-ZKYEJROM.js +0 -94
  123. package/dist/chunk-ZKYEJROM.js.map +0 -1
  124. package/dist/cli.d.ts +0 -2
  125. package/dist/cli.d.ts.map +0 -1
  126. package/dist/cli.js.map +0 -1
  127. package/dist/commands/contract-emit.d.ts +0 -3
  128. package/dist/commands/contract-emit.d.ts.map +0 -1
  129. package/dist/commands/contract-emit.js +0 -9
  130. package/dist/commands/contract-emit.js.map +0 -1
  131. package/dist/commands/db-init.d.ts +0 -3
  132. package/dist/commands/db-init.d.ts.map +0 -1
  133. package/dist/commands/db-init.js +0 -341
  134. package/dist/commands/db-init.js.map +0 -1
  135. package/dist/commands/db-introspect.d.ts +0 -3
  136. package/dist/commands/db-introspect.d.ts.map +0 -1
  137. package/dist/commands/db-introspect.js +0 -190
  138. package/dist/commands/db-introspect.js.map +0 -1
  139. package/dist/commands/db-schema-verify.d.ts +0 -3
  140. package/dist/commands/db-schema-verify.d.ts.map +0 -1
  141. package/dist/commands/db-schema-verify.js +0 -164
  142. package/dist/commands/db-schema-verify.js.map +0 -1
  143. package/dist/commands/db-sign.d.ts +0 -3
  144. package/dist/commands/db-sign.d.ts.map +0 -1
  145. package/dist/commands/db-sign.js +0 -199
  146. package/dist/commands/db-sign.js.map +0 -1
  147. package/dist/commands/db-verify.d.ts +0 -3
  148. package/dist/commands/db-verify.d.ts.map +0 -1
  149. package/dist/commands/db-verify.js +0 -173
  150. package/dist/commands/db-verify.js.map +0 -1
  151. package/dist/config-loader.d.ts.map +0 -1
  152. package/dist/config-loader.js +0 -7
  153. package/dist/config-loader.js.map +0 -1
  154. package/dist/exports/config-types.d.ts +0 -3
  155. package/dist/exports/config-types.d.ts.map +0 -1
  156. package/dist/exports/config-types.js +0 -6
  157. package/dist/exports/config-types.js.map +0 -1
  158. package/dist/exports/index.d.ts +0 -4
  159. package/dist/exports/index.d.ts.map +0 -1
  160. package/dist/exports/index.js +0 -175
  161. package/dist/exports/index.js.map +0 -1
  162. package/dist/load-ts-contract.d.ts.map +0 -1
  163. package/dist/utils/action.d.ts +0 -16
  164. package/dist/utils/action.d.ts.map +0 -1
  165. package/dist/utils/cli-errors.d.ts +0 -7
  166. package/dist/utils/cli-errors.d.ts.map +0 -1
  167. package/dist/utils/command-helpers.d.ts +0 -12
  168. package/dist/utils/command-helpers.d.ts.map +0 -1
  169. package/dist/utils/framework-components.d.ts +0 -81
  170. package/dist/utils/framework-components.d.ts.map +0 -1
  171. package/dist/utils/global-flags.d.ts +0 -25
  172. package/dist/utils/global-flags.d.ts.map +0 -1
  173. package/dist/utils/output.d.ts +0 -142
  174. package/dist/utils/output.d.ts.map +0 -1
  175. package/dist/utils/result-handler.d.ts +0 -15
  176. package/dist/utils/result-handler.d.ts.map +0 -1
  177. package/dist/utils/spinner.d.ts +0 -29
  178. package/dist/utils/spinner.d.ts.map +0 -1
  179. package/src/utils/action.ts +0 -43
  180. package/src/utils/spinner.ts +0 -67
@@ -1,27 +1,27 @@
1
- import { readFile } from 'node:fs/promises';
2
1
  import { relative, resolve } from 'node:path';
3
- import {
4
- errorDatabaseUrlRequired,
5
- errorDriverRequired,
6
- errorRuntime,
7
- errorUnexpected,
8
- } from '@prisma-next/core-control-plane/errors';
9
2
  import type { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';
10
3
  import type { IntrospectSchemaResult } from '@prisma-next/core-control-plane/types';
4
+ import { notOk, ok, type Result } from '@prisma-next/utils/result';
11
5
  import { Command } from 'commander';
12
6
  import { loadConfig } from '../config-loader';
13
- import { performAction } from '../utils/action';
14
- import { setCommandDescriptions } from '../utils/command-helpers';
15
- import { assertContractRequirementsSatisfied } from '../utils/framework-components';
16
- import { parseGlobalFlags } from '../utils/global-flags';
7
+ import { createControlClient } from '../control-api/client';
8
+ import {
9
+ CliStructuredError,
10
+ errorDatabaseConnectionRequired,
11
+ errorDriverRequired,
12
+ errorJsonFormatNotSupported,
13
+ errorUnexpected,
14
+ } from '../utils/cli-errors';
15
+ import { maskConnectionUrl, setCommandDescriptions } from '../utils/command-helpers';
16
+ import { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';
17
17
  import {
18
18
  formatCommandHelp,
19
19
  formatIntrospectJson,
20
20
  formatIntrospectOutput,
21
21
  formatStyledHeader,
22
22
  } from '../utils/output';
23
+ import { createProgressAdapter } from '../utils/progress-adapter';
23
24
  import { handleResult } from '../utils/result-handler';
24
- import { withSpinner } from '../utils/spinner';
25
25
 
26
26
  interface DbIntrospectOptions {
27
27
  readonly db?: string;
@@ -38,6 +38,128 @@ interface DbIntrospectOptions {
38
38
  readonly 'no-color'?: boolean;
39
39
  }
40
40
 
41
+ interface DbIntrospectCommandResult {
42
+ readonly introspectResult: IntrospectSchemaResult<unknown>;
43
+ readonly schemaView: CoreSchemaView | undefined;
44
+ }
45
+
46
+ /**
47
+ * Executes the db introspect command and returns a structured Result.
48
+ */
49
+ async function executeDbIntrospectCommand(
50
+ options: DbIntrospectOptions,
51
+ flags: GlobalFlags,
52
+ startTime: number,
53
+ ): Promise<Result<DbIntrospectCommandResult, CliStructuredError>> {
54
+ // Load config
55
+ const config = await loadConfig(options.config);
56
+ const configPath = options.config
57
+ ? relative(process.cwd(), resolve(options.config))
58
+ : 'prisma-next.config.ts';
59
+
60
+ // Output header
61
+ if (flags.json !== 'object' && !flags.quiet) {
62
+ const details: Array<{ label: string; value: string }> = [
63
+ { label: 'config', value: configPath },
64
+ ];
65
+ if (options.db) {
66
+ details.push({ label: 'database', value: maskConnectionUrl(options.db) });
67
+ } else if (config.db?.connection && typeof config.db.connection === 'string') {
68
+ details.push({ label: 'database', value: maskConnectionUrl(config.db.connection) });
69
+ }
70
+ const header = formatStyledHeader({
71
+ command: 'db introspect',
72
+ description: 'Inspect the database schema',
73
+ url: 'https://pris.ly/db-introspect',
74
+ details,
75
+ flags,
76
+ });
77
+ console.log(header);
78
+ }
79
+
80
+ // Resolve database connection (--db flag or config.db.connection)
81
+ const dbConnection = options.db ?? config.db?.connection;
82
+ if (!dbConnection) {
83
+ return notOk(
84
+ errorDatabaseConnectionRequired({
85
+ why: `Database connection is required for db introspect (set db.connection in ${configPath}, or pass --db <url>)`,
86
+ }),
87
+ );
88
+ }
89
+
90
+ // Check for driver
91
+ if (!config.driver) {
92
+ return notOk(errorDriverRequired({ why: 'Config.driver is required for db introspect' }));
93
+ }
94
+
95
+ // Create control client
96
+ const client = createControlClient({
97
+ family: config.family,
98
+ target: config.target,
99
+ adapter: config.adapter,
100
+ driver: config.driver,
101
+ extensionPacks: config.extensionPacks ?? [],
102
+ });
103
+
104
+ // Create progress adapter
105
+ const onProgress = createProgressAdapter({ flags });
106
+
107
+ try {
108
+ // Introspect with connection and progress
109
+ const schemaIR = await client.introspect({
110
+ connection: dbConnection,
111
+ onProgress,
112
+ });
113
+
114
+ // Add blank line after all async operations if spinners were shown
115
+ if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {
116
+ console.log('');
117
+ }
118
+
119
+ // Call toSchemaView to convert schema IR to CoreSchemaView for tree rendering
120
+ const schemaView = client.toSchemaView(schemaIR);
121
+
122
+ const totalTime = Date.now() - startTime;
123
+
124
+ // Get masked connection URL for meta (only for string connections)
125
+ const connectionForMeta =
126
+ typeof dbConnection === 'string' ? maskConnectionUrl(dbConnection) : undefined;
127
+
128
+ const introspectResult: IntrospectSchemaResult<unknown> = {
129
+ ok: true,
130
+ summary: 'Schema introspected successfully',
131
+ target: {
132
+ familyId: config.family.familyId,
133
+ id: config.target.targetId,
134
+ },
135
+ schema: schemaIR,
136
+ meta: {
137
+ ...(configPath ? { configPath } : {}),
138
+ ...(connectionForMeta ? { dbUrl: connectionForMeta } : {}),
139
+ },
140
+ timings: {
141
+ total: totalTime,
142
+ },
143
+ };
144
+
145
+ return ok({ introspectResult, schemaView });
146
+ } catch (error) {
147
+ // Driver already throws CliStructuredError for connection failures
148
+ if (error instanceof CliStructuredError) {
149
+ return notOk(error);
150
+ }
151
+
152
+ // Wrap unexpected errors
153
+ return notOk(
154
+ errorUnexpected(error instanceof Error ? error.message : String(error), {
155
+ why: `Unexpected error during db introspect: ${error instanceof Error ? error.message : String(error)}`,
156
+ }),
157
+ );
158
+ } finally {
159
+ await client.close();
160
+ }
161
+ }
162
+
41
163
  export function createDbIntrospectCommand(): Command {
42
164
  const command = new Command('introspect');
43
165
  setCommandDescriptions(
@@ -56,7 +178,7 @@ export function createDbIntrospectCommand(): Command {
56
178
  })
57
179
  .option('--db <url>', 'Database connection string')
58
180
  .option('--config <path>', 'Path to prisma-next.config.ts')
59
- .option('--json [format]', 'Output as JSON (object or ndjson)', false)
181
+ .option('--json [format]', 'Output as JSON (object)', false)
60
182
  .option('-q, --quiet', 'Quiet mode: errors only')
61
183
  .option('-v, --verbose', 'Verbose output: debug info, timings')
62
184
  .option('-vv, --trace', 'Trace output: deep internals, stack traces')
@@ -65,188 +187,29 @@ export function createDbIntrospectCommand(): Command {
65
187
  .option('--no-color', 'Disable color output')
66
188
  .action(async (options: DbIntrospectOptions) => {
67
189
  const flags = parseGlobalFlags(options);
190
+ const startTime = Date.now();
68
191
 
69
- const result = await performAction(async () => {
70
- const startTime = Date.now();
71
-
72
- // Load config (file I/O)
73
- const config = await loadConfig(options.config);
74
- // Normalize config path for display (match contract path format - no ./ prefix)
75
- const configPath = options.config
76
- ? relative(process.cwd(), resolve(options.config))
77
- : 'prisma-next.config.ts';
78
-
79
- // Optionally load contract if contract config exists
80
- let contractIR: unknown | undefined;
81
- if (config.contract?.output) {
82
- const contractPath = resolve(config.contract.output);
83
- try {
84
- const contractJsonContent = await readFile(contractPath, 'utf-8');
85
- contractIR = JSON.parse(contractJsonContent);
86
- } catch (error) {
87
- // Contract file is optional for introspection - don't fail if it doesn't exist
88
- if (error instanceof Error && (error as { code?: string }).code !== 'ENOENT') {
89
- throw errorUnexpected(error.message, {
90
- why: `Failed to read contract file: ${error.message}`,
91
- });
92
- }
93
- }
94
- }
95
-
96
- // Output header (only for human-readable output)
97
- if (flags.json !== 'object' && !flags.quiet) {
98
- const details: Array<{ label: string; value: string }> = [
99
- { label: 'config', value: configPath },
100
- ];
101
- if (options.db) {
102
- // Mask password in URL for security
103
- const maskedUrl = options.db.replace(/:([^:@]+)@/, ':****@');
104
- details.push({ label: 'database', value: maskedUrl });
105
- } else if (config.db?.url) {
106
- // Mask password in URL for security
107
- const maskedUrl = config.db.url.replace(/:([^:@]+)@/, ':****@');
108
- details.push({ label: 'database', value: maskedUrl });
109
- }
110
- const header = formatStyledHeader({
192
+ // Validate JSON format option
193
+ if (flags.json === 'ndjson') {
194
+ const result = notOk(
195
+ errorJsonFormatNotSupported({
111
196
  command: 'db introspect',
112
- description: 'Inspect the database schema',
113
- url: 'https://pris.ly/db-introspect',
114
- details,
115
- flags,
116
- });
117
- console.log(header);
118
- }
119
-
120
- // Resolve database URL
121
- const dbUrl = options.db ?? config.db?.url;
122
- if (!dbUrl) {
123
- throw errorDatabaseUrlRequired();
124
- }
197
+ format: 'ndjson',
198
+ supportedFormats: ['object'],
199
+ }),
200
+ );
201
+ const exitCode = handleResult(result, flags);
202
+ process.exit(exitCode);
203
+ }
125
204
 
126
- // Check for driver
127
- if (!config.driver) {
128
- throw errorDriverRequired();
129
- }
130
-
131
- // Store driver descriptor after null check
132
- const driverDescriptor = config.driver;
133
-
134
- // Create driver
135
- const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {
136
- message: 'Connecting to database...',
137
- flags,
138
- });
139
-
140
- try {
141
- // Create family instance
142
- const familyInstance = config.family.create({
143
- target: config.target,
144
- adapter: config.adapter,
145
- driver: driverDescriptor,
146
- extensionPacks: config.extensionPacks ?? [],
147
- });
148
-
149
- // Validate contract IR if we loaded it
150
- if (contractIR) {
151
- const validatedContract = familyInstance.validateContractIR(contractIR);
152
- assertContractRequirementsSatisfied({
153
- contract: validatedContract,
154
- family: config.family,
155
- target: config.target,
156
- adapter: config.adapter,
157
- extensionPacks: config.extensionPacks,
158
- });
159
- contractIR = validatedContract;
160
- }
161
-
162
- // Call family instance introspect method
163
- let schemaIR: unknown;
164
- try {
165
- schemaIR = await withSpinner(
166
- () =>
167
- familyInstance.introspect({
168
- driver,
169
- contractIR,
170
- }),
171
- {
172
- message: 'Introspecting database schema...',
173
- flags,
174
- },
175
- );
176
- } catch (error) {
177
- // Wrap errors from introspect() in structured error
178
- throw errorRuntime(error instanceof Error ? error.message : String(error), {
179
- why: `Failed to introspect database: ${error instanceof Error ? error.message : String(error)}`,
180
- });
181
- }
182
-
183
- // Optionally call toSchemaView if available
184
- let schemaView: CoreSchemaView | undefined;
185
- if (familyInstance.toSchemaView) {
186
- try {
187
- schemaView = familyInstance.toSchemaView(schemaIR);
188
- } catch (error) {
189
- // Schema view projection is optional - log but don't fail
190
- if (flags.verbose) {
191
- console.error(
192
- `Warning: Failed to project schema to view: ${error instanceof Error ? error.message : String(error)}`,
193
- );
194
- }
195
- }
196
- }
197
-
198
- const totalTime = Date.now() - startTime;
199
-
200
- // Add blank line after all async operations if spinners were shown
201
- if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {
202
- console.log('');
203
- }
204
-
205
- // Build result envelope
206
- const introspectResult: IntrospectSchemaResult<unknown> = {
207
- ok: true,
208
- summary: 'Schema introspected successfully',
209
- target: {
210
- familyId: config.family.familyId,
211
- id: config.target.targetId,
212
- },
213
- schema: schemaIR,
214
- ...(configPath || options.db || config.db?.url
215
- ? {
216
- meta: {
217
- ...(configPath ? { configPath } : {}),
218
- ...(options.db || config.db?.url
219
- ? {
220
- dbUrl: (options.db ?? config.db?.url ?? '').replace(
221
- /:([^:@]+)@/,
222
- ':****@',
223
- ),
224
- }
225
- : {}),
226
- },
227
- }
228
- : {}),
229
- timings: {
230
- total: totalTime,
231
- },
232
- };
233
-
234
- return { introspectResult, schemaView };
235
- } finally {
236
- // Ensure driver connection is closed
237
- await driver.close();
238
- }
239
- });
205
+ const result = await executeDbIntrospectCommand(options, flags, startTime);
240
206
 
241
207
  // Handle result - formats output and returns exit code
242
208
  const exitCode = handleResult(result, flags, (value) => {
243
209
  const { introspectResult, schemaView } = value;
244
- // Output based on flags
245
210
  if (flags.json === 'object') {
246
- // JSON output to stdout
247
211
  console.log(formatIntrospectJson(introspectResult));
248
212
  } else {
249
- // Human-readable output to stdout
250
213
  const output = formatIntrospectOutput(introspectResult, schemaView, flags);
251
214
  if (output) {
252
215
  console.log(output);