@heroku/sdk 0.11.1 → 0.12.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/dist/core/create-client.d.ts +7 -2
- package/dist/core/create-client.js +5 -2
- package/dist/core/extend-resource.d.ts +52 -2
- package/dist/core/extend-resource.js +27 -0
- package/dist/core/extensions-proxy.js +51 -1
- package/dist/core/heroku-sdk.js +44 -1
- package/dist/core/with-signal.d.ts +19 -0
- package/dist/core/with-signal.js +20 -0
- package/dist/resources/data/database.js +19 -6
- package/dist/resources/data/internal/resolve-pg-database.js +4 -7
- package/dist/resources/data/maintenance.js +4 -1
- package/dist/resources/data/postgres-database.js +4 -1
- package/dist/resources/data/redis/resolve-by-app.js +2 -1
- package/dist/resources/data/redis/wait-for-ready.d.ts +1 -1
- package/dist/resources/data/redis/wait-for-ready.js +3 -2
- package/dist/resources/data/transfer/capture-and-wait.js +4 -1
- package/dist/resources/data/transfer/restore-and-wait.js +4 -1
- package/dist/resources/data/transfer/wait-for-transfer.js +8 -1
- package/dist/resources/data/transfer-schedule.js +10 -3
- package/dist/resources/extensions/platform.d.ts +3 -0
- package/dist/resources/extensions/platform.js +3 -0
- package/dist/resources/platform/account.d.ts +22 -0
- package/dist/resources/platform/account.js +34 -0
- package/dist/resources/platform/add-on/create-and-wait.js +5 -1
- package/dist/resources/platform/add-on/describe.js +5 -2
- package/dist/resources/platform/add-on/destroy-and-wait.js +2 -3
- package/dist/resources/platform/add-on/list-plans.js +8 -2
- package/dist/resources/platform/add-on/resolve.js +5 -1
- package/dist/resources/platform/add-on/upgrade.js +5 -2
- package/dist/resources/platform/add-on/wait-for-provisioning.js +4 -1
- package/dist/resources/platform/add-on-attachment/resolve.js +2 -3
- package/dist/resources/platform/app/create-and-setup.d.ts +3 -4
- package/dist/resources/platform/app/create-and-setup.js +5 -5
- package/dist/resources/platform/app/diff.js +2 -3
- package/dist/resources/platform/app/index.js +9 -3
- package/dist/resources/platform/app/info.d.ts +4 -0
- package/dist/resources/platform/app/info.js +21 -7
- package/dist/resources/platform/app/transfer.js +2 -1
- package/dist/resources/platform/app/wait-for-acm-certificates.js +2 -1
- package/dist/resources/platform/container/ensure-container-stack.js +2 -1
- package/dist/resources/platform/container/release-images.js +2 -1
- package/dist/resources/platform/container/remove-process-types.js +2 -1
- package/dist/resources/platform/delinquency.d.ts +23 -0
- package/dist/resources/platform/delinquency.js +41 -0
- package/dist/resources/platform/domain/clear-custom-domains.js +2 -1
- package/dist/resources/platform/domain/create-and-wait.js +2 -1
- package/dist/resources/platform/domain/wait-for-ready.js +2 -1
- package/dist/resources/platform/dyno/exec.d.ts +12 -2
- package/dist/resources/platform/dyno/exec.js +27 -12
- package/dist/resources/platform/dyno/index.js +9 -6
- package/dist/resources/platform/dyno/list-extended.d.ts +7 -1
- package/dist/resources/platform/dyno/list-extended.js +8 -3
- package/dist/resources/platform/dyno/run.d.ts +1 -1
- package/dist/resources/platform/dyno/run.js +5 -3
- package/dist/resources/platform/dyno/wait-for-info.js +2 -1
- package/dist/resources/platform/dyno/wait-for-release.js +2 -1
- package/dist/resources/platform/log-session/index.d.ts +1 -1
- package/dist/resources/platform/log-session/index.js +12 -11
- package/dist/resources/platform/pipeline/coupling.js +5 -2
- package/dist/resources/platform/pipeline/index.d.ts +2 -2
- package/dist/resources/platform/pipeline/index.js +6 -4
- package/dist/resources/platform/pipeline/promotion.d.ts +1 -1
- package/dist/resources/platform/pipeline/promotion.js +22 -18
- package/dist/resources/platform/review-app-config/resolve-repo-name.js +4 -3
- package/dist/resources/platform/sni-endpoint/create-and-associate.js +2 -1
- package/dist/resources/platform/space/wait-for-allocated.js +2 -4
- package/dist/resources/platform/team.d.ts +22 -0
- package/dist/resources/platform/team.js +34 -0
- package/dist/resources/platform/telemetry-drain/remove-drains-for-target.js +2 -1
- package/dist/resources/platform/test-run/wait-for-state.js +2 -1
- package/dist/resources/platform/vpn-connection/wait-for-active.js +2 -1
- package/dist/utils/is-abort-error.d.ts +11 -0
- package/dist/utils/is-abort-error.js +14 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +2 -0
- package/package.json +9 -4
|
@@ -7,7 +7,7 @@ type RoutesModule = Record<string, Record<string, RouteDefinition>>;
|
|
|
7
7
|
* and `stream` are deliberately excluded — those belong on the
|
|
8
8
|
* individual route call, not on the client wrapper.
|
|
9
9
|
*/
|
|
10
|
-
export type StickyRouteOptions = Pick<RequestOptions, 'headers' | 'signal' | 'timeout'> & {
|
|
10
|
+
export type StickyRouteOptions = Pick<RequestOptions, 'headers' | 'reauthorize' | 'signal' | 'timeout'> & {
|
|
11
11
|
/**
|
|
12
12
|
* Request body applied to write calls on the derived client. Primarily
|
|
13
13
|
* for methods whose route metadata lacks `hasRequestBody` (e.g. DELETE
|
|
@@ -30,7 +30,12 @@ export type RoutesClientExtras<T> = {
|
|
|
30
30
|
* Returns a same-shaped client where each route call applies the
|
|
31
31
|
* provided options. Caller-supplied headers override the api-client's
|
|
32
32
|
* defaults; subsequent `withOptions` calls layer headers and replace
|
|
33
|
-
* signal / timeout.
|
|
33
|
+
* signal / timeout / reauthorize.
|
|
34
|
+
*
|
|
35
|
+
* Pass `reauthorize: false` to opt the derived client's calls out of the
|
|
36
|
+
* client-level 401 refresh (see {@link RequestOptions.reauthorize}) — for
|
|
37
|
+
* call sites where a 401 means something other than an expired Heroku
|
|
38
|
+
* credential and must not drive a login.
|
|
34
39
|
*
|
|
35
40
|
* The original client is not mutated.
|
|
36
41
|
*/
|
|
@@ -11,12 +11,15 @@ function mergeStickyOptions(base, next) {
|
|
|
11
11
|
if (next.headers || base?.headers) {
|
|
12
12
|
merged.headers = { ...base?.headers, ...next.headers };
|
|
13
13
|
}
|
|
14
|
-
// signal, timeout, and body are not additive — last wins,
|
|
15
|
-
// the caller actually set them. Otherwise the previous value
|
|
14
|
+
// signal, timeout, reauthorize, and body are not additive — last wins,
|
|
15
|
+
// but only if the caller actually set them. Otherwise the previous value
|
|
16
|
+
// persists.
|
|
16
17
|
if (next.signal !== undefined)
|
|
17
18
|
merged.signal = next.signal;
|
|
18
19
|
if (next.timeout !== undefined)
|
|
19
20
|
merged.timeout = next.timeout;
|
|
21
|
+
if (next.reauthorize !== undefined)
|
|
22
|
+
merged.reauthorize = next.reauthorize;
|
|
20
23
|
if (next.body !== undefined)
|
|
21
24
|
merged.body = next.body;
|
|
22
25
|
return merged;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { HerokuApiClientOptions } from '@heroku/heroku-fetch';
|
|
2
|
+
import { HerokuApiClient } from '@heroku/heroku-fetch';
|
|
1
3
|
import type { DashboardBackendClient } from '../services/dashboard-backend.js';
|
|
2
4
|
import type { DataClient } from '../services/data.js';
|
|
3
5
|
import type { MetricsClient } from '../services/metrics.js';
|
|
@@ -14,10 +16,58 @@ type BaseResourceCtx = {
|
|
|
14
16
|
platform: PlatformClient;
|
|
15
17
|
repositories: RepositoriesClient;
|
|
16
18
|
};
|
|
17
|
-
export type ResourceCtx =
|
|
19
|
+
export type ResourceCtx = {
|
|
20
|
+
/**
|
|
21
|
+
* Build a raw {@link HerokuApiClient} that inherits the SDK's resolved
|
|
22
|
+
* client options for the `inheritFrom` service bundle (token,
|
|
23
|
+
* `userAgent`/headers, `signal`, `timeout`, `warn`, …), with `overrides`
|
|
24
|
+
* applied last.
|
|
25
|
+
*
|
|
26
|
+
* `inheritFrom` selects *which resolved option bundle to start from* — not
|
|
27
|
+
* the wire service; pass `service` in `overrides` to redirect the client to
|
|
28
|
+
* a different host and auth behavior. The returned client is raw, NOT the
|
|
29
|
+
* managed service client: it does not carry that client's `defaultAccept`
|
|
30
|
+
* (e.g. the platform's `version=3.sdk`) or routes proxy, so callers issue
|
|
31
|
+
* `get`/`post`/`stream` directly and set `Accept` per call.
|
|
32
|
+
*
|
|
33
|
+
* When `overrides.service === 'custom'` the inherited bundle is narrowed to
|
|
34
|
+
* identity and cancellation only (never auth/routing), so a custom stream
|
|
35
|
+
* host can't receive the Heroku token, a `reauthorize` login callback, or
|
|
36
|
+
* consumer headers. Prefer {@link makeCustomHostClient} for that case rather
|
|
37
|
+
* than assembling the overrides by hand.
|
|
38
|
+
*
|
|
39
|
+
* Optional for compatibility with existing extension contexts; prefer
|
|
40
|
+
* {@link makeCtxClient} at call sites so a context predating this stays
|
|
41
|
+
* on the pre-threading behavior.
|
|
42
|
+
*
|
|
43
|
+
* TODO(next major): make this required on ResourceCtx and drop the
|
|
44
|
+
* {@link makeCtxClient} fallback once external hand-built contexts are no
|
|
45
|
+
* longer supported.
|
|
46
|
+
*/
|
|
47
|
+
makeClient?: (inheritFrom: ServiceName, overrides?: HerokuApiClientOptions) => HerokuApiClient;
|
|
18
48
|
/** Available to SDK-provided extensions; optional for compatibility with existing extension contexts. */
|
|
19
49
|
repositoriesApi?: RepositoriesApiClient;
|
|
20
|
-
};
|
|
50
|
+
} & BaseResourceCtx;
|
|
51
|
+
/**
|
|
52
|
+
* Build a raw {@link HerokuApiClient} from a resource context, inheriting the
|
|
53
|
+
* SDK's resolved client options for the `inheritFrom` service bundle
|
|
54
|
+
* (identity, `signal`, `warn`, token, …) with `overrides` applied last. Falls
|
|
55
|
+
* back to a bare client carrying only `overrides` when the context predates
|
|
56
|
+
* {@link ResourceCtx.makeClient} (e.g. a hand-built test ctx, or a standalone
|
|
57
|
+
* call with no SDK behind it), preserving the pre-threading behavior exactly.
|
|
58
|
+
*/
|
|
59
|
+
export declare function makeCtxClient(ctx: Pick<ResourceCtx, 'makeClient'>, inheritFrom: ServiceName, overrides?: HerokuApiClientOptions): HerokuApiClient;
|
|
60
|
+
/**
|
|
61
|
+
* Build a raw {@link HerokuApiClient} for a non-Heroku-credential host — a
|
|
62
|
+
* custom stream/API host the routes-generated clients don't cover (logplex,
|
|
63
|
+
* busl, exec-manager). Inherits only the SDK's identity and cancellation from
|
|
64
|
+
* the platform option bundle; forces `service: 'custom'`, the given `baseUrl`,
|
|
65
|
+
* and an empty `token`, and drops every auth/routing option (`reauthorize`,
|
|
66
|
+
* `headers`, `hooks`, `twoFactor`, `region`, …) so none crosses to the
|
|
67
|
+
* third-party origin. `overrides` the call site explicitly sets still apply —
|
|
68
|
+
* use them for a per-host header or timeout, not to smuggle inherited auth.
|
|
69
|
+
*/
|
|
70
|
+
export declare function makeCustomHostClient(ctx: Pick<ResourceCtx, 'makeClient'>, baseUrl: string, overrides?: Omit<HerokuApiClientOptions, 'baseUrl' | 'service' | 'token'>): HerokuApiClient;
|
|
21
71
|
export type ResourceMethods = Record<string, (...args: any[]) => any>;
|
|
22
72
|
export type ResourceExtension<S extends ServiceName = ServiceName, R extends string = string, M extends ResourceMethods = ResourceMethods> = {
|
|
23
73
|
factory: (ctx: ResourceCtx) => M;
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
import { HerokuApiClient } from '@heroku/heroku-fetch';
|
|
2
|
+
/**
|
|
3
|
+
* Build a raw {@link HerokuApiClient} from a resource context, inheriting the
|
|
4
|
+
* SDK's resolved client options for the `inheritFrom` service bundle
|
|
5
|
+
* (identity, `signal`, `warn`, token, …) with `overrides` applied last. Falls
|
|
6
|
+
* back to a bare client carrying only `overrides` when the context predates
|
|
7
|
+
* {@link ResourceCtx.makeClient} (e.g. a hand-built test ctx, or a standalone
|
|
8
|
+
* call with no SDK behind it), preserving the pre-threading behavior exactly.
|
|
9
|
+
*/
|
|
10
|
+
export function makeCtxClient(ctx, inheritFrom, overrides = {}) {
|
|
11
|
+
return ctx.makeClient ? ctx.makeClient(inheritFrom, overrides) : new HerokuApiClient(overrides);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build a raw {@link HerokuApiClient} for a non-Heroku-credential host — a
|
|
15
|
+
* custom stream/API host the routes-generated clients don't cover (logplex,
|
|
16
|
+
* busl, exec-manager). Inherits only the SDK's identity and cancellation from
|
|
17
|
+
* the platform option bundle; forces `service: 'custom'`, the given `baseUrl`,
|
|
18
|
+
* and an empty `token`, and drops every auth/routing option (`reauthorize`,
|
|
19
|
+
* `headers`, `hooks`, `twoFactor`, `region`, …) so none crosses to the
|
|
20
|
+
* third-party origin. `overrides` the call site explicitly sets still apply —
|
|
21
|
+
* use them for a per-host header or timeout, not to smuggle inherited auth.
|
|
22
|
+
*/
|
|
23
|
+
export function makeCustomHostClient(ctx, baseUrl, overrides = {}) {
|
|
24
|
+
return makeCtxClient(ctx, 'platform', {
|
|
25
|
+
...overrides, baseUrl, service: 'custom', token: '',
|
|
26
|
+
});
|
|
27
|
+
}
|
|
1
28
|
export function extendResource(service, resource, factory) {
|
|
2
29
|
return { factory, resource, service };
|
|
3
30
|
}
|
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
import createDebug from 'debug';
|
|
2
2
|
const debug = createDebug('heroku:sdk:extensions');
|
|
3
|
+
/**
|
|
4
|
+
* Re-derive the extension context so that an operation-wide cancellation set
|
|
5
|
+
* via `sdk.platform.withOptions({signal})` also reaches the clients its
|
|
6
|
+
* extensions issue requests through `ctx`.
|
|
7
|
+
*
|
|
8
|
+
* Extension factories close over `ctx.*` (e.g. `ctx.platform`) to issue their
|
|
9
|
+
* own — often nested, sometimes cross-service — requests. Without this, a signal
|
|
10
|
+
* set on a service client would reach generated route methods but never the
|
|
11
|
+
* requests an extension method makes through `ctx`, so cancellation could not
|
|
12
|
+
* stop the work an extension started. The derivation is applied to *every*
|
|
13
|
+
* service client in `ctx` because cancellation is operation-wide and extensions
|
|
14
|
+
* cross services (e.g. a `data` extension polls through `ctx.platform`).
|
|
15
|
+
*
|
|
16
|
+
* Only the operation-wide `signal` / `timeout` are propagated. A `withHeaders`
|
|
17
|
+
* call, and the `headers` / `body` fields of a `withOptions` call, are
|
|
18
|
+
* endpoint-specific and must not ride cross-service onto unrelated requests
|
|
19
|
+
* (e.g. an `Accept-Expansion` header a sibling endpoint rejects), so they stay
|
|
20
|
+
* on the routes client the caller scoped and are not re-derived here.
|
|
21
|
+
*
|
|
22
|
+
* `withOptions` returns a fresh client without mutating the original, and the
|
|
23
|
+
* derived clients are memoized per key, so sibling derived clients — and the
|
|
24
|
+
* base client — stay isolated from one another.
|
|
25
|
+
*/
|
|
26
|
+
function deriveCtx(ctx, method, args) {
|
|
27
|
+
if (method !== 'withOptions')
|
|
28
|
+
return ctx;
|
|
29
|
+
const options = args[0];
|
|
30
|
+
const scoped = {};
|
|
31
|
+
if (options?.signal !== undefined)
|
|
32
|
+
scoped.signal = options.signal;
|
|
33
|
+
if (options?.timeout !== undefined)
|
|
34
|
+
scoped.timeout = options.timeout;
|
|
35
|
+
if (Object.keys(scoped).length === 0)
|
|
36
|
+
return ctx;
|
|
37
|
+
const cache = new Map();
|
|
38
|
+
const derived = {};
|
|
39
|
+
for (const key of Object.keys(ctx)) {
|
|
40
|
+
Object.defineProperty(derived, key, {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get() {
|
|
43
|
+
if (!cache.has(key)) {
|
|
44
|
+
const client = ctx[key];
|
|
45
|
+
cache.set(key, typeof client?.withOptions === 'function' ? client.withOptions(scoped) : client);
|
|
46
|
+
}
|
|
47
|
+
return cache.get(key);
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return derived;
|
|
52
|
+
}
|
|
3
53
|
export function mergeExtensions(client, extensions, ctx) {
|
|
4
54
|
const methodsByResource = new Map();
|
|
5
55
|
for (const ext of extensions) {
|
|
@@ -34,7 +84,7 @@ export function mergeExtensions(client, extensions, ctx) {
|
|
|
34
84
|
}
|
|
35
85
|
return (...args) => {
|
|
36
86
|
const rewrapped = inner.apply(target, args);
|
|
37
|
-
return mergeExtensions(rewrapped, extensions, ctx);
|
|
87
|
+
return mergeExtensions(rewrapped, extensions, deriveCtx(ctx, resourceKey, args));
|
|
38
88
|
};
|
|
39
89
|
}
|
|
40
90
|
const extMethods = methodsByResource.get(resourceKey);
|
package/dist/core/heroku-sdk.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HerokuApiClient } from '@heroku/heroku-fetch';
|
|
1
2
|
import { createDashboardBackendClient } from '../services/dashboard-backend.js';
|
|
2
3
|
import { createDataClient } from '../services/data.js';
|
|
3
4
|
import { createMetricsClient } from '../services/metrics.js';
|
|
@@ -5,7 +6,17 @@ import { createNotificationsClient } from '../services/notifications.js';
|
|
|
5
6
|
import { createPlatformClient } from '../services/platform.js';
|
|
6
7
|
import { createRepositoriesApiClient } from '../services/repositories-api.js';
|
|
7
8
|
import { createRepositoriesClient } from '../services/repositories.js';
|
|
9
|
+
import { SDK_VERSION } from '../version.js';
|
|
8
10
|
import { mergeExtensions } from './extensions-proxy.js';
|
|
11
|
+
/**
|
|
12
|
+
* Default `User-Agent` identity for SDK-originated traffic. {@link HerokuSDK}
|
|
13
|
+
* applies it as a fill-if-absent default on every service client (in its
|
|
14
|
+
* `#getClientOptions` merge), so requests the SDK drives stay identifiable even
|
|
15
|
+
* when the consumer passes no `userAgent`. A consumer-supplied
|
|
16
|
+
* `clientOptions.userAgent` — or a per-service override — wins. The version is
|
|
17
|
+
* stamped from package.json at build time; see `src/version.ts`.
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_USER_AGENT = { name: '@heroku/sdk', version: SDK_VERSION };
|
|
9
20
|
function partitionByService(extensions) {
|
|
10
21
|
const map = new Map();
|
|
11
22
|
for (const ext of extensions) {
|
|
@@ -15,6 +26,26 @@ function partitionByService(extensions) {
|
|
|
15
26
|
}
|
|
16
27
|
return map;
|
|
17
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* The options a custom-host client (`service: 'custom'`) inherits from the
|
|
31
|
+
* SDK's resolved bundle: identity and cancellation only. Every
|
|
32
|
+
* Heroku-credential-domain option — auth (`token`, `reauthorize`, `twoFactor`),
|
|
33
|
+
* routing (`headers`, `region`, `defaultAccept`), and consumer
|
|
34
|
+
* `hooks`/`onResponseMetadata` — is intentionally dropped so it never reaches a
|
|
35
|
+
* third-party origin (logplex, busl, exec-manager): sending the bearer token or
|
|
36
|
+
* a consumer `Authorization` header cross-origin would leak credentials, and
|
|
37
|
+
* inheriting `reauthorize` would turn a non-Heroku 401 into a spurious
|
|
38
|
+
* `heroku login`.
|
|
39
|
+
*/
|
|
40
|
+
function pickCustomHostOptions(options) {
|
|
41
|
+
return {
|
|
42
|
+
...(options.debug !== undefined && { debug: options.debug }),
|
|
43
|
+
...(options.signal !== undefined && { signal: options.signal }),
|
|
44
|
+
...(options.timeout !== undefined && { timeout: options.timeout }),
|
|
45
|
+
...(options.userAgent !== undefined && { userAgent: options.userAgent }),
|
|
46
|
+
...(options.warn !== undefined && { warn: options.warn }),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
18
49
|
export class HerokuSDK {
|
|
19
50
|
#clientOptions;
|
|
20
51
|
#clientOptionsByService;
|
|
@@ -72,6 +103,7 @@ export class HerokuSDK {
|
|
|
72
103
|
const serviceOptions = { ...serviceOverride };
|
|
73
104
|
delete serviceOptions.service;
|
|
74
105
|
return {
|
|
106
|
+
userAgent: DEFAULT_USER_AGENT,
|
|
75
107
|
...this.#clientOptions,
|
|
76
108
|
...serviceOptions,
|
|
77
109
|
};
|
|
@@ -86,6 +118,17 @@ export class HerokuSDK {
|
|
|
86
118
|
enumerable: true,
|
|
87
119
|
get: () => this.#getRawData(),
|
|
88
120
|
},
|
|
121
|
+
makeClient: {
|
|
122
|
+
enumerable: true,
|
|
123
|
+
value: (inheritFrom, overrides = {}) => {
|
|
124
|
+
const resolved = this.#getClientOptions(inheritFrom);
|
|
125
|
+
// A custom host is not the Heroku credential domain: start from
|
|
126
|
+
// identity/cancellation only, never the auth/routing options that
|
|
127
|
+
// would leak across origins or drive a re-login on a foreign 401.
|
|
128
|
+
const base = overrides.service === 'custom' ? pickCustomHostOptions(resolved) : resolved;
|
|
129
|
+
return new HerokuApiClient({ ...base, ...overrides });
|
|
130
|
+
},
|
|
131
|
+
},
|
|
89
132
|
metrics: {
|
|
90
133
|
enumerable: true,
|
|
91
134
|
get: () => this.#getRawMetrics(),
|
|
@@ -122,7 +165,7 @@ export class HerokuSDK {
|
|
|
122
165
|
return this.#rawMetrics;
|
|
123
166
|
}
|
|
124
167
|
#getRawNotifications() {
|
|
125
|
-
this.#rawNotifications ??= createNotificationsClient(this.#
|
|
168
|
+
this.#rawNotifications ??= createNotificationsClient(this.#getClientOptions('notifications'));
|
|
126
169
|
return this.#rawNotifications;
|
|
127
170
|
}
|
|
128
171
|
#getRawPlatform() {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RoutesClientExtras } from './create-client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Bind a cancellation signal to a routes client so the requests it issues
|
|
4
|
+
* abort in flight.
|
|
5
|
+
*
|
|
6
|
+
* Extension methods receive their signal as a per-call option (e.g.
|
|
7
|
+
* `addOn.createAndWait(app, body, {signal})`) rather than through the client,
|
|
8
|
+
* so the signal reaches `wait()`/`throwIfAborted()` checkpoints but not the
|
|
9
|
+
* in-flight request unless it's pushed onto the client. This returns a derived,
|
|
10
|
+
* signal-bearing client (the original is never mutated) — or the client
|
|
11
|
+
* unchanged when no signal is supplied, so a signal-less call stays a no-op.
|
|
12
|
+
*
|
|
13
|
+
* Signals do not combine: `withOptions` is last-wins, so binding a per-call
|
|
14
|
+
* signal here replaces any signal already set on the client (e.g. a
|
|
15
|
+
* session-level one) for the requests this derived client issues. A caller that
|
|
16
|
+
* needs both to abort the request must combine them itself (e.g.
|
|
17
|
+
* `AbortSignal.any([sessionSignal, callSignal])`) before passing one in.
|
|
18
|
+
*/
|
|
19
|
+
export declare function withSignal<T>(client: RoutesClientExtras<T> & T, signal?: AbortSignal): RoutesClientExtras<T> & T;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bind a cancellation signal to a routes client so the requests it issues
|
|
3
|
+
* abort in flight.
|
|
4
|
+
*
|
|
5
|
+
* Extension methods receive their signal as a per-call option (e.g.
|
|
6
|
+
* `addOn.createAndWait(app, body, {signal})`) rather than through the client,
|
|
7
|
+
* so the signal reaches `wait()`/`throwIfAborted()` checkpoints but not the
|
|
8
|
+
* in-flight request unless it's pushed onto the client. This returns a derived,
|
|
9
|
+
* signal-bearing client (the original is never mutated) — or the client
|
|
10
|
+
* unchanged when no signal is supplied, so a signal-less call stays a no-op.
|
|
11
|
+
*
|
|
12
|
+
* Signals do not combine: `withOptions` is last-wins, so binding a per-call
|
|
13
|
+
* signal here replaces any signal already set on the client (e.g. a
|
|
14
|
+
* session-level one) for the requests this derived client issues. A caller that
|
|
15
|
+
* needs both to abort the request must combine them itself (e.g.
|
|
16
|
+
* `AbortSignal.any([sessionSignal, callSignal])`) before passing one in.
|
|
17
|
+
*/
|
|
18
|
+
export function withSignal(client, signal) {
|
|
19
|
+
return signal ? client.withOptions({ signal }) : client;
|
|
20
|
+
}
|
|
@@ -1,34 +1,47 @@
|
|
|
1
1
|
import { extendResource } from '../../core/extend-resource.js';
|
|
2
|
+
import { withSignal } from '../../core/with-signal.js';
|
|
2
3
|
import { resolvePgDatabase } from './internal/resolve-pg-database.js';
|
|
3
4
|
export async function describe(ctx, appIdentity, addonIdentity, options = {}) {
|
|
4
5
|
options.signal?.throwIfAborted();
|
|
5
6
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
6
|
-
|
|
7
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
8
|
+
const data = withSignal(ctx.data, options.signal);
|
|
9
|
+
return data.database.info(addon.id);
|
|
7
10
|
}
|
|
8
11
|
export async function upgradeWaitStatus(ctx, appIdentity, addonIdentity, options = {}) {
|
|
9
12
|
options.signal?.throwIfAborted();
|
|
10
13
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
11
|
-
|
|
14
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
15
|
+
const data = withSignal(ctx.data, options.signal);
|
|
16
|
+
return data.database.upgradeWaitStatus(addon.id);
|
|
12
17
|
}
|
|
13
18
|
export async function dryRunUpgrade(ctx, appIdentity, addonIdentity, body = {}, options = {}) {
|
|
14
19
|
options.signal?.throwIfAborted();
|
|
15
20
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
16
|
-
|
|
21
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
22
|
+
const data = withSignal(ctx.data, options.signal);
|
|
23
|
+
return data.database.dryRunUpgrade(addon.id, body);
|
|
17
24
|
}
|
|
18
25
|
export async function runUpgrade(ctx, appIdentity, addonIdentity, body = {}, options = {}) {
|
|
19
26
|
options.signal?.throwIfAborted();
|
|
20
27
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
21
|
-
|
|
28
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
29
|
+
const data = withSignal(ctx.data, options.signal);
|
|
30
|
+
return data.database.runUpgrade(addon.id, body);
|
|
22
31
|
}
|
|
23
32
|
export async function prepareUpgrade(ctx, appIdentity, addonIdentity, body = {}, options = {}) {
|
|
24
33
|
options.signal?.throwIfAborted();
|
|
25
34
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
26
|
-
|
|
35
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
36
|
+
const data = withSignal(ctx.data, options.signal);
|
|
37
|
+
return data.database.prepareUpgrade(addon.id, body);
|
|
27
38
|
}
|
|
28
39
|
export async function cancelUpgrade(ctx, appIdentity, addonIdentity, options = {}) {
|
|
29
40
|
options.signal?.throwIfAborted();
|
|
30
41
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
31
|
-
|
|
42
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
43
|
+
const data = withSignal(ctx.data, options.signal);
|
|
44
|
+
return data.database.cancelUpgrade(addon.id);
|
|
32
45
|
}
|
|
33
46
|
export const databaseExtensions = extendResource('data', 'database', ctx => ({
|
|
34
47
|
cancelUpgrade: (appIdentity, addonIdentity, options) => cancelUpgrade(ctx, appIdentity, addonIdentity, options),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NotFoundError } from '@heroku/heroku-fetch';
|
|
2
2
|
import createDebug from 'debug';
|
|
3
|
+
import { withSignal } from '../../../core/with-signal.js';
|
|
3
4
|
import { AddonAttachmentAmbiguousError, AddonAttachmentNotFoundError, resolveAddonAttachment } from '../../platform/add-on-attachment/resolve.js';
|
|
4
5
|
import { getPostgresServiceName, isPostgresAddonInternal } from './postgres-utils.js';
|
|
5
6
|
const debug = createDebug('heroku:sdk:resources:database');
|
|
@@ -87,8 +88,7 @@ async function equivalentAttachment(ctx, matches, error, signal) {
|
|
|
87
88
|
*/
|
|
88
89
|
async function listAppConfigVars(ctx, appIdentity, error, signal) {
|
|
89
90
|
try {
|
|
90
|
-
return await ctx.platform
|
|
91
|
-
.withOptions({ signal })
|
|
91
|
+
return await withSignal(ctx.platform, signal)
|
|
92
92
|
.configVar.infoForApp(appIdentity);
|
|
93
93
|
}
|
|
94
94
|
catch (configVarError) {
|
|
@@ -101,14 +101,11 @@ async function listAppConfigVars(ctx, appIdentity, error, signal) {
|
|
|
101
101
|
* Used by `attachmentResolutionFallback` to list all attachments on an app that match the
|
|
102
102
|
* add-on service filter. Throws `PgDatabaseNotFoundError` if the app does not exist
|
|
103
103
|
* or the listing fails for any other reason.
|
|
104
|
-
*/
|
|
104
|
+
*/
|
|
105
105
|
async function listPostgresAttachments(ctx, appIdentity, attachmentId, error, signal) {
|
|
106
106
|
let attachments;
|
|
107
107
|
try {
|
|
108
|
-
attachments = await ctx.platform
|
|
109
|
-
.withHeaders({ 'Accept-Inclusion': 'addon:plan,config_vars' })
|
|
110
|
-
.withOptions({ signal })
|
|
111
|
-
.addOnAttachment.listByApp(appIdentity);
|
|
108
|
+
attachments = await withSignal(ctx.platform.withHeaders({ 'Accept-Inclusion': 'addon:plan,config_vars' }), signal).addOnAttachment.listByApp(appIdentity);
|
|
112
109
|
}
|
|
113
110
|
catch (listError) {
|
|
114
111
|
signal?.throwIfAborted();
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { extendResource } from '../../core/extend-resource.js';
|
|
2
|
+
import { withSignal } from '../../core/with-signal.js';
|
|
2
3
|
import { resolvePgDatabase } from './internal/resolve-pg-database.js';
|
|
3
4
|
export async function info(ctx, appIdentity, addonIdentity, options = {}) {
|
|
4
5
|
options.signal?.throwIfAborted();
|
|
5
6
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
6
|
-
|
|
7
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
8
|
+
const data = withSignal(ctx.data, options.signal);
|
|
9
|
+
return data.maintenance.info(addon.id);
|
|
7
10
|
}
|
|
8
11
|
export const maintenanceExtensions = extendResource('data', 'maintenance', ctx => ({
|
|
9
12
|
info: (appIdentity, addonIdentity, options) => info(ctx, appIdentity, addonIdentity, options),
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { extendResource } from '../../core/extend-resource.js';
|
|
2
|
+
import { withSignal } from '../../core/with-signal.js';
|
|
2
3
|
import { resolvePgDatabase } from './internal/resolve-pg-database.js';
|
|
3
4
|
export async function listCredentials(ctx, appIdentity, addonIdentity, options = {}) {
|
|
4
5
|
options.signal?.throwIfAborted();
|
|
5
6
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
6
|
-
|
|
7
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
8
|
+
const data = withSignal(ctx.data, options.signal);
|
|
9
|
+
return data.postgresDatabase.listCredentials(addon.id);
|
|
7
10
|
}
|
|
8
11
|
export const postgresDatabaseExtensions = extendResource('data', 'postgresDatabase', ctx => ({
|
|
9
12
|
listCredentials: (appIdentity, addonIdentity, options) => listCredentials(ctx, appIdentity, addonIdentity, options),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import createDebug from 'debug';
|
|
2
|
+
import { withSignal } from '../../../core/with-signal.js';
|
|
2
3
|
import { RedisAddonAmbiguousError, RedisAddonNotFoundError } from './errors.js';
|
|
3
4
|
const debug = createDebug('heroku:sdk:resources:redis');
|
|
4
5
|
const DEFAULT_REDIS_ADDON_SERVICE_PREFIX = 'heroku-redis';
|
|
@@ -19,7 +20,7 @@ const DEFAULT_REDIS_ADDON_SERVICE_PREFIX = 'heroku-redis';
|
|
|
19
20
|
export async function resolveRedisByApp(ctx, appIdentity, options = {}) {
|
|
20
21
|
options.signal?.throwIfAborted();
|
|
21
22
|
const { addonServiceName = DEFAULT_REDIS_ADDON_SERVICE_PREFIX, database } = options;
|
|
22
|
-
const platform =
|
|
23
|
+
const platform = withSignal(ctx.platform, options.signal);
|
|
23
24
|
debug('resolveByApp app=%s service-prefix=%s database=%s', appIdentity, addonServiceName, database ?? '<any>');
|
|
24
25
|
const addons = await platform.addOn.listByApp(appIdentity);
|
|
25
26
|
const filter = database?.toUpperCase();
|
|
@@ -26,7 +26,7 @@ export type WaitForRedisReadyOptions = {
|
|
|
26
26
|
* provision call resolves.
|
|
27
27
|
*
|
|
28
28
|
* Cancellation: the caller's `signal` is threaded into both the
|
|
29
|
-
* in-flight request (via `
|
|
29
|
+
* in-flight request (via `withSignal`) and the poll-delay `wait()`,
|
|
30
30
|
* so aborting takes effect during either phase.
|
|
31
31
|
*/
|
|
32
32
|
export declare function waitForRedisReady(ctx: Pick<ResourceCtx, 'data'>, nameOrId: string, options?: WaitForRedisReadyOptions): Promise<RedisWaitResult>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NotFoundError } from '@heroku/heroku-fetch';
|
|
2
2
|
import createDebug from 'debug';
|
|
3
|
+
import { withSignal } from '../../../core/with-signal.js';
|
|
3
4
|
import { wait } from '../../../utils/wait.js';
|
|
4
5
|
const debug = createDebug('heroku:sdk:resources:redis');
|
|
5
6
|
const DEFAULT_INTERVAL_MS = 5000;
|
|
@@ -13,13 +14,13 @@ const DEFAULT_INTERVAL_MS = 5000;
|
|
|
13
14
|
* provision call resolves.
|
|
14
15
|
*
|
|
15
16
|
* Cancellation: the caller's `signal` is threaded into both the
|
|
16
|
-
* in-flight request (via `
|
|
17
|
+
* in-flight request (via `withSignal`) and the poll-delay `wait()`,
|
|
17
18
|
* so aborting takes effect during either phase.
|
|
18
19
|
*/
|
|
19
20
|
export async function waitForRedisReady(ctx, nameOrId, options = {}) {
|
|
20
21
|
const { intervalMs = DEFAULT_INTERVAL_MS, signal, timeoutMs } = options;
|
|
21
22
|
signal?.throwIfAborted();
|
|
22
|
-
const data =
|
|
23
|
+
const data = withSignal(ctx.data, signal);
|
|
23
24
|
const deadline = timeoutMs === undefined ? undefined : Date.now() + timeoutMs;
|
|
24
25
|
debug('waitForReady name=%s intervalMs=%d timeoutMs=%s', nameOrId, intervalMs, timeoutMs ?? '<none>');
|
|
25
26
|
while (true) {
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { withSignal } from '../../../core/with-signal.js';
|
|
1
2
|
import { resolvePgDatabase } from '../internal/resolve-pg-database.js';
|
|
2
3
|
import { waitForTransfer } from './wait-for-transfer.js';
|
|
3
4
|
export async function captureAndWait(ctx, appIdentity, addonIdentity, options = {}) {
|
|
4
5
|
const { capturePoller, signal, waitPoller } = options;
|
|
5
6
|
signal?.throwIfAborted();
|
|
6
7
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
8
|
+
// Bind the signal so the create request aborts in flight, not just the wait.
|
|
9
|
+
const data = withSignal(ctx.data, signal);
|
|
7
10
|
capturePoller?.onStart?.(addon);
|
|
8
|
-
const backup = await
|
|
11
|
+
const backup = await data.backup.create(addon.id);
|
|
9
12
|
capturePoller?.onStop?.(addon);
|
|
10
13
|
waitPoller?.onStart?.(backup);
|
|
11
14
|
const transfer = await waitForTransfer(ctx, addon.app.name, backup.uuid, options);
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import { withSignal } from '../../../core/with-signal.js';
|
|
1
2
|
import { resolvePgDatabase } from '../internal/resolve-pg-database.js';
|
|
2
3
|
import { waitForTransfer } from './wait-for-transfer.js';
|
|
3
4
|
export async function restoreAndWait(ctx, appIdentity, addonIdentity, backupUrl, options = {}) {
|
|
4
5
|
const { extensions, restorePoller, signal, waitPoller } = options;
|
|
5
6
|
signal?.throwIfAborted();
|
|
6
7
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
8
|
+
// Bind the signal so the create request aborts in flight, not just the wait.
|
|
9
|
+
const data = withSignal(ctx.data, signal);
|
|
7
10
|
restorePoller?.onStart?.(addon);
|
|
8
11
|
// eslint-disable-next-line camelcase
|
|
9
|
-
const restore = await
|
|
12
|
+
const restore = await data.restore.create(addon.id, { backup_url: backupUrl, extensions });
|
|
10
13
|
restorePoller?.onStop?.(addon);
|
|
11
14
|
waitPoller?.onStart?.(restore);
|
|
12
15
|
const transfer = await waitForTransfer(ctx, addon.app.name, restore.uuid, options);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { extendResource } from '../../../core/extend-resource.js';
|
|
2
|
+
import { withSignal } from '../../../core/with-signal.js';
|
|
3
|
+
import { isAbortError } from '../../../utils/is-abort-error.js';
|
|
2
4
|
import { wait } from '../../../utils/wait.js';
|
|
3
5
|
const DEFAULT_INTERVAL_MS = 3000;
|
|
4
6
|
const MAX_FAILURES = 20;
|
|
@@ -46,7 +48,7 @@ export class TransferTimeoutError extends Error {
|
|
|
46
48
|
export async function waitForTransfer(ctx, appIdentity, transferId, options = {}) {
|
|
47
49
|
const { intervalMs = DEFAULT_INTERVAL_MS, onPoll, signal, timeoutMs, verbose, } = options;
|
|
48
50
|
signal?.throwIfAborted();
|
|
49
|
-
const data =
|
|
51
|
+
const data = withSignal(ctx.data, signal);
|
|
50
52
|
const deadline = timeoutMs === undefined ? undefined : Date.now() + timeoutMs;
|
|
51
53
|
let failures = 0;
|
|
52
54
|
let transfer;
|
|
@@ -56,6 +58,11 @@ export async function waitForTransfer(ctx, appIdentity, transferId, options = {}
|
|
|
56
58
|
transfer = await data.transfer.infoByApp(appIdentity, transferId, { verbose });
|
|
57
59
|
}
|
|
58
60
|
catch (error) {
|
|
61
|
+
// Never retry a cancellation: a client- or caller-level abort must stop
|
|
62
|
+
// the poll immediately rather than burn up to MAX_FAILURES attempts.
|
|
63
|
+
if (signal?.aborted || isAbortError(error)) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
59
66
|
failures++;
|
|
60
67
|
if (failures > MAX_FAILURES) {
|
|
61
68
|
throw error;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { extendResource } from '../../core/extend-resource.js';
|
|
2
|
+
import { withSignal } from '../../core/with-signal.js';
|
|
2
3
|
import { findLegacyDatabase } from './internal/postgres-utils.js';
|
|
3
4
|
import { resolvePgDatabase } from './internal/resolve-pg-database.js';
|
|
4
5
|
export async function list(ctx, appIdentity, options = {}) {
|
|
5
6
|
options.signal?.throwIfAborted();
|
|
6
7
|
// Schedules are app-scoped, so any legacy DB ID unlocks the app's list.
|
|
7
8
|
const addon = await findLegacyDatabase(ctx, appIdentity);
|
|
8
|
-
|
|
9
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
10
|
+
const data = withSignal(ctx.data, options.signal);
|
|
11
|
+
return data.transferSchedule.list(addon.id);
|
|
9
12
|
}
|
|
10
13
|
export async function create(ctx, appIdentity, addonIdentity, body, options = {}) {
|
|
11
14
|
options.signal?.throwIfAborted();
|
|
@@ -17,12 +20,16 @@ export async function create(ctx, appIdentity, addonIdentity, body, options = {}
|
|
|
17
20
|
// eslint-disable-next-line camelcase
|
|
18
21
|
requestBody = { ...body, schedule_name: `${attachment.name}_URL` };
|
|
19
22
|
}
|
|
20
|
-
|
|
23
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
24
|
+
const data = withSignal(ctx.data, options.signal);
|
|
25
|
+
return data.transferSchedule.create(addon.id, requestBody);
|
|
21
26
|
}
|
|
22
27
|
export async function del(ctx, appIdentity, addonIdentity, scheduleId, options = {}) {
|
|
23
28
|
options.signal?.throwIfAborted();
|
|
24
29
|
const addon = await resolvePgDatabase(ctx, appIdentity, { input: addonIdentity, ...options });
|
|
25
|
-
|
|
30
|
+
// Bind the signal so the request aborts in flight, not just during resolution.
|
|
31
|
+
const data = withSignal(ctx.data, options.signal);
|
|
32
|
+
return data.transferSchedule.delete(addon.id, scheduleId);
|
|
26
33
|
}
|
|
27
34
|
export const transferScheduleExtensions = extendResource('data', 'transferSchedule', ctx => ({
|
|
28
35
|
create: (appIdentity, addonIdentity, body, options) => create(ctx, appIdentity, addonIdentity, body, options),
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
export { accountExtensions, type AccountWithDelinquency, type GetAccountWithDelinquencyOptions } from '../platform/account.js';
|
|
1
2
|
export { addOnAttachmentExtensions } from '../platform/add-on-attachment/index.js';
|
|
2
3
|
export { addOnExtensions } from '../platform/add-on/index.js';
|
|
3
4
|
export { appExtensions, type AppInfo, type DiffAppsOptions, type DiffRow, type PipelineCouplingDetail, } from '../platform/app/index.js';
|
|
4
5
|
export { containerExtensions, type DockerReleasesBatchUpdateOpts, NotAContainerAppError, type ReleaseDockerImagesResult, type RemoveProcessTypesOpts, } from '../platform/container/index.js';
|
|
6
|
+
export { type DelinquencyResource, type DelinquencySchedule, formatDelinquencyWarning, } from '../platform/delinquency.js';
|
|
5
7
|
export { type CreateAndWaitOptions, domainExtensions, type DomainOptions, type WaitForReadyOptions, } from '../platform/domain/index.js';
|
|
6
8
|
export { DynoCrashedError, type DynoExtended, type DynoExtendedFields, dynoExtensions, DynoNotReadyError, type DynoState, enableExec, exchangeExecCredentials, type ExchangeExecCredentialsOptions, type ExecCredentials, type ExecOptions, type ExecPrereqs, execPrereqs, type ExecReservation, execStatus, type ExecStatusOptions, listExtended, type ListExtendedOptions, restartForExec, type RestartForExecOptions, runDyno, type RunDynoOptions, waitForInfo, type WaitForInfoOptions, waitForRelease, type WaitForReleaseOptions, type WaitForReleaseProgress, type WaitForReleaseResult, } from '../platform/dyno/index.js';
|
|
7
9
|
export { type AttachmentAttachedEvent, type AttachmentDetachedEvent, type AttachmentUpdatedEvent, type HerokuLogEvent, logSessionExtensions, parseHerokuLogLine, type ProvisioningCompletedEvent, type ScaledToEntry, type ScaledToEvent, type StartingProcessEvent, type StateChangedEvent, } from '../platform/log-session/index.js';
|
|
@@ -12,6 +14,7 @@ export { type ResolveRepoNameOptions, reviewAppConfigExtensions } from '../platf
|
|
|
12
14
|
export { privateToShield, shieldToPrivate } from '../platform/shield.js';
|
|
13
15
|
export { createAndAssociate, type CreateAndAssociateOptions, sniEndpointExtensions } from '../platform/sni-endpoint/index.js';
|
|
14
16
|
export { spaceExtensions, SpaceNotAllocatedError, SpaceNotReadyError, type SpaceOptions, type SpaceWithNat, waitForAllocated, type WaitForAllocatedOptions, } from '../platform/space/index.js';
|
|
17
|
+
export { type GetTeamWithDelinquencyOptions, teamExtensions, type TeamWithDelinquency } from '../platform/team.js';
|
|
15
18
|
export { telemetryDrainExtensions, type TelemetryDrainOptions, type TelemetryDrainTarget } from '../platform/telemetry-drain/index.js';
|
|
16
19
|
export { testRunExtensions, TestRunNotReadyError, type TestRunStatus, waitForState, type WaitForStateOptions, } from '../platform/test-run/index.js';
|
|
17
20
|
export { vpnConnectionExtensions, VpnConnectionFailedError, VpnConnectionNotReadyError, type VpnConnectionOptions, waitForActive, type WaitForActiveOptions, } from '../platform/vpn-connection/index.js';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
export { accountExtensions } from '../platform/account.js';
|
|
1
2
|
export { addOnAttachmentExtensions } from '../platform/add-on-attachment/index.js';
|
|
2
3
|
export { addOnExtensions } from '../platform/add-on/index.js';
|
|
3
4
|
export { appExtensions, } from '../platform/app/index.js';
|
|
4
5
|
export { containerExtensions, NotAContainerAppError, } from '../platform/container/index.js';
|
|
6
|
+
export { formatDelinquencyWarning, } from '../platform/delinquency.js';
|
|
5
7
|
export { domainExtensions, } from '../platform/domain/index.js';
|
|
6
8
|
export { DynoCrashedError, dynoExtensions, DynoNotReadyError, enableExec, exchangeExecCredentials, execPrereqs, execStatus, listExtended, restartForExec, runDyno, waitForInfo, waitForRelease, } from '../platform/dyno/index.js';
|
|
7
9
|
export { logSessionExtensions, parseHerokuLogLine, } from '../platform/log-session/index.js';
|
|
@@ -12,6 +14,7 @@ export { reviewAppConfigExtensions } from '../platform/review-app-config/index.j
|
|
|
12
14
|
export { privateToShield, shieldToPrivate } from '../platform/shield.js';
|
|
13
15
|
export { createAndAssociate, sniEndpointExtensions } from '../platform/sni-endpoint/index.js';
|
|
14
16
|
export { spaceExtensions, SpaceNotAllocatedError, SpaceNotReadyError, waitForAllocated, } from '../platform/space/index.js';
|
|
17
|
+
export { teamExtensions } from '../platform/team.js';
|
|
15
18
|
export { telemetryDrainExtensions } from '../platform/telemetry-drain/index.js';
|
|
16
19
|
export { testRunExtensions, TestRunNotReadyError, waitForState, } from '../platform/test-run/index.js';
|
|
17
20
|
export { vpnConnectionExtensions, VpnConnectionFailedError, VpnConnectionNotReadyError, waitForActive, } from '../platform/vpn-connection/index.js';
|