@bussolabs/closeyourit-cli 0.15.0 → 0.16.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/README.md +3 -0
- package/dist/commands/tickets/lease/claim.d.ts +14 -0
- package/dist/commands/tickets/lease/claim.js +71 -0
- package/dist/commands/tickets/lease/release.d.ts +13 -0
- package/dist/commands/tickets/lease/release.js +52 -0
- package/dist/commands/tickets/lease/renew.d.ts +14 -0
- package/dist/commands/tickets/lease/renew.js +71 -0
- package/dist/lib/lease.d.ts +44 -0
- package/dist/lib/lease.js +61 -0
- package/oclif.manifest.json +2799 -2617
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -105,6 +105,9 @@ CLOSEYOURIT_TOKEN=cyi_u_… CLOSEYOURIT_API_URL=https://www.closeyour.it \
|
|
|
105
105
|
| `tickets watch\|unwatch <id> --project <id\|key>` | Watch / stop watching a ticket (its notifications). |
|
|
106
106
|
| `tickets branch <id\|code> --project <id\|key>` | Create a GitHub branch from a ticket (name prefixed with the ticket code). |
|
|
107
107
|
| `tickets pr <id\|code> --project <id\|key>` | Open a GitHub pull request from a ticket (head = the ticket branch). |
|
|
108
|
+
| `tickets lease claim <id\|code> --project <id\|key> [--ttl <seconds>] [--run-id <id>]` | Claim the working lease on a ticket (server default TTL: 8h). Exits non-zero on a 409, naming the current holder and its expiry. |
|
|
109
|
+
| `tickets lease renew <id\|code> --project <id\|key> [--ttl <seconds>] [--run-id <id>]` | Extend your own lease before it expires. |
|
|
110
|
+
| `tickets lease release <id\|code> --project <id\|key> [--run-id <id>]` | Release your own lease so someone else can claim the ticket. |
|
|
108
111
|
| `ideas delete <id> --project <id\|key> --confirm` | Delete an idea (author always allowed; others need ideas.delete). |
|
|
109
112
|
| `ideas archive\|unarchive <id> --project <id\|key>` | Archive an idea (open → archived) / reopen it. |
|
|
110
113
|
| `ideas case-update <idea-id> <case-id> --project <id\|key> [--title] [--description]` | Update a case (example) of an idea. |
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base';
|
|
2
|
+
export default class TicketsLeaseClaim extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
ttl: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
'run-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<unknown>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_1 = require("../../../base");
|
|
5
|
+
const lease_1 = require("../../../lib/lease");
|
|
6
|
+
const output_1 = require("../../../lib/output");
|
|
7
|
+
class TicketsLeaseClaim extends base_1.BaseCommand {
|
|
8
|
+
static description = 'Claim the working lease on a ticket, so nobody else (person or agent) starts it at the same time';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> tickets lease claim <ticket-id> --project acme-api',
|
|
11
|
+
'<%= config.bin %> tickets lease claim DRFL-3 -p driverone-flutter --ttl 3600 --run-id run-42',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: core_1.Args.string({ description: 'Ticket id or code (e.g. DRFL-3)', required: true }),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
...base_1.projectFlag,
|
|
18
|
+
ttl: core_1.Flags.integer({ description: 'Lease duration in seconds (server default: 8h; range 1s..30 days)' }),
|
|
19
|
+
'run-id': core_1.Flags.string({ description: 'Automation run id, for tokens that juggle several concurrent runs' }),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { args, flags } = await this.parse(TicketsLeaseClaim);
|
|
23
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
24
|
+
const path = `/cli/v1/projects/${encodeURIComponent(projectId)}/tickets/${encodeURIComponent(args.id)}/lease`;
|
|
25
|
+
const body = {};
|
|
26
|
+
if (flags.ttl !== undefined)
|
|
27
|
+
body.ttl_seconds = flags.ttl;
|
|
28
|
+
if (flags['run-id'] !== undefined)
|
|
29
|
+
body.run_id = flags['run-id'];
|
|
30
|
+
let res;
|
|
31
|
+
try {
|
|
32
|
+
res = await this.api.post(path, body);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
// 409 = somebody else already holds it. --json prints the full backend envelope (details
|
|
36
|
+
// included) itself and returns, so BaseCommand.catch never trims it down to {code,message};
|
|
37
|
+
// human mode gets the holder spelled out in the message instead (requisito CYCL-14).
|
|
38
|
+
if (this.jsonEnabled()) {
|
|
39
|
+
const envelope = (0, lease_1.leaseErrorEnvelope)(error);
|
|
40
|
+
if (!envelope)
|
|
41
|
+
throw error;
|
|
42
|
+
this.logJson(envelope);
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
throw (0, lease_1.describeLeaseConflict)(error);
|
|
47
|
+
}
|
|
48
|
+
if (!this.jsonEnabled()) {
|
|
49
|
+
const lease = res.data ?? {};
|
|
50
|
+
this.log(`Ticket ${args.id} leased until ${lease.expires_at ?? '?'}:`);
|
|
51
|
+
this.log((0, output_1.renderRecord)(leaseSummary(lease)));
|
|
52
|
+
}
|
|
53
|
+
return res;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.default = TicketsLeaseClaim;
|
|
57
|
+
/** Flatten the lease payload for `renderRecord`: `held_by` is a nested object, so print it as one line. */
|
|
58
|
+
function leaseSummary(lease) {
|
|
59
|
+
const heldBy = lease.held_by;
|
|
60
|
+
return {
|
|
61
|
+
ticket: lease.ticket,
|
|
62
|
+
run_id: lease.run_id,
|
|
63
|
+
held_by: heldBy ? `${heldBy.kind} ${heldBy.name ?? heldBy.id}` : null,
|
|
64
|
+
expires_at: lease.expires_at,
|
|
65
|
+
host_id: lease.host_id,
|
|
66
|
+
account_id: lease.account_id,
|
|
67
|
+
agent: lease.agent,
|
|
68
|
+
execution_phase: lease.execution_phase,
|
|
69
|
+
profile_digest: lease.profile_digest,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base';
|
|
2
|
+
export default class TicketsLeaseRelease extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
'run-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<unknown>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_1 = require("../../../base");
|
|
5
|
+
const lease_1 = require("../../../lib/lease");
|
|
6
|
+
const output_1 = require("../../../lib/output");
|
|
7
|
+
class TicketsLeaseRelease extends base_1.BaseCommand {
|
|
8
|
+
static description = 'Release your own working lease on a ticket, so someone else can claim it';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> tickets lease release <ticket-id> --project acme-api',
|
|
11
|
+
'<%= config.bin %> tickets lease release DRFL-3 -p driverone-flutter --run-id run-42',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: core_1.Args.string({ description: 'Ticket id or code (e.g. DRFL-3)', required: true }),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
...base_1.projectFlag,
|
|
18
|
+
'run-id': core_1.Flags.string({ description: 'Automation run id, for tokens that juggle several concurrent runs' }),
|
|
19
|
+
};
|
|
20
|
+
async run() {
|
|
21
|
+
const { args, flags } = await this.parse(TicketsLeaseRelease);
|
|
22
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
23
|
+
const path = `/cli/v1/projects/${encodeURIComponent(projectId)}/tickets/${encodeURIComponent(args.id)}/lease`;
|
|
24
|
+
const body = {};
|
|
25
|
+
if (flags['run-id'] !== undefined)
|
|
26
|
+
body.run_id = flags['run-id'];
|
|
27
|
+
let res;
|
|
28
|
+
try {
|
|
29
|
+
res = await this.api.delete(path, { body });
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
// 409 = somebody else already holds it, 404 = no lease to release. --json prints the full
|
|
33
|
+
// backend envelope (details included) itself and returns, so BaseCommand.catch never trims
|
|
34
|
+
// it down to {code,message}; human mode gets the holder spelled out instead (CYCL-14).
|
|
35
|
+
if (this.jsonEnabled()) {
|
|
36
|
+
const envelope = (0, lease_1.leaseErrorEnvelope)(error);
|
|
37
|
+
if (!envelope)
|
|
38
|
+
throw error;
|
|
39
|
+
this.logJson(envelope);
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
throw (0, lease_1.describeLeaseConflict)(error);
|
|
44
|
+
}
|
|
45
|
+
if (!this.jsonEnabled()) {
|
|
46
|
+
this.log(`Ticket ${args.id} lease released:`);
|
|
47
|
+
this.log((0, output_1.renderRecord)(res.data ?? {}));
|
|
48
|
+
}
|
|
49
|
+
return res;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.default = TicketsLeaseRelease;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base';
|
|
2
|
+
export default class TicketsLeaseRenew extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
ttl: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
'run-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<unknown>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_1 = require("../../../base");
|
|
5
|
+
const lease_1 = require("../../../lib/lease");
|
|
6
|
+
const output_1 = require("../../../lib/output");
|
|
7
|
+
class TicketsLeaseRenew extends base_1.BaseCommand {
|
|
8
|
+
static description = 'Extend your own working lease on a ticket before it expires';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> tickets lease renew <ticket-id> --project acme-api',
|
|
11
|
+
'<%= config.bin %> tickets lease renew DRFL-3 -p driverone-flutter --ttl 3600 --run-id run-42',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: core_1.Args.string({ description: 'Ticket id or code (e.g. DRFL-3)', required: true }),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
...base_1.projectFlag,
|
|
18
|
+
ttl: core_1.Flags.integer({ description: 'New lease duration in seconds (server default: 8h; range 1s..30 days)' }),
|
|
19
|
+
'run-id': core_1.Flags.string({ description: 'Automation run id, for tokens that juggle several concurrent runs' }),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { args, flags } = await this.parse(TicketsLeaseRenew);
|
|
23
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
24
|
+
const path = `/cli/v1/projects/${encodeURIComponent(projectId)}/tickets/${encodeURIComponent(args.id)}/lease`;
|
|
25
|
+
const body = {};
|
|
26
|
+
if (flags.ttl !== undefined)
|
|
27
|
+
body.ttl_seconds = flags.ttl;
|
|
28
|
+
if (flags['run-id'] !== undefined)
|
|
29
|
+
body.run_id = flags['run-id'];
|
|
30
|
+
let res;
|
|
31
|
+
try {
|
|
32
|
+
res = await this.api.put(path, body);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
// 409 = somebody else already holds it, 404 = no lease to renew. --json prints the full
|
|
36
|
+
// backend envelope (details included) itself and returns, so BaseCommand.catch never trims
|
|
37
|
+
// it down to {code,message}; human mode gets the holder spelled out instead (CYCL-14).
|
|
38
|
+
if (this.jsonEnabled()) {
|
|
39
|
+
const envelope = (0, lease_1.leaseErrorEnvelope)(error);
|
|
40
|
+
if (!envelope)
|
|
41
|
+
throw error;
|
|
42
|
+
this.logJson(envelope);
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
throw (0, lease_1.describeLeaseConflict)(error);
|
|
47
|
+
}
|
|
48
|
+
if (!this.jsonEnabled()) {
|
|
49
|
+
const lease = res.data ?? {};
|
|
50
|
+
this.log(`Ticket ${args.id} lease renewed until ${lease.expires_at ?? '?'}:`);
|
|
51
|
+
this.log((0, output_1.renderRecord)(leaseSummary(lease)));
|
|
52
|
+
}
|
|
53
|
+
return res;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.default = TicketsLeaseRenew;
|
|
57
|
+
/** Flatten the lease payload for `renderRecord`: `held_by` is a nested object, so print it as one line. */
|
|
58
|
+
function leaseSummary(lease) {
|
|
59
|
+
const heldBy = lease.held_by;
|
|
60
|
+
return {
|
|
61
|
+
ticket: lease.ticket,
|
|
62
|
+
run_id: lease.run_id,
|
|
63
|
+
held_by: heldBy ? `${heldBy.kind} ${heldBy.name ?? heldBy.id}` : null,
|
|
64
|
+
expires_at: lease.expires_at,
|
|
65
|
+
host_id: lease.host_id,
|
|
66
|
+
account_id: lease.account_id,
|
|
67
|
+
agent: lease.agent,
|
|
68
|
+
execution_phase: lease.execution_phase,
|
|
69
|
+
profile_digest: lease.profile_digest,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On a 409 lease conflict, rewrite the error message to name who holds the ticket and until when.
|
|
3
|
+
* An automation reading "R409-LEASE-001: Ticket is already leased" alone cannot decide whether to
|
|
4
|
+
* skip to the next ticket — it needs the holder. Every other status/code (and a 409 without the
|
|
5
|
+
* expected `details.holder` shape) passes through untouched, so unrelated errors keep the server's
|
|
6
|
+
* own wording. Human-mode only: `--json` prints its own full envelope instead (see
|
|
7
|
+
* `leaseErrorEnvelope`), so it never goes through this rewrite.
|
|
8
|
+
*/
|
|
9
|
+
export declare function describeLeaseConflict(error: unknown): unknown;
|
|
10
|
+
/** Allow-listed `details` for the --json envelope: only the fields a lease conflict is documented to carry. */
|
|
11
|
+
interface LeaseErrorDetails {
|
|
12
|
+
holder: {
|
|
13
|
+
held_by: {
|
|
14
|
+
kind: string;
|
|
15
|
+
id: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
};
|
|
18
|
+
expires_at?: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Full `{error:{code,message,details}}` envelope for a lease command failure in `--json` mode.
|
|
23
|
+
* `BaseCommand.catch` — shared by every command in the CLI — only ever emits `{code,message}`; a
|
|
24
|
+
* script reading `--json` on a 409 needs `details.holder` too (who holds the ticket, until when),
|
|
25
|
+
* so lease commands print this themselves and return before the error reaches `catch()`, instead of
|
|
26
|
+
* changing that shared, cross-cutting behaviour (out of scope for CYCL-14).
|
|
27
|
+
*
|
|
28
|
+
* `details` is rebuilt field-by-field from an explicit allow-list (`holder.held_by.{kind,id,name}`,
|
|
29
|
+
* `holder.expires_at`) instead of forwarding `error.details` verbatim — same reasoning as
|
|
30
|
+
* `BaseCommand.catch`'s own allow-listed envelope (see `base.ts`): never serialize a server-shaped
|
|
31
|
+
* object of arbitrary provenance straight into `--json` output. Any other field the backend happens
|
|
32
|
+
* to send inside `details` (e.g. a stray `holder.ticket`) is dropped, not forwarded.
|
|
33
|
+
*
|
|
34
|
+
* Returns undefined for anything that isn't an `ApiRequestError`: callers should let those propagate
|
|
35
|
+
* to `catch()` as usual.
|
|
36
|
+
*/
|
|
37
|
+
export declare function leaseErrorEnvelope(error: unknown): {
|
|
38
|
+
error: {
|
|
39
|
+
code: string;
|
|
40
|
+
message: string;
|
|
41
|
+
details?: LeaseErrorDetails;
|
|
42
|
+
};
|
|
43
|
+
} | undefined;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeLeaseConflict = describeLeaseConflict;
|
|
4
|
+
exports.leaseErrorEnvelope = leaseErrorEnvelope;
|
|
5
|
+
const api_1 = require("./api");
|
|
6
|
+
/** Extract `{kind,id,name?,expiresAt?}` from a 409's `details`, or undefined if the shape doesn't match. */
|
|
7
|
+
function parseLeaseHolder(details) {
|
|
8
|
+
const holder = details?.holder;
|
|
9
|
+
const heldBy = holder?.held_by;
|
|
10
|
+
if (!heldBy?.kind || !heldBy.id)
|
|
11
|
+
return undefined;
|
|
12
|
+
return { kind: heldBy.kind, id: heldBy.id, name: heldBy.name, expiresAt: holder?.expires_at };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* On a 409 lease conflict, rewrite the error message to name who holds the ticket and until when.
|
|
16
|
+
* An automation reading "R409-LEASE-001: Ticket is already leased" alone cannot decide whether to
|
|
17
|
+
* skip to the next ticket — it needs the holder. Every other status/code (and a 409 without the
|
|
18
|
+
* expected `details.holder` shape) passes through untouched, so unrelated errors keep the server's
|
|
19
|
+
* own wording. Human-mode only: `--json` prints its own full envelope instead (see
|
|
20
|
+
* `leaseErrorEnvelope`), so it never goes through this rewrite.
|
|
21
|
+
*/
|
|
22
|
+
function describeLeaseConflict(error) {
|
|
23
|
+
if (!(error instanceof api_1.ApiRequestError) || error.status !== 409)
|
|
24
|
+
return error;
|
|
25
|
+
const holder = parseLeaseHolder(error.details);
|
|
26
|
+
if (!holder)
|
|
27
|
+
return error;
|
|
28
|
+
const who = holder.name ? `${holder.kind} "${holder.name}"` : `${holder.kind} ${holder.id}`;
|
|
29
|
+
const until = holder.expiresAt ? ` until ${holder.expiresAt}` : '';
|
|
30
|
+
return new api_1.ApiRequestError(error.status, error.code, `Ticket already leased by ${who}${until}.`, error.details);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Full `{error:{code,message,details}}` envelope for a lease command failure in `--json` mode.
|
|
34
|
+
* `BaseCommand.catch` — shared by every command in the CLI — only ever emits `{code,message}`; a
|
|
35
|
+
* script reading `--json` on a 409 needs `details.holder` too (who holds the ticket, until when),
|
|
36
|
+
* so lease commands print this themselves and return before the error reaches `catch()`, instead of
|
|
37
|
+
* changing that shared, cross-cutting behaviour (out of scope for CYCL-14).
|
|
38
|
+
*
|
|
39
|
+
* `details` is rebuilt field-by-field from an explicit allow-list (`holder.held_by.{kind,id,name}`,
|
|
40
|
+
* `holder.expires_at`) instead of forwarding `error.details` verbatim — same reasoning as
|
|
41
|
+
* `BaseCommand.catch`'s own allow-listed envelope (see `base.ts`): never serialize a server-shaped
|
|
42
|
+
* object of arbitrary provenance straight into `--json` output. Any other field the backend happens
|
|
43
|
+
* to send inside `details` (e.g. a stray `holder.ticket`) is dropped, not forwarded.
|
|
44
|
+
*
|
|
45
|
+
* Returns undefined for anything that isn't an `ApiRequestError`: callers should let those propagate
|
|
46
|
+
* to `catch()` as usual.
|
|
47
|
+
*/
|
|
48
|
+
function leaseErrorEnvelope(error) {
|
|
49
|
+
if (!(error instanceof api_1.ApiRequestError))
|
|
50
|
+
return undefined;
|
|
51
|
+
const holder = parseLeaseHolder(error.details);
|
|
52
|
+
const details = holder
|
|
53
|
+
? {
|
|
54
|
+
holder: {
|
|
55
|
+
held_by: holder.name ? { kind: holder.kind, id: holder.id, name: holder.name } : { kind: holder.kind, id: holder.id },
|
|
56
|
+
...(holder.expiresAt ? { expires_at: holder.expiresAt } : {}),
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
: undefined;
|
|
60
|
+
return { error: { code: error.code, message: error.message, details } };
|
|
61
|
+
}
|