@pantechdynamic/sdk 0.1.0 → 0.2.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 +19 -0
- package/README.md +28 -4
- package/dist/index.cjs +147 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1819 -156
- package/dist/index.d.ts +1819 -156
- package/dist/index.js +147 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ A new version heading here (`## X.Y.Z (YYYY-MM-DD)`) pushed to main is
|
|
|
4
4
|
tagged `vX.Y.Z` and published to npm. Add changes under `## Unreleased`
|
|
5
5
|
until then.
|
|
6
6
|
|
|
7
|
+
## 0.2.0 (2026-10-28)
|
|
8
|
+
|
|
9
|
+
- `client.migrate`, for moving from another cloud: `migrate.connections`
|
|
10
|
+
(`list`, `listAll`, `create`, `get`, `update` for the name, role ARN or a retry, `delete`)
|
|
11
|
+
connects an AWS account through a read-only role; `migrate.scans` (`list`, `listAll`,
|
|
12
|
+
`start`, `get` with `{ include: "inventory" }`) reads what runs there; `migrate.migrations`
|
|
13
|
+
(`list`, `listAll`, `create`, `get`, `rename`, `delete`, `updateItem`, `exportTerraform`) plans
|
|
14
|
+
the move with a price comparison and a Terraform export.
|
|
15
|
+
- `migrate.connections.wait()` and `migrate.scans.wait()`, which reject with the new
|
|
16
|
+
`CloudFailedError` when the connection or scan fails.
|
|
17
|
+
- `examples/migrate-from-aws.ts`.
|
|
18
|
+
- Types follow the current public API, including Kubernetes clusters' `node_health`,
|
|
19
|
+
`ready_nodes` and `nodes_checked_at`, and a load balancer's `protocol`.
|
|
20
|
+
- Fixed: request fields the API defaults (`endpoint_access`, `control_nodes`, a firewall rule's
|
|
21
|
+
`direction` and `action`, `algorithm`, `purpose`, `admin_username`, `retention_count`,
|
|
22
|
+
`enabled`, `autoscaling_enabled`) are optional in the types, as they are in the API.
|
|
23
|
+
- Agent sessions, which answer only AI apps connected through Pantech's MCP server, have no
|
|
24
|
+
methods yet; `scripts/not-in-sdk.json` lists them and `npm run generate` leaves out their types.
|
|
25
|
+
|
|
7
26
|
## 0.1.0 (2026-10-24)
|
|
8
27
|
|
|
9
28
|
- First release: a client for every operation in the Pantech Dynamics public API
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
The official client for the [Pantech Dynamics public API](https://docs.pantechdynamics.com/api):
|
|
8
8
|
instances, VPC networks, firewalls, public IPs, load balancers, volumes, snapshots, managed
|
|
9
|
-
databases, managed Kubernetes, SSH keys, webhooks, billing and
|
|
9
|
+
databases, managed Kubernetes, SSH keys, webhooks, billing, usage, and moving from another cloud.
|
|
10
10
|
|
|
11
11
|
- Zero runtime dependencies. Uses the global `fetch` and Web Crypto, so it runs on Node.js 18+,
|
|
12
12
|
Bun, Deno and edge runtimes.
|
|
@@ -75,9 +75,11 @@ Every method takes per-call options last: `{ signal, timeout, maxRetries, idempo
|
|
|
75
75
|
| Databases | `databases.*`, `databases.snapshots.*`, `databaseOrders.wait(order)` |
|
|
76
76
|
| SSH keys, webhooks | `sshKeys.*`, `webhooks.*`, `webhooks.deliveries.*` |
|
|
77
77
|
| Billing and usage | `billing.credit.get()`, `billing.credit.purchases.create(...)`, `billing.receipts.getPdf(id)`, `usage.get()` |
|
|
78
|
+
| Move from another cloud | `migrate.connections.*`, `migrate.scans.*`, `migrate.migrations.*` |
|
|
78
79
|
| Operations | `operations.get(id)`, `operations.wait(id)`, `operations.stream(id)` |
|
|
79
80
|
|
|
80
|
-
Every operation in the public spec has a method
|
|
81
|
+
Every operation in the public spec has a method, except agent sessions, which answer only AI apps
|
|
82
|
+
connected through Pantech's MCP server; `test/coverage.test.ts` fails if one is missing.
|
|
81
83
|
For anything else, `client.request({ method, path, query, body })` sends a raw request with the
|
|
82
84
|
same auth, retries and errors.
|
|
83
85
|
|
|
@@ -101,7 +103,29 @@ for await (const o of client.operations.stream("op_…")) console.log(o.status);
|
|
|
101
103
|
```
|
|
102
104
|
|
|
103
105
|
A failed operation rejects with `OperationFailedError` (`code`, `detail` from its `failure`), a
|
|
104
|
-
failed or unpaid order with `OrderFailedError`,
|
|
106
|
+
failed or unpaid order with `OrderFailedError`, a failed cloud connection or scan with
|
|
107
|
+
`CloudFailedError`, and a wait that runs out with `WaitTimeoutError`.
|
|
108
|
+
|
|
109
|
+
## Move from another cloud
|
|
110
|
+
|
|
111
|
+
`client.migrate` connects an AWS account through a read-only role that only Pantech can assume (no
|
|
112
|
+
access keys are shared), scans what runs there, and plans the move with a price comparison and a
|
|
113
|
+
Terraform export. Nothing is created on Pantech until you apply the Terraform.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
let conn = await client.migrate.connections.create({ name: "Production AWS" });
|
|
117
|
+
console.log(conn.setup.quick_create_url); // create the stack in AWS, then send its RoleArn output
|
|
118
|
+
await client.migrate.connections.update(conn.id, { role_arn: "arn:aws:iam::…:role/…" });
|
|
119
|
+
conn = await client.migrate.connections.wait(conn.id); // CloudFailedError if the role cannot be assumed
|
|
120
|
+
|
|
121
|
+
const scan = await client.migrate.scans.wait((await client.migrate.scans.start(conn.id)).id);
|
|
122
|
+
const plan = await client.migrate.migrations.create({ scan_id: scan.id, name: "Move to Pantech" });
|
|
123
|
+
console.log(plan.estimate?.pantech_monthly_minor, plan.estimate?.source_monthly_minor);
|
|
124
|
+
const { files } = await client.migrate.migrations.exportTerraform(plan.id); // main.tf, variables.tf
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`migrate.migrations.updateItem(id, { key, excluded: true })` leaves an item out, or changes its
|
|
128
|
+
plan, size, address range or role, before you export. See `examples/migrate-from-aws.ts`.
|
|
105
129
|
|
|
106
130
|
## Errors
|
|
107
131
|
|
|
@@ -156,7 +180,7 @@ the timestamp is too old. On Node.js 18, start node with `--experimental-global-
|
|
|
156
180
|
|
|
157
181
|
## Examples
|
|
158
182
|
|
|
159
|
-
`examples/` has `create-instance.ts`, `list.ts` and `
|
|
183
|
+
`examples/` has `create-instance.ts`, `list.ts`, `webhook-receiver.ts` and `migrate-from-aws.ts`. With Node.js 23.6+:
|
|
160
184
|
`npm run build && PANTECH_API_KEY=PAN_… node examples/list.ts`.
|
|
161
185
|
|
|
162
186
|
## Development
|
package/dist/index.cjs
CHANGED
|
@@ -88,6 +88,18 @@ var OrderFailedError = class extends PantechError {
|
|
|
88
88
|
this.order = order;
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
|
+
var CloudFailedError = class extends PantechError {
|
|
92
|
+
name = "CloudFailedError";
|
|
93
|
+
/** `connection` or `scan`. */
|
|
94
|
+
kind;
|
|
95
|
+
/** The failed connection or scan, as the API returned it. */
|
|
96
|
+
resource;
|
|
97
|
+
constructor(message, kind, resource, init = {}) {
|
|
98
|
+
super(message, init);
|
|
99
|
+
this.kind = kind;
|
|
100
|
+
this.resource = resource;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
91
103
|
var WaitTimeoutError = class extends PantechError {
|
|
92
104
|
name = "WaitTimeoutError";
|
|
93
105
|
};
|
|
@@ -775,6 +787,136 @@ var MeResource = class extends APIResource {
|
|
|
775
787
|
}
|
|
776
788
|
};
|
|
777
789
|
|
|
790
|
+
// src/resources/migrate.ts
|
|
791
|
+
var CONNECTION_WAIT_MS = 10 * 6e4;
|
|
792
|
+
var SCAN_WAIT_MS = 30 * 6e4;
|
|
793
|
+
function cloudFailed(kind, id, failure, resource) {
|
|
794
|
+
const detail = failure?.message ?? `The ${kind} failed.`;
|
|
795
|
+
const code = failure?.code;
|
|
796
|
+
return new CloudFailedError(
|
|
797
|
+
code ? `Cloud ${kind} ${id} failed: ${detail} (${code})` : `Cloud ${kind} ${id} failed: ${detail}`,
|
|
798
|
+
kind,
|
|
799
|
+
resource,
|
|
800
|
+
{ code, detail }
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
var Migrate = class extends APIResource {
|
|
804
|
+
/** Connections to AWS accounts through a read-only role only Pantech can assume. */
|
|
805
|
+
connections = new CloudConnections(this._client);
|
|
806
|
+
/** Reads of everything a connection's role can see. */
|
|
807
|
+
scans = new CloudScans(this._client);
|
|
808
|
+
/** Plans to move what a scan found to Pantech. Nothing is created until you apply the Terraform. */
|
|
809
|
+
migrations = new Migrations(this._client);
|
|
810
|
+
};
|
|
811
|
+
var CloudConnections = class extends APIResource {
|
|
812
|
+
list(params = {}, options) {
|
|
813
|
+
return this._get("/cloud-connections", params, options);
|
|
814
|
+
}
|
|
815
|
+
listAll(params = {}, options) {
|
|
816
|
+
return this._listAll("/cloud-connections", params, options);
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Starts a connection. Its `setup` holds the CloudFormation template (and,
|
|
820
|
+
* when offered, a one-click `quick_create_url`) that creates the read-only
|
|
821
|
+
* role in your AWS account; send the stack's `RoleArn` output with `update`.
|
|
822
|
+
*/
|
|
823
|
+
create(body, options) {
|
|
824
|
+
return this._post("/cloud-connections", body, options);
|
|
825
|
+
}
|
|
826
|
+
get(connectionId, options) {
|
|
827
|
+
return this._get(path`/cloud-connections/${connectionId}`, void 0, options);
|
|
828
|
+
}
|
|
829
|
+
/** Renames the connection, sets its `role_arn`, or retries a failed check (`retry: true`). */
|
|
830
|
+
update(connectionId, body, options) {
|
|
831
|
+
return this._patch(path`/cloud-connections/${connectionId}`, body, options);
|
|
832
|
+
}
|
|
833
|
+
/** Removes the connection and its scans; plans made from it stay. Delete the stack in AWS to revoke the role there. */
|
|
834
|
+
delete(connectionId, options) {
|
|
835
|
+
return this._delete(path`/cloud-connections/${connectionId}`, options);
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Polls the connection until it is `connected` (resolves with it) or its
|
|
839
|
+
* check fails (rejects with CloudFailedError). Set the role ARN with
|
|
840
|
+
* `update` first. Default timeout 10 minutes, polling every 5 seconds.
|
|
841
|
+
*/
|
|
842
|
+
wait(connectionId, options = {}) {
|
|
843
|
+
return poll(
|
|
844
|
+
() => this.get(connectionId, { signal: options.signal }),
|
|
845
|
+
(c) => {
|
|
846
|
+
if (c.status === "failed") throw cloudFailed("connection", c.id, c.failure, c);
|
|
847
|
+
return c.status === "connected";
|
|
848
|
+
},
|
|
849
|
+
`Cloud connection ${connectionId}`,
|
|
850
|
+
{ timeoutMs: CONNECTION_WAIT_MS, pollIntervalMs: 5e3, ...options }
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
};
|
|
854
|
+
var CloudScans = class extends APIResource {
|
|
855
|
+
/** A connection's scans, newest first, without their inventories. */
|
|
856
|
+
list(connectionId, params = {}, options) {
|
|
857
|
+
return this._get(path`/cloud-connections/${connectionId}/scans`, params, options);
|
|
858
|
+
}
|
|
859
|
+
listAll(connectionId, params = {}, options) {
|
|
860
|
+
return this._listAll(path`/cloud-connections/${connectionId}/scans`, params, options);
|
|
861
|
+
}
|
|
862
|
+
/** Queues a scan of a connected account. Follow it with `wait`. */
|
|
863
|
+
start(connectionId, options) {
|
|
864
|
+
return this._post(path`/cloud-connections/${connectionId}/scans`, void 0, options);
|
|
865
|
+
}
|
|
866
|
+
/** A scan's status and counts. Pass `{ include: "inventory" }` for everything it found. */
|
|
867
|
+
get(scanId, params = {}, options) {
|
|
868
|
+
return this._get(path`/cloud-scans/${scanId}`, params, options);
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Polls the scan until it `succeeded` (resolves with it, without its
|
|
872
|
+
* inventory) or failed (rejects with CloudFailedError). Default timeout 30
|
|
873
|
+
* minutes, polling every 10 seconds.
|
|
874
|
+
*/
|
|
875
|
+
wait(scanId, options = {}) {
|
|
876
|
+
return poll(
|
|
877
|
+
() => this.get(scanId, {}, { signal: options.signal }),
|
|
878
|
+
(s) => {
|
|
879
|
+
if (s.status === "failed") throw cloudFailed("scan", s.id, s.failure, s);
|
|
880
|
+
return s.status === "succeeded";
|
|
881
|
+
},
|
|
882
|
+
`Cloud scan ${scanId}`,
|
|
883
|
+
{ timeoutMs: SCAN_WAIT_MS, pollIntervalMs: 1e4, ...options }
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
var Migrations = class extends APIResource {
|
|
888
|
+
/** Your migration plans, newest first, without their items or estimate. */
|
|
889
|
+
list(params = {}, options) {
|
|
890
|
+
return this._get("/migrations", params, options);
|
|
891
|
+
}
|
|
892
|
+
listAll(params = {}, options) {
|
|
893
|
+
return this._listAll("/migrations", params, options);
|
|
894
|
+
}
|
|
895
|
+
/** Builds a plan, with a price comparison, from a scan that succeeded. Nothing is created on Pantech. */
|
|
896
|
+
create(body, options) {
|
|
897
|
+
return this._post("/migrations", body, options);
|
|
898
|
+
}
|
|
899
|
+
/** A plan with every item, and a price comparison computed now. */
|
|
900
|
+
get(migrationId, options) {
|
|
901
|
+
return this._get(path`/migrations/${migrationId}`, void 0, options);
|
|
902
|
+
}
|
|
903
|
+
rename(migrationId, body, options) {
|
|
904
|
+
return this._patch(path`/migrations/${migrationId}`, body, options);
|
|
905
|
+
}
|
|
906
|
+
/** Deletes the plan. Nothing on Pantech or in the other cloud is touched. */
|
|
907
|
+
delete(migrationId, options) {
|
|
908
|
+
return this._delete(path`/migrations/${migrationId}`, options);
|
|
909
|
+
}
|
|
910
|
+
/** Changes one item, named by its `key`: exclude it, or change its plan, size, range, role or email. */
|
|
911
|
+
updateItem(migrationId, body, options) {
|
|
912
|
+
return this._patch(path`/migrations/${migrationId}/items`, body, options);
|
|
913
|
+
}
|
|
914
|
+
/** The plan's planned items as Terraform: `main.tf` and `variables.tf`. */
|
|
915
|
+
exportTerraform(migrationId, options) {
|
|
916
|
+
return this._get(path`/migrations/${migrationId}/terraform`, void 0, options);
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
|
|
778
920
|
// src/resources/networks.ts
|
|
779
921
|
var Networks = class extends APIResource {
|
|
780
922
|
/** A network's subnets: `client.networks.subnets.list(networkId)`. */
|
|
@@ -1185,7 +1327,7 @@ var WebhookDeliveries = class extends APIResource {
|
|
|
1185
1327
|
};
|
|
1186
1328
|
|
|
1187
1329
|
// src/version.ts
|
|
1188
|
-
var VERSION = "0.
|
|
1330
|
+
var VERSION = "0.2.0";
|
|
1189
1331
|
|
|
1190
1332
|
// src/client.ts
|
|
1191
1333
|
var DEFAULT_BASE_URL = "https://api.pantechdynamics.com/public/v1";
|
|
@@ -1230,6 +1372,8 @@ var Pantech = class {
|
|
|
1230
1372
|
databaseOrders;
|
|
1231
1373
|
sshKeys;
|
|
1232
1374
|
webhooks;
|
|
1375
|
+
/** Move from another cloud: connections, scans and migration plans. */
|
|
1376
|
+
migrate;
|
|
1233
1377
|
operations;
|
|
1234
1378
|
constructor(options = {}) {
|
|
1235
1379
|
const apiKey = options.apiKey ?? readEnv("PANTECH_API_KEY");
|
|
@@ -1271,6 +1415,7 @@ var Pantech = class {
|
|
|
1271
1415
|
this.databaseOrders = new DatabaseOrders(this);
|
|
1272
1416
|
this.sshKeys = new SshKeys(this);
|
|
1273
1417
|
this.webhooks = new Webhooks(this);
|
|
1418
|
+
this.migrate = new Migrate(this);
|
|
1274
1419
|
}
|
|
1275
1420
|
/**
|
|
1276
1421
|
* Sends one request and returns its decoded body (undefined for an empty
|
|
@@ -1490,6 +1635,7 @@ exports.APIConnectionError = APIConnectionError;
|
|
|
1490
1635
|
exports.APITimeoutError = APITimeoutError;
|
|
1491
1636
|
exports.AuthenticationError = AuthenticationError;
|
|
1492
1637
|
exports.BadRequestError = BadRequestError;
|
|
1638
|
+
exports.CloudFailedError = CloudFailedError;
|
|
1493
1639
|
exports.ConflictError = ConflictError;
|
|
1494
1640
|
exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
1495
1641
|
exports.DEFAULT_WEBHOOK_TOLERANCE_SECONDS = DEFAULT_WEBHOOK_TOLERANCE_SECONDS;
|