@zmdb/cli 1.0.0-beta.1
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/LICENSE +674 -0
- package/README.md +19 -0
- package/dist/__fixtures__/http-client/src/contract.d.ts +38 -0
- package/dist/__fixtures__/http-client/src/contract.d.ts.map +1 -0
- package/dist/__fixtures__/http-client/src/contract.js +121 -0
- package/dist/__fixtures__/http-client/src/contract.js.map +1 -0
- package/dist/__fixtures__/http-client/src/models.d.ts +11 -0
- package/dist/__fixtures__/http-client/src/models.d.ts.map +1 -0
- package/dist/__fixtures__/http-client/src/models.js +2 -0
- package/dist/__fixtures__/http-client/src/models.js.map +1 -0
- package/dist/__fixtures__/http-client/src/schema.d.ts +4 -0
- package/dist/__fixtures__/http-client/src/schema.d.ts.map +1 -0
- package/dist/__fixtures__/http-client/src/schema.js +2 -0
- package/dist/__fixtures__/http-client/src/schema.js.map +1 -0
- package/dist/__fixtures__/http-client/src/unrelated.d.ts +2 -0
- package/dist/__fixtures__/http-client/src/unrelated.d.ts.map +1 -0
- package/dist/__fixtures__/http-client/src/unrelated.js +2 -0
- package/dist/__fixtures__/http-client/src/unrelated.js.map +1 -0
- package/dist/__fixtures__/http-client/zmdb.config.d.ts +16 -0
- package/dist/__fixtures__/http-client/zmdb.config.d.ts.map +1 -0
- package/dist/__fixtures__/http-client/zmdb.config.js +12 -0
- package/dist/__fixtures__/http-client/zmdb.config.js.map +1 -0
- package/dist/__fixtures__/project/src/schema.d.ts +6 -0
- package/dist/__fixtures__/project/src/schema.d.ts.map +1 -0
- package/dist/__fixtures__/project/src/schema.js +2 -0
- package/dist/__fixtures__/project/src/schema.js.map +1 -0
- package/dist/__fixtures__/project/zmdb.config.d.ts +22 -0
- package/dist/__fixtures__/project/zmdb.config.d.ts.map +1 -0
- package/dist/__fixtures__/project/zmdb.config.js +55 -0
- package/dist/__fixtures__/project/zmdb.config.js.map +1 -0
- package/dist/application-loader.d.ts +4 -0
- package/dist/application-loader.d.ts.map +1 -0
- package/dist/application-loader.js +102 -0
- package/dist/application-loader.js.map +1 -0
- package/dist/args.d.ts +23 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +353 -0
- package/dist/args.js.map +1 -0
- package/dist/atomic.d.ts +13 -0
- package/dist/atomic.d.ts.map +1 -0
- package/dist/atomic.js +28 -0
- package/dist/atomic.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +4 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/check.d.ts +5 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +7 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/client.d.ts +38 -0
- package/dist/commands/client.d.ts.map +1 -0
- package/dist/commands/client.js +347 -0
- package/dist/commands/client.js.map +1 -0
- package/dist/commands/codegen.d.ts +9 -0
- package/dist/commands/codegen.d.ts.map +1 -0
- package/dist/commands/codegen.js +56 -0
- package/dist/commands/codegen.js.map +1 -0
- package/dist/commands/embed.d.ts +8 -0
- package/dist/commands/embed.d.ts.map +1 -0
- package/dist/commands/embed.js +17 -0
- package/dist/commands/embed.js.map +1 -0
- package/dist/commands/export.d.ts +5 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +6 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/generate.d.ts +5 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +6 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/migrate.d.ts +9 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +18 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/new.d.ts +4 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +35 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/pull.d.ts +5 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +14 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +6 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +11 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/studio.d.ts +31 -0
- package/dist/commands/studio.d.ts.map +1 -0
- package/dist/commands/studio.js +154 -0
- package/dist/commands/studio.js.map +1 -0
- package/dist/commands/upgrade.d.ts +5 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +11 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/database.d.ts +4 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +8 -0
- package/dist/database.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +20 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +626 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle.d.ts +6 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +75 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/migration-project.d.ts +14 -0
- package/dist/migration-project.d.ts.map +1 -0
- package/dist/migration-project.js +74 -0
- package/dist/migration-project.js.map +1 -0
- package/dist/output.d.ts +27 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +60 -0
- package/dist/output.js.map +1 -0
- package/dist/repl.d.ts +48 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/repl.js +265 -0
- package/dist/repl.js.map +1 -0
- package/dist/scaffold.d.ts +28 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +414 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/studio/index.d.ts +20 -0
- package/dist/studio/index.d.ts.map +1 -0
- package/dist/studio/index.js +607 -0
- package/dist/studio/index.js.map +1 -0
- package/dist/templates/command.d.ts +3 -0
- package/dist/templates/command.d.ts.map +1 -0
- package/dist/templates/command.js +65 -0
- package/dist/templates/command.js.map +1 -0
- package/dist/templates/controller.d.ts +3 -0
- package/dist/templates/controller.d.ts.map +1 -0
- package/dist/templates/controller.js +41 -0
- package/dist/templates/controller.js.map +1 -0
- package/dist/templates/index.d.ts +4 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +18 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/module.d.ts +3 -0
- package/dist/templates/module.d.ts.map +1 -0
- package/dist/templates/module.js +41 -0
- package/dist/templates/module.js.map +1 -0
- package/dist/templates/project.d.ts +3 -0
- package/dist/templates/project.d.ts.map +1 -0
- package/dist/templates/project.js +280 -0
- package/dist/templates/project.js.map +1 -0
- package/dist/templates/repository.d.ts +3 -0
- package/dist/templates/repository.d.ts.map +1 -0
- package/dist/templates/repository.js +66 -0
- package/dist/templates/repository.js.map +1 -0
- package/dist/templates/schema.d.ts +3 -0
- package/dist/templates/schema.d.ts.map +1 -0
- package/dist/templates/schema.js +36 -0
- package/dist/templates/schema.js.map +1 -0
- package/dist/templates/types.d.ts +25 -0
- package/dist/templates/types.d.ts.map +1 -0
- package/dist/templates/types.js +17 -0
- package/dist/templates/types.js.map +1 -0
- package/package.json +72 -0
- package/src/__fixtures__/http-client/package.json +5 -0
- package/src/__fixtures__/http-client/src/contract.ts +85 -0
- package/src/__fixtures__/http-client/src/models.ts +12 -0
- package/src/__fixtures__/http-client/src/schema.ts +3 -0
- package/src/__fixtures__/http-client/src/unrelated.ts +1 -0
- package/src/__fixtures__/http-client/tsconfig.json +17 -0
- package/src/__fixtures__/http-client/zmdb.config.ts +12 -0
- package/src/__fixtures__/project/package.json +5 -0
- package/src/__fixtures__/project/src/schema.ts +6 -0
- package/src/__fixtures__/project/tsconfig.json +24 -0
- package/src/__fixtures__/project/zmdb.config.ts +57 -0
- package/src/application-loader.ts +108 -0
- package/src/args.ts +391 -0
- package/src/atomic.ts +43 -0
- package/src/bin.ts +5 -0
- package/src/commands/check.ts +11 -0
- package/src/commands/client.ts +415 -0
- package/src/commands/codegen.ts +73 -0
- package/src/commands/embed.ts +36 -0
- package/src/commands/export.ts +10 -0
- package/src/commands/generate.ts +14 -0
- package/src/commands/migrate.ts +38 -0
- package/src/commands/new.ts +48 -0
- package/src/commands/pull.ts +32 -0
- package/src/commands/push.ts +21 -0
- package/src/commands/studio.ts +200 -0
- package/src/commands/upgrade.ts +14 -0
- package/src/database.ts +9 -0
- package/src/errors.ts +19 -0
- package/src/index.ts +710 -0
- package/src/lifecycle.ts +73 -0
- package/src/migration-project.ts +91 -0
- package/src/output.ts +77 -0
- package/src/repl.ts +328 -0
- package/src/scaffold.ts +485 -0
- package/src/studio/index.ts +674 -0
- package/src/templates/command.ts +66 -0
- package/src/templates/controller.ts +42 -0
- package/src/templates/index.ts +29 -0
- package/src/templates/module.ts +42 -0
- package/src/templates/project.ts +281 -0
- package/src/templates/repository.ts +67 -0
- package/src/templates/schema.ts +37 -0
- package/src/templates/types.ts +46 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
// @zmdb/cli — argument handling for developer and schema commands.
|
|
2
|
+
//
|
|
3
|
+
// The executable is a build-time boundary: config loading, TypeScript
|
|
4
|
+
// reflection, esbuild and node:repl must not enter an application bundle.
|
|
5
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
6
|
+
if (value !== null && value !== void 0) {
|
|
7
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
8
|
+
var dispose, inner;
|
|
9
|
+
if (async) {
|
|
10
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.asyncDispose];
|
|
12
|
+
}
|
|
13
|
+
if (dispose === void 0) {
|
|
14
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
15
|
+
dispose = value[Symbol.dispose];
|
|
16
|
+
if (async) inner = dispose;
|
|
17
|
+
}
|
|
18
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
19
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
20
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
21
|
+
}
|
|
22
|
+
else if (async) {
|
|
23
|
+
env.stack.push({ async: true });
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
};
|
|
27
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
28
|
+
return function (env) {
|
|
29
|
+
function fail(e) {
|
|
30
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
31
|
+
env.hasError = true;
|
|
32
|
+
}
|
|
33
|
+
var r, s = 0;
|
|
34
|
+
function next() {
|
|
35
|
+
while (r = env.stack.pop()) {
|
|
36
|
+
try {
|
|
37
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
38
|
+
if (r.dispose) {
|
|
39
|
+
var result = r.dispose.call(r.value);
|
|
40
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
41
|
+
}
|
|
42
|
+
else s |= 1;
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
fail(e);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
49
|
+
if (env.hasError) throw env.error;
|
|
50
|
+
}
|
|
51
|
+
return next();
|
|
52
|
+
};
|
|
53
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
54
|
+
var e = new Error(message);
|
|
55
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
56
|
+
});
|
|
57
|
+
import { readFileSync } from 'node:fs';
|
|
58
|
+
import { createRequire } from 'node:module';
|
|
59
|
+
import { homedir } from 'node:os';
|
|
60
|
+
import { resolve } from 'node:path';
|
|
61
|
+
import { createInterface } from 'node:readline/promises';
|
|
62
|
+
import { fileURLToPath } from 'node:url';
|
|
63
|
+
import { loadRootModule, requireOptionalPeer } from './application-loader.js';
|
|
64
|
+
import { commandHelp, globalHelp, parseCommand } from './args.js';
|
|
65
|
+
import { CliInvocationError, errorMessage } from './errors.js';
|
|
66
|
+
import { withConfiguredDriver, withSignals } from './lifecycle.js';
|
|
67
|
+
import { CliOutput } from './output.js';
|
|
68
|
+
const requireCommand = createRequire(import.meta.url);
|
|
69
|
+
export async function embedMigrations(config, options = {}) {
|
|
70
|
+
const command = await import('./commands/embed.js');
|
|
71
|
+
return command.embedMigrations(config, options);
|
|
72
|
+
}
|
|
73
|
+
export function exportSchema(config) {
|
|
74
|
+
// boundary: Node require is untyped; this literal private module and the named
|
|
75
|
+
// function type above share the same source owner.
|
|
76
|
+
const command = requireCommand('./commands/export.js');
|
|
77
|
+
return command.exportSchema(config);
|
|
78
|
+
}
|
|
79
|
+
export async function generateMigration(config, options = {}) {
|
|
80
|
+
const command = await import('./commands/generate.js');
|
|
81
|
+
return command.generateMigration(config, options);
|
|
82
|
+
}
|
|
83
|
+
export async function pullDeclarations(config, options = {}) {
|
|
84
|
+
const command = await import('./commands/pull.js');
|
|
85
|
+
return withConfiguredDriver(config, scoped => command.pullDeclarations(scoped, options));
|
|
86
|
+
}
|
|
87
|
+
/** Programmatic generation stays on the same lazy boundary as the CLI command. */
|
|
88
|
+
export async function generateHttpArtifacts(config, options = {}) {
|
|
89
|
+
requireOptionalPeer('@zmdb/web');
|
|
90
|
+
const command = await import('./commands/client.js');
|
|
91
|
+
return command.generateHttpArtifacts(config, options);
|
|
92
|
+
}
|
|
93
|
+
/** Programmatic watch mode retains the same lazy build-time dependency boundary. */
|
|
94
|
+
export async function watchHttpArtifacts(config, options = {}) {
|
|
95
|
+
requireOptionalPeer('@zmdb/web');
|
|
96
|
+
const command = await import('./commands/client.js');
|
|
97
|
+
return command.watchHttpArtifacts(config, options);
|
|
98
|
+
}
|
|
99
|
+
const DEFAULT_MODULE_SPEC = './src/app.module.ts#AppModule';
|
|
100
|
+
const PACKAGE_VERSION = readPackageVersion();
|
|
101
|
+
/** Run the CLI against injectable streams, returning its process exit code. */
|
|
102
|
+
export async function runCli(argv, environment = {}) {
|
|
103
|
+
const io = runtimeEnvironment(environment);
|
|
104
|
+
const command = argv[0];
|
|
105
|
+
const globalConfig = resolve(io.cwd, 'zmdb.config.ts');
|
|
106
|
+
if (command === '--help' || command === '-h') {
|
|
107
|
+
return new CliOutput('help', globalConfig, argv.includes('--json'), io).help(globalHelp());
|
|
108
|
+
}
|
|
109
|
+
if (command === '--version') {
|
|
110
|
+
return new CliOutput('version', globalConfig, argv.includes('--json'), io).result({ version: PACKAGE_VERSION }, `zmdb ${PACKAGE_VERSION}\n`);
|
|
111
|
+
}
|
|
112
|
+
if (command === undefined) {
|
|
113
|
+
new CliOutput('zmdb', globalConfig, false, io).writeStderr(globalHelp());
|
|
114
|
+
return 2;
|
|
115
|
+
}
|
|
116
|
+
if (command === 'graph') {
|
|
117
|
+
new CliOutput('graph', globalConfig, false, io).writeStderr('zmdb: "graph" is ambiguous in a schema tool; use "zmdb modules"\n');
|
|
118
|
+
return 2;
|
|
119
|
+
}
|
|
120
|
+
const parsedResult = parseCommand(command, argv.slice(1), io.cwd);
|
|
121
|
+
if ('error' in parsedResult) {
|
|
122
|
+
if (command === 'studio' && !parsedResult.json) {
|
|
123
|
+
io.stderr(`zmdb: ${parsedResult.error}\n`);
|
|
124
|
+
return 2;
|
|
125
|
+
}
|
|
126
|
+
return new CliOutput(command, parsedResult.config, parsedResult.json, io).failure(parsedResult.error, 2);
|
|
127
|
+
}
|
|
128
|
+
const parsed = parsedResult.parsed;
|
|
129
|
+
const output = new CliOutput(command, parsed.config, parsed.json, io);
|
|
130
|
+
if (parsed.help)
|
|
131
|
+
return output.help(commandHelp(command));
|
|
132
|
+
if (parsed.version) {
|
|
133
|
+
return output.result({ version: PACKAGE_VERSION }, `zmdb ${PACKAGE_VERSION}\n`);
|
|
134
|
+
}
|
|
135
|
+
if (command === 'up') {
|
|
136
|
+
return output.failure('`up` is not a command; use `migrate` to apply migrations or `upgrade` to rewrite a stored snapshot', 2);
|
|
137
|
+
}
|
|
138
|
+
if (command === 'rollback') {
|
|
139
|
+
try {
|
|
140
|
+
rollbackTarget(parsed.values.to);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
return output.failure(errorMessage(error), 2);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (['modules', 'repl', 'studio', 'client'].includes(command)) {
|
|
147
|
+
try {
|
|
148
|
+
requireOptionalPeer('@zmdb/web');
|
|
149
|
+
if (command === 'modules' || command === 'repl')
|
|
150
|
+
requireOptionalPeer('@zmdb/app');
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
return output.failure(errorMessage(error), error instanceof CliInvocationError ? 2 : 1);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (command === 'codegen') {
|
|
157
|
+
const { runCodegen } = await import('./commands/codegen.js');
|
|
158
|
+
return runCodegen(parsed, io);
|
|
159
|
+
}
|
|
160
|
+
if (command === 'new') {
|
|
161
|
+
const { createNewScaffold } = await import('./commands/new.js');
|
|
162
|
+
return createNewScaffold(parsed, output, io.cwd);
|
|
163
|
+
}
|
|
164
|
+
if (command === 'studio')
|
|
165
|
+
return runStudioCommand(parsed, io);
|
|
166
|
+
if (command === 'modules')
|
|
167
|
+
return runModules(parsed, io);
|
|
168
|
+
if (command === 'repl')
|
|
169
|
+
return runRepl(parsed, io);
|
|
170
|
+
if (command === 'client')
|
|
171
|
+
return runClientCommand(parsed, io);
|
|
172
|
+
return runDatabaseCommand(parsed, io);
|
|
173
|
+
}
|
|
174
|
+
async function runClientCommand(parsed, io) {
|
|
175
|
+
const pendingOutput = new CliOutput('client generate', parsed.config, parsed.json, io);
|
|
176
|
+
if (parsed.positionals[0] !== 'generate') {
|
|
177
|
+
return pendingOutput.failure('expected the subcommand `generate`', 2);
|
|
178
|
+
}
|
|
179
|
+
if (parsed.values.check === true && parsed.values.watch === true) {
|
|
180
|
+
return pendingOutput.failure('--check and --watch ask for opposite things', 2);
|
|
181
|
+
}
|
|
182
|
+
if (parsed.json && parsed.values.watch === true) {
|
|
183
|
+
return pendingOutput.failure('--json is unavailable because a watch session is not one JSON document', 2);
|
|
184
|
+
}
|
|
185
|
+
let config;
|
|
186
|
+
try {
|
|
187
|
+
config = await loadCommandConfig(parsed, io.cwd);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
return pendingOutput.failure(errorMessage(error), 2, parsed.config);
|
|
191
|
+
}
|
|
192
|
+
const output = pendingOutput.withConfig(config.configPath);
|
|
193
|
+
try {
|
|
194
|
+
const command = await import('./commands/client.js');
|
|
195
|
+
if (parsed.values.watch === true) {
|
|
196
|
+
await withSignals(until => command.watchHttpArtifacts(config, {
|
|
197
|
+
until,
|
|
198
|
+
log: generation => {
|
|
199
|
+
output.progress(renderClientGeneration(config.configPath, generation));
|
|
200
|
+
},
|
|
201
|
+
}));
|
|
202
|
+
return 0;
|
|
203
|
+
}
|
|
204
|
+
const check = parsed.values.check === true;
|
|
205
|
+
const generation = await command.generateHttpArtifacts(config, check ? { check: true } : {});
|
|
206
|
+
const exitCode = parsed.values.check === true && generation.stale.length > 0 ? 1 : 0;
|
|
207
|
+
return output.result(generation.result, renderClientGeneration(config.configPath, generation, check), exitCode);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
return output.failure(errorMessage(error), error instanceof CliInvocationError ? 2 : 1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
async function runStudioCommand(parsed, io) {
|
|
214
|
+
const pendingOutput = new CliOutput('studio', parsed.config, parsed.json, io);
|
|
215
|
+
if (parsed.json) {
|
|
216
|
+
return pendingOutput.failure('--json is unavailable because a studio session is not one JSON document', 2);
|
|
217
|
+
}
|
|
218
|
+
const portValue = parsed.values.port;
|
|
219
|
+
const port = portValue === undefined
|
|
220
|
+
? 0
|
|
221
|
+
: typeof portValue === 'string' && /^(?:0|[1-9]\d*)$/.test(portValue)
|
|
222
|
+
? Number(portValue)
|
|
223
|
+
: Number.NaN;
|
|
224
|
+
if (!Number.isInteger(port) || port < 0 || port > 65_535) {
|
|
225
|
+
return pendingOutput.failure(`--port must be an integer from 0 through 65535, received "${String(portValue)}"`, 2);
|
|
226
|
+
}
|
|
227
|
+
let config;
|
|
228
|
+
try {
|
|
229
|
+
config = await loadCommandConfig(parsed, io.cwd);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
return pendingOutput.failure(errorMessage(error), 2, parsed.config);
|
|
233
|
+
}
|
|
234
|
+
const output = pendingOutput.withConfig(config.configPath);
|
|
235
|
+
if (config.driver === undefined) {
|
|
236
|
+
return output.failure('the config must declare a driver thunk before studio can connect', 2);
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
const { schemasFromFiles } = await import('@zmdb/compiler/testing');
|
|
240
|
+
const schemas = schemasFromFiles(config.schemaFiles, {
|
|
241
|
+
project: config.project,
|
|
242
|
+
naming: config.resolvedNaming,
|
|
243
|
+
});
|
|
244
|
+
return await withConfiguredDriver(config, async (scoped) => {
|
|
245
|
+
if (scoped.driver === undefined)
|
|
246
|
+
throw new CliInvocationError('studio needs a driver');
|
|
247
|
+
const [driver, { runStudio }] = await Promise.all([scoped.driver(), import('./commands/studio.js')]);
|
|
248
|
+
return runStudio({ schemas, driver, dialect: config.dialect }, {
|
|
249
|
+
port,
|
|
250
|
+
stdout: text => output.writeStdout(text),
|
|
251
|
+
stderr: text => output.writeStderr(text),
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
return output.failure(errorMessage(error), 1);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async function runDatabaseCommand(parsed, io) {
|
|
260
|
+
const pendingOutput = new CliOutput(parsed.command, parsed.config, parsed.json, io);
|
|
261
|
+
let config;
|
|
262
|
+
try {
|
|
263
|
+
config = await loadCommandConfig(parsed, io.cwd);
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
return pendingOutput.failure(errorMessage(error), 2, parsed.config);
|
|
267
|
+
}
|
|
268
|
+
const output = pendingOutput.withConfig(config.configPath);
|
|
269
|
+
try {
|
|
270
|
+
const publish = await withConfiguredDriver(config, async (scopedConfig) => {
|
|
271
|
+
if (parsed.command === 'embed') {
|
|
272
|
+
const out = typeof parsed.values.out === 'string' ? parsed.values.out : undefined;
|
|
273
|
+
const result = await embedMigrations(scopedConfig, {
|
|
274
|
+
...(out === undefined ? {} : { out }),
|
|
275
|
+
...(parsed.values['with-down'] === true ? { withDown: true } : {}),
|
|
276
|
+
});
|
|
277
|
+
return () => output.result(result, `${scopedConfig.configPath}\nwrote ${result.file} (${String(result.migrations.length)} migrations)\n`);
|
|
278
|
+
}
|
|
279
|
+
if (parsed.command === 'generate') {
|
|
280
|
+
const name = typeof parsed.values.name === 'string' ? parsed.values.name : undefined;
|
|
281
|
+
if (name !== undefined && !/[a-z0-9]/i.test(name)) {
|
|
282
|
+
return () => output.failure(`migration name ${JSON.stringify(name)} has no letters or digits`, 2);
|
|
283
|
+
}
|
|
284
|
+
const result = await generateMigration(scopedConfig, name === undefined ? {} : { name });
|
|
285
|
+
const human = 'file' in result
|
|
286
|
+
? `${scopedConfig.configPath}\nwrote ${result.file} (${String(result.ops.length)} operations)\n`
|
|
287
|
+
: `${scopedConfig.configPath}\nno changes; no migration written\n`;
|
|
288
|
+
return () => output.result(result, human);
|
|
289
|
+
}
|
|
290
|
+
if (parsed.command === 'export') {
|
|
291
|
+
const result = (await import('./commands/export.js')).exportSchema(scopedConfig);
|
|
292
|
+
const sql = result.statements.length === 0 ? '' : `${result.statements.join(';\n')};\n`;
|
|
293
|
+
return () => output.result(result, `-- zmdb config: ${scopedConfig.configPath}\n${sql}`);
|
|
294
|
+
}
|
|
295
|
+
if (parsed.command === 'migrate') {
|
|
296
|
+
output.progress(`${scopedConfig.configPath}\n`);
|
|
297
|
+
const result = await (await import('./commands/migrate.js')).migrate(scopedConfig, { progress: text => output.progress(text) });
|
|
298
|
+
return () => output.result(result, result.applied.length === 0
|
|
299
|
+
? 'nothing to apply; 0 pending migrations\n'
|
|
300
|
+
: `applied ${result.applied.map(item => String(item.version)).join(', ')}\n`);
|
|
301
|
+
}
|
|
302
|
+
if (parsed.command === 'rollback') {
|
|
303
|
+
output.progress(`${scopedConfig.configPath}\n`);
|
|
304
|
+
const target = rollbackTarget(parsed.values.to);
|
|
305
|
+
const result = await (await import('./commands/migrate.js')).rollback(scopedConfig, target, { progress: text => output.progress(text) });
|
|
306
|
+
return () => output.result(result, result.versions.length === 0
|
|
307
|
+
? 'nothing to roll back\n'
|
|
308
|
+
: `reverted ${result.versions.map(item => String(item.version)).join(', ')}\n`);
|
|
309
|
+
}
|
|
310
|
+
if (parsed.command === 'status') {
|
|
311
|
+
output.progress(`${scopedConfig.configPath}\n`);
|
|
312
|
+
const result = await (await import('./commands/migrate.js')).migrationStatus(scopedConfig);
|
|
313
|
+
const human = result.migrations
|
|
314
|
+
.map(item => `${item.applied ? '[x]' : '[ ]'} ${String(item.version)} ${item.name}`)
|
|
315
|
+
.join('\n');
|
|
316
|
+
return () => output.result(result, human.length === 0 ? 'no migrations\n' : `${human}\n`);
|
|
317
|
+
}
|
|
318
|
+
if (parsed.command === 'push') {
|
|
319
|
+
output.progress(`${scopedConfig.configPath}\n`);
|
|
320
|
+
const plan = await (await import('./commands/push.js')).planPush(scopedConfig);
|
|
321
|
+
for (const statement of plan.statements)
|
|
322
|
+
output.progress(`${statement};\n`);
|
|
323
|
+
if (plan.destructive.length > 0 && parsed.values.force !== true) {
|
|
324
|
+
return () => output.failure(`--force is required for destructive SQL:\n${plan.destructive.join(';\n')};`, 2);
|
|
325
|
+
}
|
|
326
|
+
if (plan.destructive.length > 0 && parsed.values.yes !== true && (parsed.json || !io.stdinIsTTY)) {
|
|
327
|
+
return () => output.failure('--yes is required for a destructive push when no TTY prompt is available', 2);
|
|
328
|
+
}
|
|
329
|
+
if (plan.destructive.length > 0 &&
|
|
330
|
+
parsed.values.yes !== true &&
|
|
331
|
+
!(await confirmPush(io, plan.destructive.length))) {
|
|
332
|
+
return () => output.failure('push cancelled before executing SQL', 1);
|
|
333
|
+
}
|
|
334
|
+
const result = await (await import('./commands/push.js')).applyPush(plan, warning => output.progress(`warning: ${warning}\n`));
|
|
335
|
+
return () => output.result(result, result.applied ? `applied ${String(result.statements.length)} statements\n` : 'no changes\n');
|
|
336
|
+
}
|
|
337
|
+
if (parsed.command === 'check') {
|
|
338
|
+
output.progress(`${scopedConfig.configPath}\n`);
|
|
339
|
+
const result = await (await import('./commands/check.js')).checkProject(scopedConfig);
|
|
340
|
+
const findings = result.findings.map(finding => `${finding.kind}: ${finding.message} (${finding.subject})`);
|
|
341
|
+
const skipped = result.skipped.map(item => `skipped ${item.kind}: ${item.reason}`);
|
|
342
|
+
const human = [...findings, ...skipped];
|
|
343
|
+
return () => output.result(result, `${human.join('\n') || 'check passed'}\n`, result.findings.length === 0 ? 0 : 1);
|
|
344
|
+
}
|
|
345
|
+
if (parsed.command === 'upgrade') {
|
|
346
|
+
output.progress(`${scopedConfig.configPath}\n`);
|
|
347
|
+
const result = await (await import('./commands/upgrade.js')).upgradeSnapshot(scopedConfig);
|
|
348
|
+
return () => output.result(result, result.changed
|
|
349
|
+
? `upgraded snapshot ${String(result.from)} -> ${String(result.to)}; backup ${result.backup ?? ''}\n`
|
|
350
|
+
: `snapshot is already at version ${String(result.to)}\n`);
|
|
351
|
+
}
|
|
352
|
+
if (parsed.command === 'pull') {
|
|
353
|
+
if (scopedConfig.driver === undefined) {
|
|
354
|
+
return () => output.failure('the config must declare a driver thunk before pull can connect', 2);
|
|
355
|
+
}
|
|
356
|
+
const execution = await (await import('./commands/pull.js')).pullDeclarations(scopedConfig, {
|
|
357
|
+
...(parsed.values['dry-run'] === true ? { dryRun: true } : {}),
|
|
358
|
+
...(parsed.values.check === true ? { check: true } : {}),
|
|
359
|
+
});
|
|
360
|
+
if (parsed.json) {
|
|
361
|
+
for (const warning of execution.warnings)
|
|
362
|
+
output.writeStderr(`${formatPullWarning(warning)}\n`);
|
|
363
|
+
}
|
|
364
|
+
return () => output.result(execution.result, renderPull(execution, scopedConfig.configPath), execution.exitCode);
|
|
365
|
+
}
|
|
366
|
+
return () => output.failure(`command "${parsed.command}" is not implemented`, 2);
|
|
367
|
+
});
|
|
368
|
+
return publish();
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
return output.failure(errorMessage(error), error instanceof CliInvocationError ? 2 : 1);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
function rollbackTarget(value) {
|
|
375
|
+
if (value === undefined)
|
|
376
|
+
return undefined;
|
|
377
|
+
if (typeof value !== 'string' || !/^\d+$/.test(value)) {
|
|
378
|
+
throw new CliInvocationError(`--to needs a decimal migration version, received "${String(value)}"`);
|
|
379
|
+
}
|
|
380
|
+
const version = Number(value);
|
|
381
|
+
if (!Number.isSafeInteger(version)) {
|
|
382
|
+
throw new CliInvocationError(`--to migration version ${value} is not a safe integer`);
|
|
383
|
+
}
|
|
384
|
+
return version;
|
|
385
|
+
}
|
|
386
|
+
async function confirmPush(io, destructiveCount) {
|
|
387
|
+
const prompt = createInterface({ input: io.input, output: io.output, terminal: true });
|
|
388
|
+
try {
|
|
389
|
+
const answer = await prompt.question(`Apply ${String(destructiveCount)} destructive statement${destructiveCount === 1 ? '' : 's'}? [y/N] `);
|
|
390
|
+
return /^y(?:es)?$/i.test(answer.trim());
|
|
391
|
+
}
|
|
392
|
+
finally {
|
|
393
|
+
prompt.close();
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
async function loadCommandConfig(parsed, cwd) {
|
|
397
|
+
const { loadConfig, resolveConfig } = await import('@zmdb/compiler/config');
|
|
398
|
+
const explicit = typeof parsed.values.config === 'string' ? parsed.values.config : undefined;
|
|
399
|
+
const loaded = await loadConfig({
|
|
400
|
+
cwd,
|
|
401
|
+
...(explicit === undefined ? {} : { path: explicit }),
|
|
402
|
+
});
|
|
403
|
+
if (parsed.project === undefined)
|
|
404
|
+
return loaded;
|
|
405
|
+
return resolveConfig(authorConfig(loaded, resolve(cwd, parsed.project)), loaded.configPath);
|
|
406
|
+
}
|
|
407
|
+
function authorConfig(config, project) {
|
|
408
|
+
return {
|
|
409
|
+
schema: config.schema,
|
|
410
|
+
dialect: config.dialect,
|
|
411
|
+
project,
|
|
412
|
+
out: config.out,
|
|
413
|
+
...(config.naming === undefined ? {} : { naming: config.naming }),
|
|
414
|
+
...(config.migrations === undefined ? {} : { migrations: config.migrations }),
|
|
415
|
+
...(config.introspect === undefined ? {} : { introspect: config.introspect }),
|
|
416
|
+
...(config.http === undefined
|
|
417
|
+
? {}
|
|
418
|
+
: {
|
|
419
|
+
http: {
|
|
420
|
+
contracts: config.http.contracts.map(contract => `${contract.file}#${contract.exportName}`),
|
|
421
|
+
openApi: { out: config.http.openApiOut },
|
|
422
|
+
client: { out: config.http.clientOut },
|
|
423
|
+
},
|
|
424
|
+
}),
|
|
425
|
+
...(config.driver === undefined ? {} : { driver: config.driver }),
|
|
426
|
+
...(config.namingStrategy === undefined ? {} : { namingStrategy: config.namingStrategy }),
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
function renderClientGeneration(configPath, generation, check = false) {
|
|
430
|
+
if (!generation.result.changed)
|
|
431
|
+
return `${configPath}\nHTTP client artifacts are current\n`;
|
|
432
|
+
const lines = [configPath];
|
|
433
|
+
for (const path of generation.stale)
|
|
434
|
+
lines.push(`${check ? 'stale' : 'generated'} ${path}`);
|
|
435
|
+
return `${lines.join('\n')}\n`;
|
|
436
|
+
}
|
|
437
|
+
async function runModules(parsed, io) {
|
|
438
|
+
const output = new CliOutput('modules', parsed.config, parsed.json, io);
|
|
439
|
+
const options = parseModules(parsed, io.cwd);
|
|
440
|
+
if ('error' in options)
|
|
441
|
+
return output.failure(options.error, 2);
|
|
442
|
+
if (parsed.json && options.formatWasNamed) {
|
|
443
|
+
return output.failure('--json and --format ask for opposite output shapes', 2);
|
|
444
|
+
}
|
|
445
|
+
try {
|
|
446
|
+
const root = await loadRootModule(options.moduleSpec, io.cwd);
|
|
447
|
+
const { describeGraph, renderDot, renderTree } = await import('@zmdb/web/devtools');
|
|
448
|
+
const graph = describeGraph(root);
|
|
449
|
+
const exitCode = graph.findings.some(finding => finding.severity === 'error') ? 1 : 0;
|
|
450
|
+
if (parsed.json)
|
|
451
|
+
return output.result(graph, '', exitCode);
|
|
452
|
+
let rendered;
|
|
453
|
+
try {
|
|
454
|
+
rendered = options.format === 'dot' ? renderDot(graph, options.filter) : renderTree(graph, options.filter);
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
return output.failure(errorMessage(error), 2);
|
|
458
|
+
}
|
|
459
|
+
if (options.format === 'dot') {
|
|
460
|
+
for (const finding of graph.findings) {
|
|
461
|
+
output.writeStderr(`${finding.severity}: ${finding.kind}: ${finding.message}\n`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return output.result(graph, rendered, exitCode);
|
|
465
|
+
}
|
|
466
|
+
catch (error) {
|
|
467
|
+
return output.failure(errorMessage(error), error instanceof CliInvocationError ? 2 : 1);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
function parseModules(parsed, cwd) {
|
|
471
|
+
const moduleSpec = parsed.positionals[0];
|
|
472
|
+
if (moduleSpec === undefined && isWorkspaceRoot(cwd)) {
|
|
473
|
+
return {
|
|
474
|
+
error: `a workspace root must name the application as <path>#<export>; the default is ${DEFAULT_MODULE_SPEC}`,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
const namedFormat = parsed.values.format;
|
|
478
|
+
if (namedFormat !== undefined && namedFormat !== 'tree' && namedFormat !== 'dot') {
|
|
479
|
+
return { error: `--format must be tree or dot, received "${String(namedFormat)}"` };
|
|
480
|
+
}
|
|
481
|
+
const depthValue = parsed.values.depth;
|
|
482
|
+
const depth = typeof depthValue === 'string' ? Number(depthValue) : undefined;
|
|
483
|
+
if (depth !== undefined && (!Number.isInteger(depth) || depth < 0)) {
|
|
484
|
+
return { error: `--depth needs a non-negative integer, received "${String(depthValue)}"` };
|
|
485
|
+
}
|
|
486
|
+
const moduleName = typeof parsed.values.module === 'string' ? parsed.values.module : undefined;
|
|
487
|
+
const token = typeof parsed.values.token === 'string' ? parsed.values.token : undefined;
|
|
488
|
+
const filter = {
|
|
489
|
+
...(parsed.values.providers === true ? { providers: true } : {}),
|
|
490
|
+
...(moduleName === undefined ? {} : { module: moduleName }),
|
|
491
|
+
...(token === undefined ? {} : { token }),
|
|
492
|
+
...(depth === undefined ? {} : { depth }),
|
|
493
|
+
};
|
|
494
|
+
return {
|
|
495
|
+
moduleSpec: moduleSpec ?? DEFAULT_MODULE_SPEC,
|
|
496
|
+
format: namedFormat === 'dot' ? 'dot' : 'tree',
|
|
497
|
+
formatWasNamed: namedFormat !== undefined,
|
|
498
|
+
filter,
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
async function runRepl(parsed, io) {
|
|
502
|
+
const output = new CliOutput('repl', parsed.config, parsed.json, io);
|
|
503
|
+
if (parsed.json) {
|
|
504
|
+
return output.failure('--json is unavailable because an interactive session is not one JSON document', 2);
|
|
505
|
+
}
|
|
506
|
+
if (!io.stdinIsTTY) {
|
|
507
|
+
return output.failure('stdin must be a TTY; piped or network-controlled input is refused', 2);
|
|
508
|
+
}
|
|
509
|
+
const options = parseRepl(parsed, io.cwd);
|
|
510
|
+
if ('error' in options)
|
|
511
|
+
return output.failure(options.error, 2);
|
|
512
|
+
let root;
|
|
513
|
+
try {
|
|
514
|
+
root = await loadRootModule(options.moduleSpec, io.cwd);
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
return output.failure(errorMessage(error), error instanceof CliInvocationError ? 2 : 1);
|
|
518
|
+
}
|
|
519
|
+
try {
|
|
520
|
+
const { createReplSession, replHistoryPath } = await import('./repl.js');
|
|
521
|
+
await withSignals(async (until) => {
|
|
522
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
523
|
+
try {
|
|
524
|
+
const session = __addDisposableResource(env_1, await createReplSession(root, {
|
|
525
|
+
configPath: parsed.config,
|
|
526
|
+
moduleSpec: options.moduleSpec,
|
|
527
|
+
cwd: io.cwd,
|
|
528
|
+
input: io.input,
|
|
529
|
+
output: io.output,
|
|
530
|
+
stderr: text => output.writeStderr(text),
|
|
531
|
+
historyPath: options.history ? replHistoryPath(io.environment, io.homeDirectory) : null,
|
|
532
|
+
terminal: io.stdinIsTTY && streamIsTTY(io.output),
|
|
533
|
+
}), true);
|
|
534
|
+
await Promise.race([session.closed, until]);
|
|
535
|
+
}
|
|
536
|
+
catch (e_1) {
|
|
537
|
+
env_1.error = e_1;
|
|
538
|
+
env_1.hasError = true;
|
|
539
|
+
}
|
|
540
|
+
finally {
|
|
541
|
+
const result_1 = __disposeResources(env_1);
|
|
542
|
+
if (result_1)
|
|
543
|
+
await result_1;
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
return 0;
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
return output.failure(errorMessage(error), 1);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
function parseRepl(parsed, cwd) {
|
|
553
|
+
const moduleSpec = parsed.positionals[0];
|
|
554
|
+
if (moduleSpec === undefined && isWorkspaceRoot(cwd)) {
|
|
555
|
+
return {
|
|
556
|
+
error: `a workspace root must name the application as <path>#<export>; the default is ${DEFAULT_MODULE_SPEC}`,
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
moduleSpec: moduleSpec ?? DEFAULT_MODULE_SPEC,
|
|
561
|
+
history: parsed.values.history !== false,
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function runtimeEnvironment(environment) {
|
|
565
|
+
const output = environment.output ?? process.stdout;
|
|
566
|
+
return {
|
|
567
|
+
cwd: environment.cwd ?? process.cwd(),
|
|
568
|
+
stdinIsTTY: environment.stdinIsTTY ?? process.stdin.isTTY === true,
|
|
569
|
+
input: environment.input ?? process.stdin,
|
|
570
|
+
output,
|
|
571
|
+
stdout: environment.stdout ?? (text => output.write(text)),
|
|
572
|
+
stderr: environment.stderr ?? (text => process.stderr.write(text)),
|
|
573
|
+
environment: environment.environment ?? process.env,
|
|
574
|
+
homeDirectory: environment.homeDirectory ?? homedir(),
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
function streamIsTTY(stream) {
|
|
578
|
+
return 'isTTY' in stream && stream.isTTY === true;
|
|
579
|
+
}
|
|
580
|
+
function isWorkspaceRoot(cwd) {
|
|
581
|
+
try {
|
|
582
|
+
const manifest = JSON.parse(readFileSync(resolve(cwd, 'package.json'), 'utf8'));
|
|
583
|
+
if (typeof manifest !== 'object' || manifest === null)
|
|
584
|
+
return false;
|
|
585
|
+
const workspaces = Reflect.get(manifest, 'workspaces');
|
|
586
|
+
return Array.isArray(workspaces) || (typeof workspaces === 'object' && workspaces !== null);
|
|
587
|
+
}
|
|
588
|
+
catch {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
function readPackageVersion() {
|
|
593
|
+
const manifest = JSON.parse(readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8'));
|
|
594
|
+
if (typeof manifest !== 'object' || manifest === null)
|
|
595
|
+
return 'unknown';
|
|
596
|
+
const version = Reflect.get(manifest, 'version');
|
|
597
|
+
return typeof version === 'string' ? version : 'unknown';
|
|
598
|
+
}
|
|
599
|
+
function renderPull(execution, configPath) {
|
|
600
|
+
const lines = [configPath];
|
|
601
|
+
for (const warning of execution.warnings)
|
|
602
|
+
lines.push(formatPullWarning(warning));
|
|
603
|
+
const skipped = new Map(execution.result.skipped.map(file => [file.path, file.reason]));
|
|
604
|
+
for (const output of execution.outputs) {
|
|
605
|
+
const reason = skipped.get(output.path);
|
|
606
|
+
if (reason !== undefined) {
|
|
607
|
+
lines.push(`${execution.mode === 'check' ? 'drift' : 'skipped'} ${output.path}: ${reason}`);
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
if (execution.mode === 'dry-run') {
|
|
611
|
+
lines.push(`would write ${output.path}`, output.source.trimEnd());
|
|
612
|
+
}
|
|
613
|
+
else if (execution.mode === 'check') {
|
|
614
|
+
lines.push(`current ${output.path}`);
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
lines.push(`wrote ${output.path}`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
return `${lines.join('\n')}\n`;
|
|
621
|
+
}
|
|
622
|
+
function formatPullWarning(warning) {
|
|
623
|
+
const subject = warning.column === undefined ? warning.table : `${warning.table}.${warning.column}`;
|
|
624
|
+
return `WARNING ${subject}: ${warning.reason}`;
|
|
625
|
+
}
|
|
626
|
+
//# sourceMappingURL=index.js.map
|