neonctl 2.37.0 → 2.38.0

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 (160) hide show
  1. package/{LICENSE.md → LICENSE} +27 -3
  2. package/README.md +15 -700
  3. package/bin/cli.js +3 -0
  4. package/package.json +8 -75
  5. package/dist/analytics.js +0 -168
  6. package/dist/api.js +0 -720
  7. package/dist/auth.js +0 -125
  8. package/dist/callback.html +0 -51
  9. package/dist/cli.js +0 -9
  10. package/dist/commands/api.js +0 -278
  11. package/dist/commands/auth.js +0 -214
  12. package/dist/commands/bootstrap.js +0 -481
  13. package/dist/commands/branches.js +0 -488
  14. package/dist/commands/bucket.js +0 -549
  15. package/dist/commands/checkout.js +0 -321
  16. package/dist/commands/config.js +0 -626
  17. package/dist/commands/connection_string.js +0 -172
  18. package/dist/commands/data_api.js +0 -284
  19. package/dist/commands/databases.js +0 -82
  20. package/dist/commands/deploy.js +0 -26
  21. package/dist/commands/dev.js +0 -698
  22. package/dist/commands/diff.js +0 -222
  23. package/dist/commands/env.js +0 -189
  24. package/dist/commands/functions.js +0 -373
  25. package/dist/commands/index.js +0 -62
  26. package/dist/commands/init.js +0 -73
  27. package/dist/commands/inspect.js +0 -65
  28. package/dist/commands/ip_allow.js +0 -137
  29. package/dist/commands/link.js +0 -1121
  30. package/dist/commands/neon_auth.js +0 -1028
  31. package/dist/commands/operations.js +0 -28
  32. package/dist/commands/orgs.js +0 -24
  33. package/dist/commands/projects.js +0 -413
  34. package/dist/commands/psql.js +0 -62
  35. package/dist/commands/roles.js +0 -65
  36. package/dist/commands/schema_diff.js +0 -151
  37. package/dist/commands/set_context.js +0 -29
  38. package/dist/commands/snapshots.js +0 -455
  39. package/dist/commands/status.js +0 -40
  40. package/dist/commands/user.js +0 -15
  41. package/dist/commands/vpc_endpoints.js +0 -134
  42. package/dist/config.js +0 -11
  43. package/dist/config_format.js +0 -72
  44. package/dist/context.js +0 -231
  45. package/dist/current_branch_fast_path.js +0 -55
  46. package/dist/dev/env.js +0 -244
  47. package/dist/dev/functions.js +0 -70
  48. package/dist/dev/inputs.js +0 -63
  49. package/dist/dev/runtime.js +0 -146
  50. package/dist/env.js +0 -36
  51. package/dist/env_file.js +0 -159
  52. package/dist/errors.js +0 -80
  53. package/dist/functions_api.js +0 -48
  54. package/dist/help.js +0 -146
  55. package/dist/index.js +0 -240
  56. package/dist/log.js +0 -18
  57. package/dist/parameters.gen.js +0 -480
  58. package/dist/pkg.js +0 -25
  59. package/dist/psql/cli.js +0 -53
  60. package/dist/psql/command/cmd_cond.js +0 -437
  61. package/dist/psql/command/cmd_connect.js +0 -820
  62. package/dist/psql/command/cmd_copy.js +0 -1035
  63. package/dist/psql/command/cmd_describe.js +0 -1815
  64. package/dist/psql/command/cmd_format.js +0 -948
  65. package/dist/psql/command/cmd_io.js +0 -2193
  66. package/dist/psql/command/cmd_lo.js +0 -393
  67. package/dist/psql/command/cmd_meta.js +0 -969
  68. package/dist/psql/command/cmd_misc.js +0 -187
  69. package/dist/psql/command/cmd_pipeline.js +0 -1148
  70. package/dist/psql/command/cmd_restrict.js +0 -171
  71. package/dist/psql/command/cmd_show.js +0 -766
  72. package/dist/psql/command/dispatch.js +0 -343
  73. package/dist/psql/command/inputQueue.js +0 -42
  74. package/dist/psql/command/shared.js +0 -71
  75. package/dist/psql/complete/filenames.js +0 -139
  76. package/dist/psql/complete/index.js +0 -104
  77. package/dist/psql/complete/matcher.js +0 -315
  78. package/dist/psql/complete/psqlVars.js +0 -249
  79. package/dist/psql/complete/queries.js +0 -493
  80. package/dist/psql/complete/rules.js +0 -2424
  81. package/dist/psql/core/common.js +0 -1253
  82. package/dist/psql/core/help.js +0 -576
  83. package/dist/psql/core/mainloop.js +0 -1360
  84. package/dist/psql/core/prompt.js +0 -439
  85. package/dist/psql/core/settings.js +0 -686
  86. package/dist/psql/core/sqlHelp.js +0 -1066
  87. package/dist/psql/core/startup.js +0 -846
  88. package/dist/psql/core/syncVars.js +0 -116
  89. package/dist/psql/core/variables.js +0 -287
  90. package/dist/psql/describe/formatters.js +0 -1330
  91. package/dist/psql/describe/processNamePattern.js +0 -270
  92. package/dist/psql/describe/queries.js +0 -2452
  93. package/dist/psql/describe/versionGate.js +0 -44
  94. package/dist/psql/index.js +0 -2030
  95. package/dist/psql/io/history.js +0 -299
  96. package/dist/psql/io/input.js +0 -120
  97. package/dist/psql/io/lineEditor/buffer.js +0 -325
  98. package/dist/psql/io/lineEditor/complete.js +0 -227
  99. package/dist/psql/io/lineEditor/filename.js +0 -159
  100. package/dist/psql/io/lineEditor/index.js +0 -893
  101. package/dist/psql/io/lineEditor/keymap.js +0 -745
  102. package/dist/psql/io/lineEditor/vt100.js +0 -363
  103. package/dist/psql/io/pgpass.js +0 -202
  104. package/dist/psql/io/pgservice.js +0 -194
  105. package/dist/psql/io/psqlrc.js +0 -422
  106. package/dist/psql/print/aligned.js +0 -1748
  107. package/dist/psql/print/asciidoc.js +0 -230
  108. package/dist/psql/print/crosstab.js +0 -463
  109. package/dist/psql/print/csv.js +0 -76
  110. package/dist/psql/print/html.js +0 -240
  111. package/dist/psql/print/json.js +0 -96
  112. package/dist/psql/print/latex.js +0 -379
  113. package/dist/psql/print/pager.js +0 -267
  114. package/dist/psql/print/troff.js +0 -240
  115. package/dist/psql/print/unaligned.js +0 -99
  116. package/dist/psql/print/units.js +0 -188
  117. package/dist/psql/scanner/slash.js +0 -515
  118. package/dist/psql/scanner/sql.js +0 -914
  119. package/dist/psql/scanner/stringutils.js +0 -394
  120. package/dist/psql/types/backslash.js +0 -1
  121. package/dist/psql/types/connection.js +0 -1
  122. package/dist/psql/types/index.js +0 -7
  123. package/dist/psql/types/printer.js +0 -1
  124. package/dist/psql/types/repl.js +0 -1
  125. package/dist/psql/types/scanner.js +0 -24
  126. package/dist/psql/types/settings.js +0 -1
  127. package/dist/psql/types/variables.js +0 -1
  128. package/dist/psql/wire/connection.js +0 -2857
  129. package/dist/psql/wire/copy.js +0 -108
  130. package/dist/psql/wire/notify.js +0 -59
  131. package/dist/psql/wire/pipeline.js +0 -521
  132. package/dist/psql/wire/protocol.js +0 -466
  133. package/dist/psql/wire/sasl.js +0 -294
  134. package/dist/psql/wire/tls.js +0 -602
  135. package/dist/storage_api.js +0 -147
  136. package/dist/test_utils/fixtures.js +0 -121
  137. package/dist/test_utils/oauth_server.js +0 -9
  138. package/dist/types.js +0 -1
  139. package/dist/utils/ai_gateway_notice.js +0 -180
  140. package/dist/utils/api_enums.js +0 -33
  141. package/dist/utils/auth.js +0 -5
  142. package/dist/utils/branch_notice.js +0 -22
  143. package/dist/utils/branch_picker.js +0 -103
  144. package/dist/utils/compute_units.js +0 -28
  145. package/dist/utils/config_diff.js +0 -185
  146. package/dist/utils/enrichers.js +0 -161
  147. package/dist/utils/esbuild.js +0 -158
  148. package/dist/utils/formats.js +0 -18
  149. package/dist/utils/git_diff.js +0 -90
  150. package/dist/utils/inspect_db.js +0 -153
  151. package/dist/utils/inspect_queries.js +0 -372
  152. package/dist/utils/middlewares.js +0 -20
  153. package/dist/utils/openapi.js +0 -114
  154. package/dist/utils/package_manager.js +0 -68
  155. package/dist/utils/point_in_time.js +0 -56
  156. package/dist/utils/psql.js +0 -120
  157. package/dist/utils/string.js +0 -5
  158. package/dist/utils/ui.js +0 -59
  159. package/dist/utils/zip.js +0 -4
  160. package/dist/writer.js +0 -97
@@ -1,68 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import which from "which";
3
- import { log } from "../log.js";
4
- // npm first so it's the default/preselected choice; the rest follow in rough
5
- // popularity order.
6
- export const PACKAGE_MANAGERS = [
7
- "npm",
8
- "pnpm",
9
- "yarn",
10
- "bun",
11
- ];
12
- /**
13
- * The package manager the CLI was invoked through, read from the
14
- * `npm_config_user_agent` npm sets for `npm exec`/`npx`, `pnpm dlx`, `yarn
15
- * dlx`, and `bunx` (so `pnpm dlx neonctl …` installs with pnpm). Returns
16
- * undefined when there's nothing to infer from — e.g. a globally-installed
17
- * `neon`/`neonctl` — so the caller can ask (or fall back) instead of silently
18
- * assuming npm.
19
- */
20
- export const detectPackageManager = () => {
21
- const ua = process.env.npm_config_user_agent ?? "";
22
- if (ua.startsWith("pnpm"))
23
- return "pnpm";
24
- if (ua.startsWith("yarn"))
25
- return "yarn";
26
- if (ua.startsWith("bun"))
27
- return "bun";
28
- if (ua.startsWith("npm"))
29
- return "npm";
30
- return undefined;
31
- };
32
- /** The package managers actually on PATH, in {@link PACKAGE_MANAGERS} order. */
33
- export const installedPackageManagers = () => PACKAGE_MANAGERS.filter((pm) => which.sync(pm, { nothrow: true }) !== null);
34
- /**
35
- * Pick a package manager without prompting: the one the CLI was invoked through,
36
- * else the first one installed, else npm. Used by non-interactive flows (e.g.
37
- * `config init`) where there's no scaffold prompt to hang a picker off.
38
- */
39
- export const resolvePackageManager = () => detectPackageManager() ?? installedPackageManagers()[0] ?? "npm";
40
- /**
41
- * The argv that adds `packages` as runtime dependencies with `pm`. npm spells it
42
- * `install`; pnpm/yarn/bun use `add`.
43
- */
44
- export const addDependenciesArgs = (pm, packages) => (pm === "npm" ? ["install", ...packages] : ["add", ...packages]);
45
- /**
46
- * Run a command inheriting our stdio so the user sees install / link output
47
- * live and can answer any prompts the child raises. Resolves to whether it
48
- * exited cleanly; a non-zero exit is reported but never throws — the caller
49
- * decides whether to treat it as fatal.
50
- */
51
- export const runCommand = (cmd, args, cwd) => new Promise((resolvePromise) => {
52
- // npm/pnpm/yarn ship as .cmd shims on Windows, which need a shell to run.
53
- const child = spawn(cmd, args, {
54
- cwd,
55
- stdio: "inherit",
56
- shell: process.platform === "win32",
57
- });
58
- child.on("error", (err) => {
59
- log.warning("Could not run `%s %s`: %s", cmd, args.join(" "), err instanceof Error ? err.message : String(err));
60
- resolvePromise(false);
61
- });
62
- child.on("close", (code) => {
63
- if (code !== 0) {
64
- log.warning("`%s %s` exited with code %d.", cmd, args.join(" "), code);
65
- }
66
- resolvePromise(code === 0);
67
- });
68
- });
@@ -1,56 +0,0 @@
1
- import { branchIdResolve } from "./enrichers.js";
2
- import { looksLikeLSN, looksLikeTimestamp } from "./formats.js";
3
- export class PointInTimeParseError extends Error {
4
- constructor(message) {
5
- super(message);
6
- this.name = "PointInTimeParseError";
7
- }
8
- }
9
- export const parsePITBranch = (input) => {
10
- const splitIndex = input.lastIndexOf("@");
11
- const sourceBranch = splitIndex === -1 ? input : input.slice(0, splitIndex);
12
- const exactPIT = splitIndex === -1 ? null : input.slice(splitIndex + 1);
13
- const result = {
14
- branch: sourceBranch,
15
- ...(exactPIT === null
16
- ? { tag: "head" }
17
- : looksLikeLSN(exactPIT)
18
- ? { tag: "lsn", lsn: exactPIT }
19
- : { tag: "timestamp", timestamp: exactPIT }),
20
- };
21
- if (result.tag === "timestamp") {
22
- const timestamp = result.timestamp;
23
- if (!looksLikeTimestamp(timestamp)) {
24
- throw new PointInTimeParseError(`Invalid source branch format - ${input}`);
25
- }
26
- if (Date.parse(timestamp) > Date.now()) {
27
- throw new PointInTimeParseError(`Timestamp can not be in future - ${input}`);
28
- }
29
- }
30
- return result;
31
- };
32
- export const parsePointInTime = async ({ pointInTime, targetBranchId, projectId, api, }) => {
33
- const parsedPIT = parsePITBranch(pointInTime);
34
- let branchId = "";
35
- if (parsedPIT.branch === "^self") {
36
- branchId = targetBranchId;
37
- }
38
- else if (parsedPIT.branch === "^parent") {
39
- const { data } = await api.getProjectBranch(projectId, targetBranchId);
40
- const { parent_id: parentId } = data.branch;
41
- if (parentId == null) {
42
- throw new PointInTimeParseError("Branch has no parent");
43
- }
44
- branchId = parentId;
45
- }
46
- else {
47
- branchId = await branchIdResolve({
48
- branch: parsedPIT.branch,
49
- projectId,
50
- apiClient: api,
51
- });
52
- }
53
- // @ts-expect-error extracting pit from parsedPIT
54
- delete parsedPIT.branch;
55
- return { ...parsedPIT, branchId };
56
- };
@@ -1,120 +0,0 @@
1
- import { spawn } from "child_process";
2
- import which from "which";
3
- import { closeAnalytics, trackEvent } from "../analytics.js";
4
- import { log } from "../log.js";
5
- const FALLBACK_ENV = "NEONCTL_PSQL_FALLBACK";
6
- /** Max time we wait for the analytics flush before handing off to psql. */
7
- const ANALYTICS_FLUSH_TIMEOUT_MS = 3000;
8
- /**
9
- * Decide which psql implementation will run, and why. The PATH probe is
10
- * skipped when TS is forced (flag or env) — we don't need it and it'd be a
11
- * wasted lookup — so `nativeAvailable` is `null` ("not checked") in those
12
- * cases rather than a misleading `false`.
13
- */
14
- const planPsql = async (opts) => {
15
- if (opts.mode === "ts") {
16
- return {
17
- implementation: "ts",
18
- reason: "forced_flag",
19
- nativeAvailable: null,
20
- nativePath: null,
21
- };
22
- }
23
- if (process.env[FALLBACK_ENV] === "1") {
24
- return {
25
- implementation: "ts",
26
- reason: "forced_env",
27
- nativeAvailable: null,
28
- nativePath: null,
29
- };
30
- }
31
- const nativePath = await which("psql", { nothrow: true });
32
- const nativeAvailable = nativePath !== null;
33
- if (opts.mode === "native") {
34
- return {
35
- implementation: "native",
36
- reason: "forced_native",
37
- nativeAvailable,
38
- nativePath,
39
- };
40
- }
41
- // 'auto' (or unset): strict fallback — prefer native, TS only if missing.
42
- return nativeAvailable
43
- ? {
44
- implementation: "native",
45
- reason: "native_available",
46
- nativeAvailable,
47
- nativePath,
48
- }
49
- : {
50
- implementation: "ts",
51
- reason: "fallback_no_native",
52
- nativeAvailable,
53
- nativePath,
54
- };
55
- };
56
- /**
57
- * Record which psql implementation is about to run, then flush analytics.
58
- *
59
- * Both exec paths below call `process.exit()`, which short-circuits the
60
- * main loop's `closeAnalytics()` — so without flushing here the event (and
61
- * any earlier queued events, e.g. `CLI Started`) would be dropped. The
62
- * flush is bounded by {@link ANALYTICS_FLUSH_TIMEOUT_MS} so a slow or
63
- * unreachable analytics endpoint can't stall the psql launch. No-ops when
64
- * analytics is disabled (`--analytics false`), since the client is absent.
65
- */
66
- const reportPsqlInvocation = async (plan) => {
67
- trackEvent("psql_invoked", {
68
- implementation: plan.implementation,
69
- reason: plan.reason,
70
- nativeAvailable: plan.nativeAvailable,
71
- });
72
- await closeAnalytics({ timeout: ANALYTICS_FLUSH_TIMEOUT_MS });
73
- };
74
- const execNative = async (binary, connection_uri, args) => {
75
- log.info("Connecting to the database using psql...");
76
- const child = spawn(binary, [connection_uri, ...args], {
77
- stdio: "inherit",
78
- });
79
- for (const signame of ["SIGINT", "SIGTERM"]) {
80
- process.on(signame, (code) => {
81
- if (!child.killed && code !== null) {
82
- child.kill(code);
83
- }
84
- });
85
- }
86
- return new Promise((_, reject) => {
87
- child.on("exit", (code) => {
88
- process.exit(code === null ? 1 : code);
89
- });
90
- child.on("error", reject);
91
- });
92
- };
93
- const execTs = async (connection_uri, args) => {
94
- log.info("Connecting to the database using embedded psql (TypeScript)...");
95
- const { runPsql } = await import("../psql/index.js");
96
- const code = await runPsql([connection_uri, ...args], {
97
- stdin: process.stdin,
98
- stdout: process.stdout,
99
- stderr: process.stderr,
100
- });
101
- process.exit(code);
102
- };
103
- export const psql = async (connection_uri, args = [], opts = {}) => {
104
- const plan = await planPsql(opts);
105
- await reportPsqlInvocation(plan);
106
- if (plan.implementation === "ts") {
107
- if (plan.reason === "fallback_no_native") {
108
- log.info("psql binary not found on PATH; falling back to embedded TypeScript psql");
109
- }
110
- return execTs(connection_uri, args);
111
- }
112
- // implementation === 'native'
113
- if (plan.nativePath === null) {
114
- // Only reachable when native was explicitly requested (mode: 'native')
115
- // but no binary is on PATH.
116
- log.error(`psql is not available in the PATH`);
117
- process.exit(1);
118
- }
119
- return execNative(plan.nativePath, connection_uri, args);
120
- };
@@ -1,5 +0,0 @@
1
- export const toSnakeCase = (str) => str
2
- .split(" ")
3
- .map((word) => word.toLowerCase())
4
- .join("_");
5
- export const isObject = (value) => value != null && value === Object(value);
package/dist/utils/ui.js DELETED
@@ -1,59 +0,0 @@
1
- // returns the next string if matches the given matcher,
2
- // otherwise returns null
3
- // consumes the line from the lines array
4
- export const consumeNextMatching = (lines, matcher) => {
5
- while (lines.length > 0) {
6
- const line = lines.shift().trim();
7
- if (line === "") {
8
- continue;
9
- }
10
- if (matcher.test(line)) {
11
- return line;
12
- }
13
- return null;
14
- }
15
- return null;
16
- };
17
- // returns strings if next non-empty line matches the given matcher,
18
- // otherwise returns empty array
19
- // consumes the lines from the lines array
20
- export const consumeBlockIfMatches = (lines, matcher) => {
21
- const result = [];
22
- if (lines.length === 0) {
23
- return result;
24
- }
25
- let line = lines.shift();
26
- while (line.trim() === "") {
27
- line = lines.shift();
28
- }
29
- if (!matcher.test(line)) {
30
- lines.unshift(line);
31
- return result;
32
- }
33
- result.push(line);
34
- while (lines.length > 0) {
35
- line = lines.shift();
36
- if (line.trim() === "") {
37
- break;
38
- }
39
- result.push(line);
40
- }
41
- return result;
42
- };
43
- export const splitColumns = (line) => {
44
- const result = line.trim().split(/\s{2,}/);
45
- result[1] = result[1] ?? "";
46
- if (result.length > 2) {
47
- result[1] = result.slice(1).join(" ");
48
- }
49
- return result;
50
- };
51
- export const drawPointer = (width) => {
52
- const result = [];
53
- result.push("└");
54
- for (let i = 0; i < width - 4; i++) {
55
- result.push("─");
56
- }
57
- result.push(">");
58
- return result.join("");
59
- };
package/dist/utils/zip.js DELETED
@@ -1,4 +0,0 @@
1
- import { zipSync } from "fflate";
2
- // Zip the esbuild output (index.mjs) into the archive the Functions deploy endpoint
3
- // expects. Compression level 6 matches the previous bundler.
4
- export const zipBundle = (entries) => zipSync(entries, { level: 6 });
package/dist/writer.js DELETED
@@ -1,97 +0,0 @@
1
- import chalk from "chalk";
2
- import Table from "cli-table";
3
- import YAML from "yaml";
4
- import { isCi } from "./env.js";
5
- import { isObject, toSnakeCase } from "./utils/string.js";
6
- const writeYaml = (chunks) => {
7
- return YAML.stringify(chunks.length === 1
8
- ? chunks[0].data
9
- : Object.fromEntries(chunks.map(({ config, data }, idx) => [
10
- config.title ? toSnakeCase(config.title) : idx,
11
- data,
12
- ])), null, 2);
13
- };
14
- const writeJson = (chunks) => {
15
- return JSON.stringify(chunks.length === 1
16
- ? chunks[0].data
17
- : Object.fromEntries(chunks.map(({ config, data }, idx) => [
18
- config.title ? toSnakeCase(config.title) : idx,
19
- data,
20
- ])), null, 2);
21
- };
22
- const writeTable = (chunks, out) => {
23
- chunks.forEach(({ data, config: { emptyMessage, fields, title, renderColumns = {} }, }) => {
24
- const arrayData = Array.isArray(data) ? data : [data];
25
- if (!arrayData.length && emptyMessage) {
26
- out.write("\n" + emptyMessage + "\n");
27
- return;
28
- }
29
- const fieldsFiltered = fields.filter((field) => arrayData.some((item) => item[field] !== undefined && item[field] !== ""));
30
- const table = new Table({
31
- style: {
32
- head: ["green"],
33
- },
34
- head: fieldsFiltered.map((field) => field
35
- .split("_")
36
- .map((word) => word[0].toUpperCase() + word.slice(1))
37
- .join(" ")),
38
- });
39
- arrayData.forEach((item) => {
40
- table.push(fieldsFiltered.map((field) => {
41
- const value = item[field];
42
- if (renderColumns[field]) {
43
- return renderColumns[field]?.(item);
44
- }
45
- return Array.isArray(value)
46
- ? value.join("\n")
47
- : isObject(value)
48
- ? JSON.stringify(value, null, 2)
49
- : (value ?? "");
50
- }));
51
- });
52
- if (title) {
53
- out.write((isCi() ? title : chalk.bold(title)) + "\n");
54
- }
55
- out.write(table.toString());
56
- out.write("\n");
57
- });
58
- };
59
- /**
60
- *
61
- * Parses the output format, takes data and writes the output to stdout.
62
- *
63
- * @example
64
- * const { data } = await props.apiClient.listProjectBranches(props.project.id);
65
- * // to output single data
66
- * writer(props).end(data, { fields: ['id', 'name', 'created_at'] })
67
- * // to output multiple data
68
- * writer(props)
69
- * .write(data, { fields: ['id', 'name', 'created_at'], title: 'branches' })
70
- * .write(data, { fields: ['id', 'created_at'], title: 'endpoints' })
71
- * .end()
72
- */
73
- export const writer = (props) => {
74
- const out = props.out ?? process.stdout;
75
- const chunks = [];
76
- return {
77
- write(data, config) {
78
- chunks.push({ data, config });
79
- return this;
80
- },
81
- text(data) {
82
- return out.write(data);
83
- },
84
- end: (...args) => {
85
- if (args.length === 2) {
86
- chunks.push({ data: args[0], config: args[1] });
87
- }
88
- if (props.output == "yaml") {
89
- return out.write(writeYaml(chunks));
90
- }
91
- if (props.output == "json") {
92
- return out.write(writeJson(chunks));
93
- }
94
- writeTable(chunks, out);
95
- },
96
- };
97
- };