ardent-cli 0.0.5 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +108 -40
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -104,9 +104,10 @@ async function bootstrapCache() {
104
104
  "Content-Type": "application/json",
105
105
  "Authorization": `Bearer ${token}`
106
106
  };
107
- const [connectorsRes, branchesRes] = await Promise.all([
107
+ const [connectorsRes, branchesRes, meRes] = await Promise.all([
108
108
  fetch(`${apiUrl}/v1/cli/connectors`, { headers }),
109
- fetch(`${apiUrl}/v1/cli/branches`, { headers })
109
+ fetch(`${apiUrl}/v1/cli/branches`, { headers }),
110
+ fetch(`${apiUrl}/v1/cli/me`, { headers })
110
111
  ]);
111
112
  let connectorCount = 0;
112
113
  let branchCount = 0;
@@ -122,10 +123,22 @@ async function bootstrapCache() {
122
123
  setCacheEntry("branches", branches);
123
124
  branchCount = branches.length;
124
125
  }
126
+ if (meRes.ok) {
127
+ const user = await meRes.json();
128
+ setConfig("user", user);
129
+ }
125
130
  return { connectors: connectorCount, branches: branchCount };
126
131
  }
127
132
 
128
133
  // src/lib/api.ts
134
+ function parseApiError(status, text) {
135
+ try {
136
+ const json = JSON.parse(text);
137
+ if (json.detail) return `API error ${status}: ${json.detail}`;
138
+ } catch {
139
+ }
140
+ return `API error ${status}: ${text}`;
141
+ }
129
142
  var ApiClient = class {
130
143
  getHeaders() {
131
144
  const token = getToken();
@@ -148,7 +161,7 @@ var ApiClient = class {
148
161
  });
149
162
  if (!response.ok) {
150
163
  const text = await response.text();
151
- throw new Error(`API error ${response.status}: ${text}`);
164
+ throw new Error(parseApiError(response.status, text));
152
165
  }
153
166
  return response.json();
154
167
  }
@@ -161,7 +174,7 @@ var ApiClient = class {
161
174
  });
162
175
  if (!response.ok) {
163
176
  const text = await response.text();
164
- throw new Error(`API error ${response.status}: ${text}`);
177
+ throw new Error(parseApiError(response.status, text));
165
178
  }
166
179
  return response.json();
167
180
  }
@@ -174,7 +187,7 @@ var ApiClient = class {
174
187
  });
175
188
  if (!response.ok) {
176
189
  const text = await response.text();
177
- throw new Error(`API error ${response.status}: ${text}`);
190
+ throw new Error(parseApiError(response.status, text));
178
191
  }
179
192
  return response.json();
180
193
  }
@@ -187,7 +200,7 @@ var ApiClient = class {
187
200
  });
188
201
  if (!response.ok) {
189
202
  const text = await response.text();
190
- throw new Error(`API error ${response.status}: ${text}`);
203
+ throw new Error(parseApiError(response.status, text));
191
204
  }
192
205
  return response.json();
193
206
  }
@@ -205,7 +218,8 @@ function isNetworkError(err) {
205
218
  }
206
219
  function isPermissionError(err) {
207
220
  if (err instanceof Error) {
208
- return err.message.includes("API error 403") || err.message.includes("API error 401");
221
+ const msg = err.message.toLowerCase();
222
+ return msg.includes("api error 403") || msg.includes("api error 401") || msg.includes("not authorized") || msg.includes("forbidden");
209
223
  }
210
224
  return false;
211
225
  }
@@ -766,43 +780,84 @@ async function createAction2(type, url, options) {
766
780
  console.error(` Supported: ${supportedTypes.join(", ")}`);
767
781
  process.exit(1);
768
782
  }
769
- try {
770
- const parsed = parsePostgresUrl(url);
771
- if (!parsed.password) {
772
- console.error("\u2717 Password required in connection URL");
773
- console.error(" Example: postgresql://user:password@host:5432/db");
783
+ const isByoc = Boolean(options.byoc);
784
+ if (isByoc) {
785
+ if (!options.apiKey || !options.projectId) {
786
+ console.error("\u2717 --api-key and --project-id are required when using --byoc");
774
787
  process.exit(1);
775
788
  }
776
- const connectionDetails = {
777
- host: parsed.host,
778
- port: parsed.port,
779
- username: parsed.username,
780
- password: parsed.password
781
- };
782
- const connectorName = options.name || "my-postgresql-connection";
783
- console.log("Creating connector...");
784
- const created = await api.post("/v1/connectors", {
785
- name: connectorName,
786
- service_name: "postgresql",
787
- connection_details: connectionDetails
788
- });
789
+ if (options.byoc !== "neon") {
790
+ console.error(`\u2717 Unsupported BYOC provider: ${options.byoc}`);
791
+ console.error(" Supported: neon");
792
+ process.exit(1);
793
+ }
794
+ } else if (!url) {
795
+ console.error("\u2717 Connection URL required");
796
+ console.error(" Example: ardent connector create postgresql postgresql://user:pass@host:5432/db");
797
+ process.exit(1);
798
+ }
799
+ try {
800
+ const connectorName = options.name || (isByoc ? "my-neon-connection" : "my-postgresql-connection");
801
+ let createPayload;
802
+ if (isByoc) {
803
+ console.log("Creating connector (BYOC Neon)...");
804
+ createPayload = {
805
+ name: connectorName,
806
+ service_name: "postgresql",
807
+ byoc: options.byoc,
808
+ neon_api_key: options.apiKey,
809
+ neon_project_id: options.projectId,
810
+ connection_details: {}
811
+ };
812
+ } else {
813
+ const parsed = parsePostgresUrl(url);
814
+ if (!parsed.password) {
815
+ console.error("\u2717 Password required in connection URL");
816
+ console.error(" Example: postgresql://user:password@host:5432/db");
817
+ process.exit(1);
818
+ }
819
+ console.log("Creating connector...");
820
+ createPayload = {
821
+ name: connectorName,
822
+ service_name: "postgresql",
823
+ connection_details: {
824
+ host: parsed.host,
825
+ port: parsed.port,
826
+ username: parsed.username,
827
+ password: parsed.password
828
+ }
829
+ };
830
+ }
831
+ const created = await api.post("/v1/connectors", createPayload);
789
832
  const connectorId = created.id;
790
- console.log("Discovering schema...");
791
- await api.post(`/v1/connectors/${connectorId}/discover`, {});
792
- console.log("Setting selection...");
793
- await api.post(`/v1/connectors/${connectorId}/selection`, {
794
- selected_paths: ["*"]
795
- });
796
- const connector = await api.get(`/v1/connectors/${connectorId}`);
797
- if (connector.branching_engine_status === "configuration_verified") {
833
+ if (isByoc) {
798
834
  console.log("Setting up branching engine...");
799
- await api.post(`/v1/connectors/${connectorId}/engine-setup`, {});
835
+ try {
836
+ await api.post(`/v1/connectors/${connectorId}/engine-setup`, {});
837
+ } catch (setupErr) {
838
+ console.error("\u2717 Engine setup failed. To retry, delete and recreate:");
839
+ console.error(` ardent connector delete ${connectorName}`);
840
+ throw setupErr;
841
+ }
842
+ } else {
843
+ console.log("Discovering schema...");
844
+ await api.post(`/v1/connectors/${connectorId}/discover`, {});
845
+ console.log("Setting selection...");
846
+ await api.post(`/v1/connectors/${connectorId}/selection`, {
847
+ selected_paths: ["*"]
848
+ });
849
+ const connector = await api.get(`/v1/connectors/${connectorId}`);
850
+ if (connector.branching_engine_status === "configuration_verified") {
851
+ console.log("Setting up branching engine...");
852
+ await api.post(`/v1/connectors/${connectorId}/engine-setup`, {});
853
+ }
800
854
  }
855
+ const finalConnector = await api.get(`/v1/connectors/${connectorId}`);
801
856
  const newConnector = {
802
857
  id: connectorId,
803
858
  name: connectorName,
804
859
  service_name: "postgresql",
805
- status: connector.connection_status === "connected" ? "healthy" : "unknown"
860
+ status: finalConnector.branching_engine_status ?? finalConnector.connection_status ?? "pending"
806
861
  };
807
862
  const cached = getCacheEntry("connectors");
808
863
  const cachedConnectors = cached?.data || [];
@@ -924,7 +979,7 @@ async function deleteAction2(name) {
924
979
 
925
980
  // src/commands/connector/index.ts
926
981
  var connectorCommand = new Command2("connector").description("Manage database connectors");
927
- connectorCommand.command("create <type> <url>").description("Create a new connector").option("-n, --name <name>", "Connector name").action(createAction2);
982
+ connectorCommand.command("create <type> [url]").description("Create a new connector").option("-n, --name <name>", "Connector name").option("--byoc <provider>", "Bring your own Neon project (e.g. neon)").option("--api-key <key>", "Neon API key (required with --byoc)").option("--project-id <id>", "Neon project ID (required with --byoc)").action(createAction2);
928
983
  connectorCommand.command("list").description("List your connectors").action(listAction2);
929
984
  connectorCommand.command("delete <name>").description("Delete a connector by name").action(deleteAction2);
930
985
 
@@ -1182,12 +1237,25 @@ function logoutAction() {
1182
1237
  // src/commands/auth/status.ts
1183
1238
  function statusAction() {
1184
1239
  const token = getConfig("token");
1185
- if (token) {
1186
- console.log("\u2713 Authenticated");
1187
- console.log(` Token: ${token.slice(0, 8)}...${token.slice(-4)}`);
1188
- } else {
1240
+ if (!token) {
1189
1241
  console.log("\u2717 Not authenticated");
1190
1242
  console.log(" Run: ardent login");
1243
+ return;
1244
+ }
1245
+ const user = getConfig("user");
1246
+ console.log("\u2713 Authenticated");
1247
+ if (user?.full_name) {
1248
+ console.log(` Account: ${user.full_name}`);
1249
+ }
1250
+ if (user?.email) {
1251
+ console.log(` Email: ${user.email}`);
1252
+ }
1253
+ if (user?.org_name) {
1254
+ console.log(` Org: ${user.org_name}`);
1255
+ }
1256
+ if (!user) {
1257
+ console.log(` Token: ${token.slice(0, 8)}...${token.slice(-4)}`);
1258
+ console.log(" Run: ardent login to refresh profile info");
1191
1259
  }
1192
1260
  }
1193
1261
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ardent-cli",
3
- "version": "0.0.5",
3
+ "version": "0.0.8",
4
4
  "description": "Git for Data infrastructure",
5
5
  "type": "module",
6
6
  "bin": {