heroku 11.10.1 → 11.11.0-beta.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.
- package/CHANGELOG.md +28 -0
- package/dist/commands/addons/create.js +1 -1
- package/dist/commands/apps/transfer.js +1 -1
- package/dist/commands/certs/add.js +1 -1
- package/dist/commands/certs/auto/disable.js +1 -1
- package/dist/commands/certs/auto/index.js +1 -1
- package/dist/commands/certs/remove.js +1 -1
- package/dist/commands/certs/update.js +1 -1
- package/dist/commands/ci/config/set.js +1 -1
- package/dist/commands/config/set.js +1 -1
- package/dist/commands/config/unset.js +1 -1
- package/dist/commands/data/pg/attachments/create.js +1 -1
- package/dist/commands/data/pg/create.js +1 -1
- package/dist/commands/data/pg/credentials/create.js +1 -1
- package/dist/commands/data/pg/credentials/url.js +1 -1
- package/dist/commands/data/pg/fork.js +1 -1
- package/dist/commands/data/pg/get-ca.d.ts +12 -0
- package/dist/commands/data/pg/get-ca.js +64 -0
- package/dist/commands/data/pg/info.js +1 -1
- package/dist/commands/data/pg/logical-replication/publications/create.d.ts +19 -0
- package/dist/commands/data/pg/logical-replication/publications/create.js +60 -0
- package/dist/commands/data/pg/logical-replication/publications/destroy.d.ts +16 -0
- package/dist/commands/data/pg/logical-replication/publications/destroy.js +38 -0
- package/dist/commands/data/pg/logical-replication/publications/index.d.ts +15 -0
- package/dist/commands/data/pg/logical-replication/publications/index.js +43 -0
- package/dist/commands/data/pg/logical-replication/publications/info.d.ts +15 -0
- package/dist/commands/data/pg/logical-replication/publications/info.js +36 -0
- package/dist/commands/data/pg/logical-replication/publications/update.d.ts +19 -0
- package/dist/commands/data/pg/logical-replication/publications/update.js +60 -0
- package/dist/commands/data/pg/logical-replication/publishing/enable.d.ts +14 -0
- package/dist/commands/data/pg/logical-replication/publishing/enable.js +36 -0
- package/dist/commands/data/pg/logical-replication/subscribing/enable.d.ts +14 -0
- package/dist/commands/data/pg/logical-replication/subscribing/enable.js +37 -0
- package/dist/commands/data/pg/migrate.d.ts +2 -0
- package/dist/commands/data/pg/migrate.js +11 -6
- package/dist/commands/data/pg/psql.js +1 -1
- package/dist/commands/data/pg/quotas/update.js +1 -1
- package/dist/commands/data/pg/settings.js +1 -1
- package/dist/commands/data/pg/update.js +1 -1
- package/dist/commands/data/pg/upgrade/run.js +1 -1
- package/dist/commands/data/pg/upgrade/wait.js +1 -1
- package/dist/commands/data/pg/wait.js +1 -1
- package/dist/commands/domains/add.js +7 -5
- package/dist/commands/logs.js +1 -1
- package/dist/commands/pg/backups/capture.js +1 -1
- package/dist/commands/pg/backups/restore.js +1 -1
- package/dist/commands/pg/blocking.js +1 -1
- package/dist/commands/pg/cache-hit.js +1 -1
- package/dist/commands/pg/calls.js +1 -1
- package/dist/commands/pg/connection-pooling/attach.js +1 -1
- package/dist/commands/pg/credentials/create.js +1 -1
- package/dist/commands/pg/credentials/repair-default.js +1 -1
- package/dist/commands/pg/credentials/url.js +1 -1
- package/dist/commands/pg/diagnose.js +1 -1
- package/dist/commands/pg/extensions.js +1 -1
- package/dist/commands/pg/fdwsql.js +1 -1
- package/dist/commands/pg/index-size.js +1 -1
- package/dist/commands/pg/index-usage.js +1 -1
- package/dist/commands/pg/kill.js +1 -1
- package/dist/commands/pg/links/destroy.js +1 -1
- package/dist/commands/pg/locks.js +1 -1
- package/dist/commands/pg/long-running-queries.js +1 -1
- package/dist/commands/pg/mandelbrot.js +1 -1
- package/dist/commands/pg/outliers.js +1 -1
- package/dist/commands/pg/promote.js +1 -1
- package/dist/commands/pg/ps.js +1 -1
- package/dist/commands/pg/psql.js +1 -1
- package/dist/commands/pg/pull.js +1 -1
- package/dist/commands/pg/push.js +1 -1
- package/dist/commands/pg/records-rank.js +1 -1
- package/dist/commands/pg/reset.js +1 -1
- package/dist/commands/pg/seq-scans.js +1 -1
- package/dist/commands/pg/settings/auto-explain/log-analyze.js +1 -1
- package/dist/commands/pg/settings/auto-explain/log-buffers.js +1 -1
- package/dist/commands/pg/settings/auto-explain/log-format.js +1 -1
- package/dist/commands/pg/settings/auto-explain/log-min-duration.js +1 -1
- package/dist/commands/pg/settings/auto-explain/log-triggers.js +1 -1
- package/dist/commands/pg/settings/auto-explain/log-verbose.js +1 -1
- package/dist/commands/pg/settings/auto-explain.js +1 -1
- package/dist/commands/pg/settings/data-connector-details-logs.js +1 -1
- package/dist/commands/pg/settings/log-connections.js +1 -1
- package/dist/commands/pg/settings/log-lock-waits.js +1 -1
- package/dist/commands/pg/settings/log-min-duration-statement.js +1 -1
- package/dist/commands/pg/settings/log-min-error-statement.js +1 -1
- package/dist/commands/pg/settings/log-statement.js +1 -1
- package/dist/commands/pg/settings/track-functions.js +1 -1
- package/dist/commands/pg/stats-reset.js +1 -1
- package/dist/commands/pg/table-indexes-size.js +1 -1
- package/dist/commands/pg/table-size.js +1 -1
- package/dist/commands/pg/total-index-size.js +1 -1
- package/dist/commands/pg/total-table-size.js +1 -1
- package/dist/commands/pg/unfollow.js +1 -1
- package/dist/commands/pg/unused-indexes.js +1 -1
- package/dist/commands/pg/upgrade/cancel.js +1 -1
- package/dist/commands/pg/upgrade/dryrun.js +1 -1
- package/dist/commands/pg/upgrade/prepare.js +1 -1
- package/dist/commands/pg/upgrade/run.js +1 -1
- package/dist/commands/pg/upgrade/wait.js +1 -1
- package/dist/commands/pg/user-connections.js +1 -1
- package/dist/commands/pg/vacuum-stats.js +1 -1
- package/dist/commands/ps/forward.js +1 -1
- package/dist/commands/ps/index.d.ts +0 -1
- package/dist/commands/ps/index.js +24 -26
- package/dist/commands/ps/restart.js +1 -1
- package/dist/commands/ps/scale.js +1 -1
- package/dist/commands/ps/socks.js +1 -1
- package/dist/commands/ps/stop.js +1 -1
- package/dist/commands/ps/type.js +1 -1
- package/dist/commands/redis/keyspace-notifications.js +1 -1
- package/dist/commands/redis/stats-reset.js +1 -1
- package/dist/commands/redis/upgrade.js +1 -1
- package/dist/commands/reviewapps/create.js +1 -1
- package/dist/commands/run/inside.js +1 -1
- package/dist/commands/spaces/create.js +1 -1
- package/dist/commands/spaces/destroy.js +1 -1
- package/dist/commands/spaces/hosts.js +1 -1
- package/dist/commands/spaces/info.js +1 -1
- package/dist/commands/spaces/peerings/accept.js +1 -1
- package/dist/commands/spaces/peerings/destroy.js +1 -1
- package/dist/commands/spaces/peerings/index.js +1 -1
- package/dist/commands/spaces/peerings/info.js +1 -1
- package/dist/commands/spaces/rename.js +1 -1
- package/dist/commands/spaces/topology.js +1 -1
- package/dist/commands/spaces/transfer.js +1 -1
- package/dist/commands/spaces/trusted-ips/add.js +1 -1
- package/dist/commands/spaces/trusted-ips/index.js +1 -1
- package/dist/commands/spaces/trusted-ips/remove.js +1 -1
- package/dist/commands/spaces/vpn/config.js +1 -1
- package/dist/commands/spaces/vpn/connect.js +1 -1
- package/dist/commands/spaces/vpn/connections.js +1 -1
- package/dist/commands/spaces/vpn/destroy.js +1 -1
- package/dist/commands/spaces/vpn/info.js +1 -1
- package/dist/commands/spaces/vpn/update.js +1 -1
- package/dist/commands/spaces/vpn/wait.js +1 -1
- package/dist/commands/spaces/wait.js +1 -1
- package/dist/commands/telemetry/add.js +1 -1
- package/dist/commands/telemetry/remove.js +1 -1
- package/dist/commands/telemetry/update.js +1 -1
- package/dist/hooks/finally/send-otel-and-sentry-errors.js +1 -28
- package/dist/hooks/preupdate/check-npm-auth.js +1 -2
- package/dist/lib/analytics-telemetry/error-classification.d.ts +6 -0
- package/dist/lib/analytics-telemetry/error-classification.js +51 -0
- package/dist/lib/analytics-telemetry/telemetry-manager.js +7 -5
- package/dist/lib/ci/git.js +6 -5
- package/dist/lib/data/logical-replication.d.ts +35 -0
- package/dist/lib/data/logical-replication.js +10 -0
- package/dist/lib/data/pool-config.js +1 -1
- package/dist/lib/data/types.d.ts +1 -1
- package/dist/lib/npm-auth.js +1 -2
- package/dist/lib/pg/backups.js +1 -1
- package/dist/lib/pg/push-pull.js +1 -1
- package/dist/lib/pipelines/disambiguate.js +2 -2
- package/dist/lib/ps-exec/exec.js +1 -1
- package/dist/lib/utils/sparkline.js +12 -14
- package/oclif.manifest.json +6264 -5703
- package/package.json +9 -7
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,34 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
## [11.11.0-beta.0](https://github.com/heroku/cli/compare/v11.10.1...v11.11.0-beta.0) (2026-09-30)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add data:pg:get-ca ([#3880](https://github.com/heroku/cli/issues/3880)) ([e0890e1](https://github.com/heroku/cli/commit/e0890e1b0010f51e4ff8b01ca4a407bf3a9bf046))
|
|
12
|
+
* **data:** manage Postgres Advanced logical replication ([#3902](https://github.com/heroku/cli/issues/3902)) ([7c24954](https://github.com/heroku/cli/commit/7c24954d583f52e7661c9352a3072deadb330a32))
|
|
13
|
+
* **data:** show status description consistently and allow refresh in data:pg:migrate ([#3942](https://github.com/heroku/cli/issues/3942)) ([be99e83](https://github.com/heroku/cli/commit/be99e83adb5ceb988774eda7c6e73cca4fc89653))
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **ps:** render ps --extended as vertical detail blocks ([#3892](https://github.com/heroku/cli/issues/3892)) ([db49d87](https://github.com/heroku/cli/commit/db49d8727a5b0351934b78c8b815907d0464a126))
|
|
18
|
+
* render sparklines for fractional values at full resolution ([#3954](https://github.com/heroku/cli/issues/3954)) ([220d68c](https://github.com/heroku/cli/commit/220d68c0cb5053942c7c0743d4365c57dcbe4b49)), closes [#3885](https://github.com/heroku/cli/issues/3885)
|
|
19
|
+
* serve the matching ARM build for Linux Homebrew installs ([#3919](https://github.com/heroku/cli/issues/3919)) ([#3953](https://github.com/heroku/cli/issues/3953)) ([c619f4e](https://github.com/heroku/cli/commit/c619f4edd58da498419640fee7f13c080fec4c1a))
|
|
20
|
+
* skip SNI endpoint chooser with ACM enabled (W-17760520) ([#3959](https://github.com/heroku/cli/issues/3959)) ([b34172c](https://github.com/heroku/cli/commit/b34172cddf3406ebe1722db9286d15ea739ee726))
|
|
21
|
+
* surface ci git & pipeline user errors as CLIErrors, not strings ([#3951](https://github.com/heroku/cli/issues/3951)) ([e4663a8](https://github.com/heroku/cli/commit/e4663a8259623583f156d65f48ece08389c28147)), closes [#1695](https://github.com/heroku/cli/issues/1695) [#1695](https://github.com/heroku/cli/issues/1695)
|
|
22
|
+
|
|
23
|
+
### Miscellaneous Chores
|
|
24
|
+
|
|
25
|
+
* update dependencies and regenerate lock file ([#3962](https://github.com/heroku/cli/issues/3962)) ([4b403c1](https://github.com/heroku/cli/commit/4b403c1d0626210bcbddcf0331aaad352ab12b49))
|
|
26
|
+
|
|
27
|
+
### Code Refactoring
|
|
28
|
+
|
|
29
|
+
* classify telemetry errors; keep Honeycomb analytics, filter Sentry (W-22403348) ([#3950](https://github.com/heroku/cli/issues/3950)) ([df63a4c](https://github.com/heroku/cli/commit/df63a4cf284fa64ca89d9b3d865f9bd7214edd24)), references [heroku/heroku-cli-command#408](https://github.com/heroku/cli/issues/408)
|
|
30
|
+
|
|
31
|
+
### Continuous Integration
|
|
32
|
+
|
|
33
|
+
* publish Dev Center docs via @heroku-cli/plugin-devcenter ([#3945](https://github.com/heroku/cli/issues/3945)) ([8922ea8](https://github.com/heroku/cli/commit/8922ea8f1b7f413e1f225f58d7152f16b7825894))
|
|
34
|
+
|
|
7
35
|
## [11.10.1](https://github.com/heroku/cli/compare/v11.10.0...v11.10.1) (2026-09-23)
|
|
8
36
|
|
|
9
37
|
|
|
@@ -4,7 +4,7 @@ import { Args, ux } from '@oclif/core';
|
|
|
4
4
|
import tsheredoc from 'tsheredoc';
|
|
5
5
|
import createAddon from '../../lib/addons/create-addon.js';
|
|
6
6
|
import notify from '../../lib/notify.js';
|
|
7
|
-
const heredoc = tsheredoc
|
|
7
|
+
const heredoc = tsheredoc;
|
|
8
8
|
export default class Create extends Command {
|
|
9
9
|
static args = {
|
|
10
10
|
'service:plan': Args.string({ description: 'unique identifier or unique name of the add-on service plan', required: true }),
|
|
@@ -7,7 +7,7 @@ import ConfirmCommand from '../../lib/confirm-command.js';
|
|
|
7
7
|
import { lazyModuleLoader } from '../../lib/lazy-module-loader.js';
|
|
8
8
|
import { getOwner, isTeamApp, isValidEmail } from '../../lib/team-utils.js';
|
|
9
9
|
import AppsLock from './lock.js';
|
|
10
|
-
const heredoc = tsheredoc
|
|
10
|
+
const heredoc = tsheredoc;
|
|
11
11
|
export default class AppsTransfer extends Command {
|
|
12
12
|
static args = {
|
|
13
13
|
recipient: Args.string({ description: 'user or team to transfer applications to', required: true }),
|
|
@@ -6,7 +6,7 @@ import { displayCertificateDetails } from '../../lib/certs/certificate-details.j
|
|
|
6
6
|
import { waitForDomains } from '../../lib/certs/domains.js';
|
|
7
7
|
import { CertAndKeyManager } from '../../lib/certs/get-cert-and-key.js';
|
|
8
8
|
import { lazyModuleLoader } from '../../lib/lazy-module-loader.js';
|
|
9
|
-
const heredoc = tsheredoc
|
|
9
|
+
const heredoc = tsheredoc;
|
|
10
10
|
export default class Add extends Command {
|
|
11
11
|
static args = {
|
|
12
12
|
CRT: Args.string({ description: 'absolute path of the certificate file on disk', required: true }),
|
|
@@ -3,7 +3,7 @@ import * as color from '@heroku/heroku-cli-util/color';
|
|
|
3
3
|
import { ux } from '@oclif/core/ux';
|
|
4
4
|
import tsheredoc from 'tsheredoc';
|
|
5
5
|
import ConfirmCommand from '../../../lib/confirm-command.js';
|
|
6
|
-
const heredoc = tsheredoc
|
|
6
|
+
const heredoc = tsheredoc;
|
|
7
7
|
export default class Disable extends Command {
|
|
8
8
|
static description = 'disable ACM for an app';
|
|
9
9
|
static flags = {
|
|
@@ -5,7 +5,7 @@ import tsheredoc from 'tsheredoc';
|
|
|
5
5
|
import { displayCertificateDetails } from '../../../lib/certs/certificate-details.js';
|
|
6
6
|
import { waitForCertIssuedOnDomains } from '../../../lib/domains/domains.js';
|
|
7
7
|
import { lazyModuleLoader } from '../../../lib/lazy-module-loader.js';
|
|
8
|
-
const heredoc = tsheredoc
|
|
8
|
+
const heredoc = tsheredoc;
|
|
9
9
|
function humanize(value) {
|
|
10
10
|
if (!value) {
|
|
11
11
|
return color.info('Waiting');
|
|
@@ -4,7 +4,7 @@ import { ux } from '@oclif/core/ux';
|
|
|
4
4
|
import tsheredoc from 'tsheredoc';
|
|
5
5
|
import getEndpoint from '../../lib/certs/flags.js';
|
|
6
6
|
import ConfirmCommand from '../../lib/confirm-command.js';
|
|
7
|
-
const heredoc = tsheredoc
|
|
7
|
+
const heredoc = tsheredoc;
|
|
8
8
|
export default class Remove extends Command {
|
|
9
9
|
static description = 'remove an SSL certificate from an app';
|
|
10
10
|
static flags = {
|
|
@@ -6,7 +6,7 @@ import { displayCertificateDetails } from '../../lib/certs/certificate-details.j
|
|
|
6
6
|
import getEndpoint from '../../lib/certs/flags.js';
|
|
7
7
|
import { CertAndKeyManager } from '../../lib/certs/get-cert-and-key.js';
|
|
8
8
|
import ConfirmCommand from '../../lib/confirm-command.js';
|
|
9
|
-
const heredoc = tsheredoc
|
|
9
|
+
const heredoc = tsheredoc;
|
|
10
10
|
export default class Update extends Command {
|
|
11
11
|
static args = {
|
|
12
12
|
CRT: Args.string({ description: 'absolute path of the certificate file on disk', required: true }),
|
|
@@ -5,7 +5,7 @@ import tsheredoc from 'tsheredoc';
|
|
|
5
5
|
import { setPipelineConfigVars } from '../../../lib/api.js';
|
|
6
6
|
import { getPipeline } from '../../../lib/ci/pipelines.js';
|
|
7
7
|
import { validateArgvPresent } from '../../../lib/ci/validate.js';
|
|
8
|
-
const heredoc = tsheredoc
|
|
8
|
+
const heredoc = tsheredoc;
|
|
9
9
|
export default class CiConfigSet extends Command {
|
|
10
10
|
static description = 'set CI config vars';
|
|
11
11
|
static examples = [heredoc(`
|
|
@@ -2,7 +2,7 @@ import { Command, flags } from '@heroku-cli/command';
|
|
|
2
2
|
import { color, hux } from '@heroku/heroku-cli-util';
|
|
3
3
|
import { ux } from '@oclif/core/ux';
|
|
4
4
|
import tsheredoc from 'tsheredoc';
|
|
5
|
-
const heredoc = tsheredoc
|
|
5
|
+
const heredoc = tsheredoc;
|
|
6
6
|
const lastRelease = async (client, app) => {
|
|
7
7
|
const { body: releases } = await client.get(`/apps/${app}/releases`, {
|
|
8
8
|
headers: { Range: 'version ..; order=desc,max=1' },
|
|
@@ -2,7 +2,7 @@ import { Command, flags } from '@heroku-cli/command';
|
|
|
2
2
|
import * as color from '@heroku/heroku-cli-util/color';
|
|
3
3
|
import { ux } from '@oclif/core/ux';
|
|
4
4
|
import tsheredoc from 'tsheredoc';
|
|
5
|
-
const heredoc = tsheredoc
|
|
5
|
+
const heredoc = tsheredoc;
|
|
6
6
|
export class ConfigUnset extends Command {
|
|
7
7
|
static aliases = [
|
|
8
8
|
'config:remove',
|
|
@@ -9,7 +9,7 @@ import BaseCommand from '../../../../lib/data/base-command.js';
|
|
|
9
9
|
import { sortByLeaderAndName, sortByOwnerAndName } from '../../../../lib/data/credential-utils.js';
|
|
10
10
|
import { AdvancedCredentialState, PoolStatus, } from '../../../../lib/data/types.js';
|
|
11
11
|
const { prompt } = inquirer;
|
|
12
|
-
const heredoc = tsheredoc
|
|
12
|
+
const heredoc = tsheredoc;
|
|
13
13
|
export default class DataPgAttachmentsCreate extends BaseCommand {
|
|
14
14
|
static args = {
|
|
15
15
|
database: Args.string({
|
|
@@ -11,7 +11,7 @@ import { parseProvisionOpts } from '../../../lib/data/parse-provision-opts.js';
|
|
|
11
11
|
import PoolConfig from '../../../lib/data/pool-config.js';
|
|
12
12
|
import { fetchLevelsAndPricing } from '../../../lib/data/utils.js';
|
|
13
13
|
import notify from '../../../lib/notify.js';
|
|
14
|
-
const heredoc = tsheredoc
|
|
14
|
+
const heredoc = tsheredoc;
|
|
15
15
|
const { prompt } = inquirer;
|
|
16
16
|
export default class DataPgCreate extends BaseCommand {
|
|
17
17
|
static baseFlags = BaseCommand.baseFlagsWithoutPrompt();
|
|
@@ -3,7 +3,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
|
|
|
3
3
|
import { Args, ux } from '@oclif/core';
|
|
4
4
|
import tsheredoc from 'tsheredoc';
|
|
5
5
|
import BaseCommand from '../../../../lib/data/base-command.js';
|
|
6
|
-
const heredoc = tsheredoc
|
|
6
|
+
const heredoc = tsheredoc;
|
|
7
7
|
export default class DataPgCredentialsCreate extends BaseCommand {
|
|
8
8
|
static args = {
|
|
9
9
|
database: Args.string({
|
|
@@ -5,7 +5,7 @@ import { URL } from 'node:url';
|
|
|
5
5
|
import tsheredoc from 'tsheredoc';
|
|
6
6
|
import BaseCommand from '../../../../lib/data/base-command.js';
|
|
7
7
|
import { isAdvancedCredentialInfo } from '../../../../lib/data/types.js';
|
|
8
|
-
const heredoc = tsheredoc
|
|
8
|
+
const heredoc = tsheredoc;
|
|
9
9
|
export default class Url extends BaseCommand {
|
|
10
10
|
static args = {
|
|
11
11
|
database: Args.string({
|
|
@@ -7,7 +7,7 @@ import BaseCommand from '../../../lib/data/base-command.js';
|
|
|
7
7
|
import { parseProvisionOpts } from '../../../lib/data/parse-provision-opts.js';
|
|
8
8
|
import { lazyModuleLoader } from '../../../lib/lazy-module-loader.js';
|
|
9
9
|
import notify from '../../../lib/notify.js';
|
|
10
|
-
const heredoc = tsheredoc
|
|
10
|
+
const heredoc = tsheredoc;
|
|
11
11
|
export default class Fork extends BaseCommand {
|
|
12
12
|
static args = {
|
|
13
13
|
database: Args.string({
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from '@heroku-cli/command';
|
|
2
|
+
export default class DataPgGetCa extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
region: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
private awsRegion;
|
|
10
|
+
private destinationDirectory;
|
|
11
|
+
private download;
|
|
12
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Command, flags } from '@heroku-cli/command';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
const RDS_CERTIFICATE_HOST = 'https://truststore.pki.rds.amazonaws.com';
|
|
6
|
+
const REGION_ALIASES = {
|
|
7
|
+
eu: 'eu-west-1',
|
|
8
|
+
us: 'us-east-1',
|
|
9
|
+
};
|
|
10
|
+
export default class DataPgGetCa extends Command {
|
|
11
|
+
static description = 'download the RDS CA bundle for a Heroku region';
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --region virginia',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> --region global',
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
region: flags.string({
|
|
18
|
+
description: 'Heroku region or global for the AWS global CA bundle',
|
|
19
|
+
required: true,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
async run() {
|
|
23
|
+
const { flags } = await this.parse(DataPgGetCa);
|
|
24
|
+
let destination = '';
|
|
25
|
+
try {
|
|
26
|
+
destination = this.destinationDirectory();
|
|
27
|
+
const awsRegion = flags.region === 'global' ? 'global' : await this.awsRegion(flags.region);
|
|
28
|
+
const fileName = `${awsRegion}-bundle.pem`;
|
|
29
|
+
destination = path.join(destination, fileName);
|
|
30
|
+
const url = `${RDS_CERTIFICATE_HOST}/${awsRegion}/${fileName}`;
|
|
31
|
+
const certificate = await this.download(url);
|
|
32
|
+
await fs.outputFile(destination, certificate, { mode: 0o600 });
|
|
33
|
+
this.log(`RDS CA bundle retrieved successfully: ${destination}`);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
37
|
+
this.error(`Unable to retrieve the RDS CA bundle at ${destination}: ${message}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async awsRegion(herokuRegion) {
|
|
41
|
+
if (REGION_ALIASES[herokuRegion])
|
|
42
|
+
return REGION_ALIASES[herokuRegion];
|
|
43
|
+
const { body: regions } = await this.heroku.get('/regions');
|
|
44
|
+
const region = regions.find(candidate => candidate.name === herokuRegion);
|
|
45
|
+
const awsRegion = region?.provider?.region;
|
|
46
|
+
if (!awsRegion)
|
|
47
|
+
throw new Error(`${herokuRegion} is not a Heroku region backed by AWS.`);
|
|
48
|
+
return awsRegion;
|
|
49
|
+
}
|
|
50
|
+
destinationDirectory() {
|
|
51
|
+
if (process.platform === 'win32') {
|
|
52
|
+
if (!process.env.APPDATA)
|
|
53
|
+
throw new Error('APPDATA is not set; unable to determine the PostgreSQL certificate directory.');
|
|
54
|
+
return path.join(process.env.APPDATA, 'postgresql');
|
|
55
|
+
}
|
|
56
|
+
return path.join(os.homedir(), '.postgresql');
|
|
57
|
+
}
|
|
58
|
+
async download(url) {
|
|
59
|
+
const response = await fetch(url);
|
|
60
|
+
if (!response.ok)
|
|
61
|
+
throw new Error(`AWS RDS returned ${response.status} ${response.statusText}.`);
|
|
62
|
+
return Buffer.from(await response.arrayBuffer());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -5,7 +5,7 @@ import tsheredoc from 'tsheredoc';
|
|
|
5
5
|
import BaseCommand from '../../../lib/data/base-command.js';
|
|
6
6
|
import { formatQuotaStatus } from '../../../lib/data/display-quota.js';
|
|
7
7
|
import { parseAttachmentFactors } from '../../../lib/data/parse-attachment-factors.js';
|
|
8
|
-
const heredoc = tsheredoc
|
|
8
|
+
const heredoc = tsheredoc;
|
|
9
9
|
const poolStatusRenderMap = {
|
|
10
10
|
available: color.success('✓ Available'),
|
|
11
11
|
modifying: color.warning('⚡ Modifying'),
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
2
|
+
export default class DataPgLogicalReplicationPublicationsCreate extends BaseCommand {
|
|
3
|
+
static aliases: string[];
|
|
4
|
+
static args: {
|
|
5
|
+
database: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
'all-schemas': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
remote: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
schema: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
table: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
private publicationTarget;
|
|
19
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { flags as Flags } from '@heroku-cli/command';
|
|
2
|
+
import { color } from '@heroku/heroku-cli-util';
|
|
3
|
+
import { Args, ux } from '@oclif/core';
|
|
4
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
5
|
+
import { resolveAdvancedDatabase } from '../../../../../lib/data/logical-replication.js';
|
|
6
|
+
export default class DataPgLogicalReplicationPublicationsCreate extends BaseCommand {
|
|
7
|
+
static aliases = ['data:pg:lr:publications:create'];
|
|
8
|
+
static args = {
|
|
9
|
+
database: Args.string({
|
|
10
|
+
description: 'database name, database attachment name, or related config var on an app',
|
|
11
|
+
required: true,
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
static description = 'create a logical replication publication on a Postgres Advanced database';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %> DATABASE --name orders --table public.orders --app example-app',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> DATABASE --name application --schema public --app example-app',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> DATABASE --name application --all-schemas --app example-app',
|
|
19
|
+
];
|
|
20
|
+
static flags = {
|
|
21
|
+
'all-schemas': Flags.boolean({
|
|
22
|
+
description: 'include all current customer schemas',
|
|
23
|
+
exclusive: ['schema', 'table'],
|
|
24
|
+
}),
|
|
25
|
+
app: Flags.app({ required: true }),
|
|
26
|
+
name: Flags.string({ description: 'name for publication', required: true }),
|
|
27
|
+
remote: Flags.remote(),
|
|
28
|
+
schema: Flags.string({ description: 'schema to include, including new tables created in the schema', multiple: true }),
|
|
29
|
+
table: Flags.string({ description: 'fully qualified table to include', multiple: true }),
|
|
30
|
+
};
|
|
31
|
+
async run() {
|
|
32
|
+
const { args, flags } = await this.parse(DataPgLogicalReplicationPublicationsCreate);
|
|
33
|
+
const addon = await resolveAdvancedDatabase(this, args.database, flags.app);
|
|
34
|
+
const target = this.publicationTarget(flags['all-schemas'], flags.table, flags.schema);
|
|
35
|
+
try {
|
|
36
|
+
ux.action.start(`Creating publication ${color.name(flags.name)} on ${color.datastore(addon.name)}`);
|
|
37
|
+
await this.dataApi.post(`/data/postgres/v1/${addon.id}/logical-replication/publications`, { body: { name: flags.name, target } });
|
|
38
|
+
ux.action.stop();
|
|
39
|
+
if (flags['all-schemas']) {
|
|
40
|
+
ux.stdout('The publication includes all current customer schemas. It doesn’t automatically add new tables or schemas created later.');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
ux.action.stop(color.red('!'));
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
publicationTarget(allSchemas, tables, schemas) {
|
|
49
|
+
if (allSchemas)
|
|
50
|
+
return { type: 'all_customer_schemas' };
|
|
51
|
+
if (tables && schemas) {
|
|
52
|
+
ux.error('You can only use either --table or --schema, not both.');
|
|
53
|
+
}
|
|
54
|
+
if (tables)
|
|
55
|
+
return { tables, type: 'tables' };
|
|
56
|
+
if (schemas)
|
|
57
|
+
return { schemas, type: 'schemas' };
|
|
58
|
+
ux.error('You must use --all-schemas, or either --table or --schema.');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
2
|
+
export default class DataPgLogicalReplicationPublicationsDestroy extends BaseCommand {
|
|
3
|
+
static aliases: string[];
|
|
4
|
+
static args: {
|
|
5
|
+
database: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
confirm: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
remote: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { flags as Flags } from '@heroku-cli/command';
|
|
2
|
+
import { color, hux } from '@heroku/heroku-cli-util';
|
|
3
|
+
import { Args, ux } from '@oclif/core';
|
|
4
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
5
|
+
import { resolveAdvancedDatabase } from '../../../../../lib/data/logical-replication.js';
|
|
6
|
+
export default class DataPgLogicalReplicationPublicationsDestroy extends BaseCommand {
|
|
7
|
+
static aliases = ['data:pg:lr:publications:destroy'];
|
|
8
|
+
static args = {
|
|
9
|
+
database: Args.string({
|
|
10
|
+
description: 'database name, database attachment name, or related config var on an app',
|
|
11
|
+
required: true,
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
static description = 'destroy a logical replication publication on a Postgres Advanced database';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %> DATABASE --name orders --app example-app --confirm example-app',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
app: Flags.app({ required: true }),
|
|
20
|
+
confirm: Flags.string({ char: 'c', description: 'pass in the app name to skip confirmation prompts' }),
|
|
21
|
+
name: Flags.string({ description: 'name of publication', required: true }),
|
|
22
|
+
remote: Flags.remote(),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args, flags } = await this.parse(DataPgLogicalReplicationPublicationsDestroy);
|
|
26
|
+
const addon = await resolveAdvancedDatabase(this, args.database, flags.app);
|
|
27
|
+
await hux.confirmCommand({ comparison: flags.app, confirmation: flags.confirm });
|
|
28
|
+
try {
|
|
29
|
+
ux.action.start(`Destroying publication ${color.name(flags.name)} on ${color.datastore(addon.name)}`);
|
|
30
|
+
await this.dataApi.delete(`/data/postgres/v1/${addon.id}/logical-replication/publications/${encodeURIComponent(flags.name)}`);
|
|
31
|
+
ux.action.stop();
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
ux.action.stop(color.red('!'));
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
2
|
+
export default class DataPgLogicalReplicationPublicationsIndex extends BaseCommand {
|
|
3
|
+
static aliases: string[];
|
|
4
|
+
static args: {
|
|
5
|
+
database: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'no-wrap': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
remote: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { flags as Flags } from '@heroku-cli/command';
|
|
2
|
+
import { hux } from '@heroku/heroku-cli-util';
|
|
3
|
+
import { Args, ux } from '@oclif/core';
|
|
4
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
5
|
+
import { resolveAdvancedDatabase } from '../../../../../lib/data/logical-replication.js';
|
|
6
|
+
import { huxTableNoWrapOptions } from '../../../../../lib/utils/table-utils.js';
|
|
7
|
+
export default class DataPgLogicalReplicationPublicationsIndex extends BaseCommand {
|
|
8
|
+
static aliases = ['data:pg:lr:publications'];
|
|
9
|
+
static args = {
|
|
10
|
+
database: Args.string({
|
|
11
|
+
description: 'database name, database attachment name, or related config var on an app',
|
|
12
|
+
required: true,
|
|
13
|
+
}),
|
|
14
|
+
};
|
|
15
|
+
static description = 'list logical replication publications on a Postgres Advanced database';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> <%= command.id %> DATABASE --app example-app',
|
|
18
|
+
];
|
|
19
|
+
static flags = {
|
|
20
|
+
app: Flags.app({ required: true }),
|
|
21
|
+
'no-wrap': Flags.noWrap(),
|
|
22
|
+
remote: Flags.remote(),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args, flags } = await this.parse(DataPgLogicalReplicationPublicationsIndex);
|
|
26
|
+
const addon = await resolveAdvancedDatabase(this, args.database, flags.app);
|
|
27
|
+
const { body: { items } } = await this.dataApi.get(`/data/postgres/v1/${addon.id}/logical-replication/publications`);
|
|
28
|
+
if (items.length === 0) {
|
|
29
|
+
ux.stdout(`No logical replication publications exist on ${addon.name}.`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
hux.table(items, {
|
|
33
|
+
Name: { get: publication => publication.name },
|
|
34
|
+
'New Tables': { get: publication => publication.target.automatically_includes_new_tables ? 'Included' : 'Not Included' },
|
|
35
|
+
Owner: { get: publication => publication.owner },
|
|
36
|
+
Target: {
|
|
37
|
+
get: publication => publication.target.type === 'schemas'
|
|
38
|
+
? `schemas: ${publication.target.schemas.join(', ')}`
|
|
39
|
+
: `tables: ${publication.current_tables.join(', ')}`,
|
|
40
|
+
},
|
|
41
|
+
}, huxTableNoWrapOptions(flags['no-wrap']));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
2
|
+
export default class DataPgLogicalReplicationPublicationsInfo extends BaseCommand {
|
|
3
|
+
static aliases: string[];
|
|
4
|
+
static args: {
|
|
5
|
+
database: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
remote: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { flags as Flags } from '@heroku-cli/command';
|
|
2
|
+
import { hux } from '@heroku/heroku-cli-util';
|
|
3
|
+
import { Args } from '@oclif/core';
|
|
4
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
5
|
+
import { resolveAdvancedDatabase } from '../../../../../lib/data/logical-replication.js';
|
|
6
|
+
export default class DataPgLogicalReplicationPublicationsInfo extends BaseCommand {
|
|
7
|
+
static aliases = ['data:pg:lr:publications:info'];
|
|
8
|
+
static args = {
|
|
9
|
+
database: Args.string({
|
|
10
|
+
description: 'database name, database attachment name, or related config var on an app',
|
|
11
|
+
required: true,
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
static description = 'show details of a logical replication publication on a Postgres Advanced database';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %> DATABASE --name orders --app example-app',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
app: Flags.app({ required: true }),
|
|
20
|
+
name: Flags.string({ description: 'name of publication', required: true }),
|
|
21
|
+
remote: Flags.remote(),
|
|
22
|
+
};
|
|
23
|
+
async run() {
|
|
24
|
+
const { args, flags } = await this.parse(DataPgLogicalReplicationPublicationsInfo);
|
|
25
|
+
const addon = await resolveAdvancedDatabase(this, args.database, flags.app);
|
|
26
|
+
const { body: publication } = await this.dataApi.get(`/data/postgres/v1/${addon.id}/logical-replication/publications/${encodeURIComponent(flags.name)}`);
|
|
27
|
+
const target = publication.target.type === 'schemas' ? publication.target.schemas.join(', ') : publication.current_tables.join(', ');
|
|
28
|
+
hux.styledObject({
|
|
29
|
+
'Current Tables': publication.current_tables.join(', '),
|
|
30
|
+
Name: publication.name,
|
|
31
|
+
'New Tables': publication.target.automatically_includes_new_tables ? 'Included' : 'Not Included',
|
|
32
|
+
Owner: publication.owner,
|
|
33
|
+
Target: `${publication.target.type}: ${target}`,
|
|
34
|
+
}, ['Name', 'Owner', 'Target', 'Current Tables', 'New Tables']);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
2
|
+
export default class DataPgLogicalReplicationPublicationsUpdate extends BaseCommand {
|
|
3
|
+
static aliases: string[];
|
|
4
|
+
static args: {
|
|
5
|
+
database: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
'all-schemas': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
remote: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
schema: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
table: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
private publicationTarget;
|
|
19
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { flags as Flags } from '@heroku-cli/command';
|
|
2
|
+
import { color } from '@heroku/heroku-cli-util';
|
|
3
|
+
import { Args, ux } from '@oclif/core';
|
|
4
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
5
|
+
import { resolveAdvancedDatabase } from '../../../../../lib/data/logical-replication.js';
|
|
6
|
+
export default class DataPgLogicalReplicationPublicationsUpdate extends BaseCommand {
|
|
7
|
+
static aliases = ['data:pg:lr:publications:update'];
|
|
8
|
+
static args = {
|
|
9
|
+
database: Args.string({
|
|
10
|
+
description: 'database name, database attachment name, or related config var on an app',
|
|
11
|
+
required: true,
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
static description = 'replace the target of a logical replication publication on a Postgres Advanced database';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %> DATABASE --name orders --table public.orders --app example-app',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> DATABASE --name application --schema public --app example-app',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> DATABASE --name application --all-schemas --app example-app',
|
|
19
|
+
];
|
|
20
|
+
static flags = {
|
|
21
|
+
'all-schemas': Flags.boolean({
|
|
22
|
+
description: 'include all current customer schemas',
|
|
23
|
+
exclusive: ['schema', 'table'],
|
|
24
|
+
}),
|
|
25
|
+
app: Flags.app({ required: true }),
|
|
26
|
+
name: Flags.string({ description: 'name of publication', required: true }),
|
|
27
|
+
remote: Flags.remote(),
|
|
28
|
+
schema: Flags.string({ description: 'schema to include, including new tables created in the schema', multiple: true }),
|
|
29
|
+
table: Flags.string({ description: 'fully qualified table to include', multiple: true }),
|
|
30
|
+
};
|
|
31
|
+
async run() {
|
|
32
|
+
const { args, flags } = await this.parse(DataPgLogicalReplicationPublicationsUpdate);
|
|
33
|
+
const addon = await resolveAdvancedDatabase(this, args.database, flags.app);
|
|
34
|
+
const target = this.publicationTarget(flags['all-schemas'], flags.table, flags.schema);
|
|
35
|
+
try {
|
|
36
|
+
ux.action.start(`Updating publication ${color.name(flags.name)} on ${color.datastore(addon.name)}`);
|
|
37
|
+
await this.dataApi.put(`/data/postgres/v1/${addon.id}/logical-replication/publications/${encodeURIComponent(flags.name)}`, { body: { target } });
|
|
38
|
+
ux.action.stop();
|
|
39
|
+
if (flags['all-schemas']) {
|
|
40
|
+
ux.stdout('The publication includes all current customer schemas. It doesn’t automatically add new tables or schemas created later.');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
ux.action.stop(color.red('!'));
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
publicationTarget(allSchemas, tables, schemas) {
|
|
49
|
+
if (allSchemas)
|
|
50
|
+
return { type: 'all_customer_schemas' };
|
|
51
|
+
if (tables && schemas) {
|
|
52
|
+
ux.error('You can only use either --table or --schema, not both.');
|
|
53
|
+
}
|
|
54
|
+
if (tables)
|
|
55
|
+
return { tables, type: 'tables' };
|
|
56
|
+
if (schemas)
|
|
57
|
+
return { schemas, type: 'schemas' };
|
|
58
|
+
ux.error('You must use --all-schemas, or either --table or --schema.');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import BaseCommand from '../../../../../lib/data/base-command.js';
|
|
2
|
+
export default class DataPgLogicalReplicationPublishingEnable extends BaseCommand {
|
|
3
|
+
static aliases: string[];
|
|
4
|
+
static args: {
|
|
5
|
+
database: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
app: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
remote: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|