@positronic/cli 0.0.29 → 0.0.30

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/src/cli.js CHANGED
@@ -213,7 +213,7 @@ export function buildCli(options) {
213
213
  var projectCommand = new ProjectCommand();
214
214
  var brainCommand = new BrainCommand();
215
215
  var scheduleCommand = new ScheduleCommand();
216
- var secretCommand = new SecretCommand(server);
216
+ var secretCommand = new SecretCommand();
217
217
  var pagesCommand = new PagesCommand();
218
218
  // Main CLI definition
219
219
  var cli = yargs(argv).scriptName('positronic').usage('Usage: $0 <command> [options]').version(version).alias('v', 'version').help('h').alias('h', 'help').wrap(null).strictCommands().exitProcess(exitProcess);
@@ -17,19 +17,6 @@ function _create_class(Constructor, protoProps, staticProps) {
17
17
  if (staticProps) _defineProperties(Constructor, staticProps);
18
18
  return Constructor;
19
19
  }
20
- function _define_property(obj, key, value) {
21
- if (key in obj) {
22
- Object.defineProperty(obj, key, {
23
- value: value,
24
- enumerable: true,
25
- configurable: true,
26
- writable: true
27
- });
28
- } else {
29
- obj[key] = value;
30
- }
31
- return obj;
32
- }
33
20
  import React from 'react';
34
21
  import { SecretCreate } from '../components/secret-create.js';
35
22
  import { SecretList } from '../components/secret-list.js';
@@ -37,18 +24,14 @@ import { SecretDelete } from '../components/secret-delete.js';
37
24
  import { SecretBulk } from '../components/secret-bulk.js';
38
25
  export var SecretCommand = /*#__PURE__*/ function() {
39
26
  "use strict";
40
- function SecretCommand(server) {
27
+ function SecretCommand() {
41
28
  _class_call_check(this, SecretCommand);
42
- _define_property(this, "server", void 0);
43
- this.server = server;
44
29
  }
45
30
  _create_class(SecretCommand, [
46
31
  {
47
32
  key: "list",
48
33
  value: function list() {
49
- return React.createElement(SecretList, {
50
- server: this.server
51
- });
34
+ return React.createElement(SecretList);
52
35
  }
53
36
  },
54
37
  {
@@ -57,8 +40,7 @@ export var SecretCommand = /*#__PURE__*/ function() {
57
40
  var name = param.name, value = param.value;
58
41
  return React.createElement(SecretCreate, {
59
42
  name: name,
60
- value: value,
61
- server: this.server
43
+ value: value
62
44
  });
63
45
  }
64
46
  },
@@ -67,8 +49,7 @@ export var SecretCommand = /*#__PURE__*/ function() {
67
49
  value: function _delete(param) {
68
50
  var name = param.name;
69
51
  return React.createElement(SecretDelete, {
70
- name: name,
71
- server: this.server
52
+ name: name
72
53
  });
73
54
  }
74
55
  },
@@ -77,8 +58,7 @@ export var SecretCommand = /*#__PURE__*/ function() {
77
58
  value: function bulk(param) {
78
59
  var file = param.file;
79
60
  return React.createElement(SecretBulk, {
80
- file: file,
81
- server: this.server
61
+ file: file
82
62
  });
83
63
  }
84
64
  }
@@ -35,13 +35,6 @@ function _async_to_generator(fn) {
35
35
  });
36
36
  };
37
37
  }
38
- function _instanceof(left, right) {
39
- if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
40
- return !!right[Symbol.hasInstance](left);
41
- } else {
42
- return left instanceof right;
43
- }
44
- }
45
38
  function _iterable_to_array_limit(arr, i) {
46
39
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
47
40
  if (_i == null) return;
@@ -173,64 +166,82 @@ function _ts_generator(thisArg, body) {
173
166
  }
174
167
  import React, { useEffect, useState } from 'react';
175
168
  import { Text, Box } from 'ink';
169
+ import { ErrorComponent } from './error.js';
170
+ import { useApiPost } from '../hooks/useApi.js';
176
171
  import * as path from 'path';
177
172
  import * as fs from 'fs';
173
+ import { parse as parseEnv } from 'dotenv';
178
174
  export var SecretBulk = function(param) {
179
- var _param_file = param.file, file = _param_file === void 0 ? '.env' : _param_file, server = param.server;
180
- var _useState = _sliced_to_array(useState(true), 2), loading = _useState[0], setLoading = _useState[1];
181
- var _useState1 = _sliced_to_array(useState(null), 2), error = _useState1[0], setError = _useState1[1];
182
- var _useState2 = _sliced_to_array(useState(false), 2), completed = _useState2[0], setCompleted = _useState2[1];
175
+ var _param_file = param.file, file = _param_file === void 0 ? '.env' : _param_file, projectDir = param.projectDir;
176
+ var _useState = _sliced_to_array(useState(null), 2), validationError = _useState[0], setValidationError = _useState[1];
177
+ var _useState1 = _sliced_to_array(useState(false), 2), completed = _useState1[0], setCompleted = _useState1[1];
178
+ var _useState2 = _sliced_to_array(useState(null), 2), result = _useState2[0], setResult = _useState2[1];
179
+ var _useApiPost = useApiPost('/secrets/bulk', {
180
+ headers: {
181
+ 'Content-Type': 'application/json'
182
+ }
183
+ }), execute = _useApiPost.execute, loading = _useApiPost.loading, error = _useApiPost.error;
183
184
  useEffect(function() {
184
185
  var bulkUploadSecrets = function() {
185
186
  return _async_to_generator(function() {
186
- var filePath, error;
187
+ var basePath, filePath, content, parsed, secrets, body, response, err;
187
188
  return _ts_generator(this, function(_state) {
188
189
  switch(_state.label){
189
190
  case 0:
190
- if (!server) {
191
- setError('No server connection available');
192
- setLoading(false);
193
- return [
194
- 2
195
- ];
196
- }
197
- _state.label = 1;
198
- case 1:
199
191
  _state.trys.push([
200
- 1,
201
- 3,
192
+ 0,
193
+ 2,
202
194
  ,
203
- 4
195
+ 3
204
196
  ]);
205
- setLoading(true);
206
- setError(null);
207
- // Always read from .env file
208
- filePath = path.resolve(server.projectRootDir, file);
197
+ // Resolve the file path - use projectDir, env var, or cwd
198
+ basePath = projectDir || process.env.POSITRONIC_CONFIG_DIR || process.cwd();
199
+ filePath = path.resolve(basePath, file);
209
200
  if (!fs.existsSync(filePath)) {
210
- throw new Error("No .env file found at ".concat(filePath, "\n\n") + 'To use this command, create a .env file in your project root with your secrets:\n' + ' ANTHROPIC_API_KEY=sk-ant-...\n' + ' DATABASE_URL=postgres://...\n' + ' REDIS_URL=redis://...');
201
+ setValidationError("No .env file found at ".concat(filePath, "\n\n") + 'To use this command, create a .env file in your project root with your secrets:\n' + ' ANTHROPIC_API_KEY=sk-ant-...\n' + ' DATABASE_URL=postgres://...\n' + ' REDIS_URL=redis://...');
202
+ return [
203
+ 2
204
+ ];
211
205
  }
212
- // Pass the file path to the backend
206
+ // Read and parse the env file using dotenv
207
+ content = fs.readFileSync(filePath, 'utf-8');
208
+ parsed = parseEnv(content);
209
+ secrets = Object.entries(parsed).map(function(param) {
210
+ var _param = _sliced_to_array(param, 2), name = _param[0], value = _param[1];
211
+ return {
212
+ name: name,
213
+ value: value
214
+ };
215
+ });
216
+ if (secrets.length === 0) {
217
+ setValidationError("No secrets found in ".concat(filePath, "\n\n") + 'Make sure your .env file contains key=value pairs:\n' + ' ANTHROPIC_API_KEY=sk-ant-...\n' + ' DATABASE_URL=postgres://...');
218
+ return [
219
+ 2
220
+ ];
221
+ }
222
+ // Send to API
223
+ body = JSON.stringify({
224
+ secrets: secrets
225
+ });
213
226
  return [
214
227
  4,
215
- server.bulkSecrets(filePath)
228
+ execute(body)
216
229
  ];
217
- case 2:
218
- _state.sent();
230
+ case 1:
231
+ response = _state.sent();
232
+ setResult(response);
219
233
  setCompleted(true);
220
- setLoading(false);
221
234
  return [
222
235
  3,
223
- 4
236
+ 3
224
237
  ];
225
- case 3:
226
- error = _state.sent();
227
- setError(_instanceof(error, Error) ? error.message : 'Failed to bulk upload secrets');
228
- setLoading(false);
238
+ case 2:
239
+ err = _state.sent();
229
240
  return [
230
241
  3,
231
- 4
242
+ 3
232
243
  ];
233
- case 4:
244
+ case 3:
234
245
  return [
235
246
  2
236
247
  ];
@@ -239,24 +250,43 @@ export var SecretBulk = function(param) {
239
250
  })();
240
251
  };
241
252
  bulkUploadSecrets();
242
- }, [
243
- file,
244
- server
245
- ]);
246
- if (error) {
253
+ }, []);
254
+ if (validationError) {
247
255
  return /*#__PURE__*/ React.createElement(Box, {
248
256
  flexDirection: "column"
249
257
  }, /*#__PURE__*/ React.createElement(Text, {
250
258
  color: "red"
251
- }, "❌ Error: ", error));
259
+ }, validationError));
260
+ }
261
+ if (error) {
262
+ return /*#__PURE__*/ React.createElement(ErrorComponent, {
263
+ error: error
264
+ });
252
265
  }
253
266
  if (loading) {
254
- return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "\uD83D\uDD04 Uploading secrets", file ? " from ".concat(file) : ' from stdin', "..."));
267
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "Uploading secrets from ", file, "..."));
255
268
  }
256
- if (completed) {
257
- // The bulk command itself outputs success message to console
258
- // We just need to ensure the component renders something to prevent React errors
259
- return /*#__PURE__*/ React.createElement(Box, null);
269
+ if (completed && result) {
270
+ var total = result.created + result.updated;
271
+ return /*#__PURE__*/ React.createElement(Box, {
272
+ flexDirection: "column"
273
+ }, /*#__PURE__*/ React.createElement(Text, {
274
+ color: "green"
275
+ }, "Secrets uploaded successfully!"), /*#__PURE__*/ React.createElement(Box, {
276
+ marginTop: 1,
277
+ paddingLeft: 2,
278
+ flexDirection: "column"
279
+ }, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
280
+ bold: true
281
+ }, "Total:"), " ", total), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
282
+ bold: true
283
+ }, "Created:"), " ", result.created), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
284
+ bold: true
285
+ }, "Updated:"), " ", result.updated)), /*#__PURE__*/ React.createElement(Box, {
286
+ marginTop: 1
287
+ }, /*#__PURE__*/ React.createElement(Text, {
288
+ dimColor: true
289
+ }, 'Tip: Use "px secret list" to view all secrets')));
260
290
  }
261
291
  return null;
262
292
  };
@@ -1,3 +1,11 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
1
9
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
10
  try {
3
11
  var info = gen[key](arg);
@@ -27,6 +35,44 @@ function _async_to_generator(fn) {
27
35
  });
28
36
  };
29
37
  }
38
+ function _iterable_to_array_limit(arr, i) {
39
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
40
+ if (_i == null) return;
41
+ var _arr = [];
42
+ var _n = true;
43
+ var _d = false;
44
+ var _s, _e;
45
+ try {
46
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
47
+ _arr.push(_s.value);
48
+ if (i && _arr.length === i) break;
49
+ }
50
+ } catch (err) {
51
+ _d = true;
52
+ _e = err;
53
+ } finally{
54
+ try {
55
+ if (!_n && _i["return"] != null) _i["return"]();
56
+ } finally{
57
+ if (_d) throw _e;
58
+ }
59
+ }
60
+ return _arr;
61
+ }
62
+ function _non_iterable_rest() {
63
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
64
+ }
65
+ function _sliced_to_array(arr, i) {
66
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
67
+ }
68
+ function _unsupported_iterable_to_array(o, minLen) {
69
+ if (!o) return;
70
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
71
+ var n = Object.prototype.toString.call(o).slice(8, -1);
72
+ if (n === "Object" && o.constructor) n = o.constructor.name;
73
+ if (n === "Map" || n === "Set") return Array.from(n);
74
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
75
+ }
30
76
  function _ts_generator(thisArg, body) {
31
77
  var f, y, t, _ = {
32
78
  label: 0,
@@ -118,36 +164,29 @@ function _ts_generator(thisArg, body) {
118
164
  };
119
165
  }
120
166
  }
121
- import React, { useEffect } from 'react';
122
- import { useApp } from 'ink';
167
+ import React, { useState, useEffect } from 'react';
168
+ import { Box, Text } from 'ink';
169
+ import { ErrorComponent } from './error.js';
170
+ import { useApiPost } from '../hooks/useApi.js';
123
171
  export var SecretCreate = function(param) {
124
- var name = param.name, providedValue = param.value, server = param.server;
125
- var exit = useApp().exit;
172
+ var name = param.name, value = param.value;
173
+ var _useState = _sliced_to_array(useState(false), 2), created = _useState[0], setCreated = _useState[1];
174
+ var _useState1 = _sliced_to_array(useState(null), 2), secret = _useState1[0], setSecret = _useState1[1];
175
+ var _useState2 = _sliced_to_array(useState(null), 2), validationError = _useState2[0], setValidationError = _useState2[1];
176
+ var _useApiPost = useApiPost('/secrets', {
177
+ headers: {
178
+ 'Content-Type': 'application/json'
179
+ }
180
+ }), execute = _useApiPost.execute, loading = _useApiPost.loading, error = _useApiPost.error;
126
181
  useEffect(function() {
127
182
  var createSecret = function() {
128
183
  return _async_to_generator(function() {
129
- var err;
184
+ var body, result, err;
130
185
  return _ts_generator(this, function(_state) {
131
186
  switch(_state.label){
132
187
  case 0:
133
- if (!server) {
134
- console.error('No project found. Please run this command from within a Positronic project directory.');
135
- exit();
136
- return [
137
- 2
138
- ];
139
- }
140
- if (!server.setSecret) {
141
- console.error('Secret management not supported for this backend');
142
- exit();
143
- return [
144
- 2
145
- ];
146
- }
147
- // If no value provided, backend will prompt for it
148
- if (!providedValue) {
149
- console.error('Please provide a value using --value flag');
150
- exit();
188
+ if (!value) {
189
+ setValidationError('Please provide a value using --value flag');
151
190
  return [
152
191
  2
153
192
  ];
@@ -160,21 +199,24 @@ export var SecretCreate = function(param) {
160
199
  ,
161
200
  4
162
201
  ]);
202
+ body = JSON.stringify({
203
+ name: name,
204
+ value: value
205
+ });
163
206
  return [
164
207
  4,
165
- server.setSecret(name, providedValue)
208
+ execute(body)
166
209
  ];
167
210
  case 2:
168
- _state.sent();
169
- exit();
211
+ result = _state.sent();
212
+ setSecret(result);
213
+ setCreated(true);
170
214
  return [
171
215
  3,
172
216
  4
173
217
  ];
174
218
  case 3:
175
219
  err = _state.sent();
176
- // Error was already printed by backend
177
- exit();
178
220
  return [
179
221
  3,
180
222
  4
@@ -188,12 +230,42 @@ export var SecretCreate = function(param) {
188
230
  })();
189
231
  };
190
232
  createSecret();
191
- }, [
192
- name,
193
- providedValue,
194
- server,
195
- exit
196
- ]);
197
- // This won't be shown because backend output is printed directly
233
+ }, []);
234
+ if (validationError) {
235
+ return /*#__PURE__*/ React.createElement(Box, {
236
+ flexDirection: "column"
237
+ }, /*#__PURE__*/ React.createElement(Text, {
238
+ color: "red"
239
+ }, validationError), /*#__PURE__*/ React.createElement(Box, {
240
+ marginTop: 1
241
+ }, /*#__PURE__*/ React.createElement(Text, {
242
+ dimColor: true
243
+ }, "Example: px secret create ", name, " --value=my-secret-value")));
244
+ }
245
+ if (error) {
246
+ return /*#__PURE__*/ React.createElement(ErrorComponent, {
247
+ error: error
248
+ });
249
+ }
250
+ if (loading) {
251
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "Creating secret..."));
252
+ }
253
+ if (created && secret) {
254
+ return /*#__PURE__*/ React.createElement(Box, {
255
+ flexDirection: "column"
256
+ }, /*#__PURE__*/ React.createElement(Text, {
257
+ color: "green"
258
+ }, "Secret created successfully!"), /*#__PURE__*/ React.createElement(Box, {
259
+ marginTop: 1,
260
+ paddingLeft: 2,
261
+ flexDirection: "column"
262
+ }, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
263
+ bold: true
264
+ }, "Name:"), " ", secret.name)), /*#__PURE__*/ React.createElement(Box, {
265
+ marginTop: 1
266
+ }, /*#__PURE__*/ React.createElement(Text, {
267
+ dimColor: true
268
+ }, 'Tip: Use "px secret list" to view all secrets')));
269
+ }
198
270
  return null;
199
271
  };
@@ -1,3 +1,11 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
1
9
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
10
  try {
3
11
  var info = gen[key](arg);
@@ -27,6 +35,44 @@ function _async_to_generator(fn) {
27
35
  });
28
36
  };
29
37
  }
38
+ function _iterable_to_array_limit(arr, i) {
39
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
40
+ if (_i == null) return;
41
+ var _arr = [];
42
+ var _n = true;
43
+ var _d = false;
44
+ var _s, _e;
45
+ try {
46
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
47
+ _arr.push(_s.value);
48
+ if (i && _arr.length === i) break;
49
+ }
50
+ } catch (err) {
51
+ _d = true;
52
+ _e = err;
53
+ } finally{
54
+ try {
55
+ if (!_n && _i["return"] != null) _i["return"]();
56
+ } finally{
57
+ if (_d) throw _e;
58
+ }
59
+ }
60
+ return _arr;
61
+ }
62
+ function _non_iterable_rest() {
63
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
64
+ }
65
+ function _sliced_to_array(arr, i) {
66
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
67
+ }
68
+ function _unsupported_iterable_to_array(o, minLen) {
69
+ if (!o) return;
70
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
71
+ var n = Object.prototype.toString.call(o).slice(8, -1);
72
+ if (n === "Object" && o.constructor) n = o.constructor.name;
73
+ if (n === "Map" || n === "Set") return Array.from(n);
74
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
75
+ }
30
76
  function _ts_generator(thisArg, body) {
31
77
  var f, y, t, _ = {
32
78
  label: 0,
@@ -118,11 +164,14 @@ function _ts_generator(thisArg, body) {
118
164
  };
119
165
  }
120
166
  }
121
- import React, { useEffect } from 'react';
122
- import { useApp } from 'ink';
167
+ import React, { useState, useEffect } from 'react';
168
+ import { Box, Text } from 'ink';
169
+ import { ErrorComponent } from './error.js';
170
+ import { useApiDelete } from '../hooks/useApi.js';
123
171
  export var SecretDelete = function(param) {
124
- var name = param.name, server = param.server;
125
- var exit = useApp().exit;
172
+ var name = param.name;
173
+ var _useState = _sliced_to_array(useState(false), 2), deleted = _useState[0], setDeleted = _useState[1];
174
+ var _useApiDelete = useApiDelete('secret'), execute = _useApiDelete.execute, loading = _useApiDelete.loading, error = _useApiDelete.error;
126
175
  useEffect(function() {
127
176
  var deleteSecret = function() {
128
177
  return _async_to_generator(function() {
@@ -130,48 +179,30 @@ export var SecretDelete = function(param) {
130
179
  return _ts_generator(this, function(_state) {
131
180
  switch(_state.label){
132
181
  case 0:
133
- if (!server) {
134
- console.error('No project found. Please run this command from within a Positronic project directory.');
135
- exit();
136
- return [
137
- 2
138
- ];
139
- }
140
- if (!server.deleteSecret) {
141
- console.error('Secret management not supported for this backend');
142
- exit();
143
- return [
144
- 2
145
- ];
146
- }
147
- _state.label = 1;
148
- case 1:
149
182
  _state.trys.push([
150
- 1,
151
- 3,
183
+ 0,
184
+ 2,
152
185
  ,
153
- 4
186
+ 3
154
187
  ]);
155
188
  return [
156
189
  4,
157
- server.deleteSecret(name)
190
+ execute("/secrets/".concat(encodeURIComponent(name)))
158
191
  ];
159
- case 2:
192
+ case 1:
160
193
  _state.sent();
161
- exit();
194
+ setDeleted(true);
162
195
  return [
163
196
  3,
164
- 4
197
+ 3
165
198
  ];
166
- case 3:
199
+ case 2:
167
200
  err = _state.sent();
168
- // Error was already printed by backend
169
- exit();
170
201
  return [
171
202
  3,
172
- 4
203
+ 3
173
204
  ];
174
- case 4:
205
+ case 3:
175
206
  return [
176
207
  2
177
208
  ];
@@ -180,11 +211,26 @@ export var SecretDelete = function(param) {
180
211
  })();
181
212
  };
182
213
  deleteSecret();
183
- }, [
184
- name,
185
- server,
186
- exit
187
- ]);
188
- // This won't be shown because backend output is printed directly
214
+ }, []);
215
+ if (error) {
216
+ return /*#__PURE__*/ React.createElement(ErrorComponent, {
217
+ error: error
218
+ });
219
+ }
220
+ if (loading) {
221
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "Deleting secret..."));
222
+ }
223
+ if (deleted) {
224
+ return /*#__PURE__*/ React.createElement(Box, {
225
+ flexDirection: "column"
226
+ }, /*#__PURE__*/ React.createElement(Text, {
227
+ color: "green"
228
+ }, "Secret deleted successfully!"), /*#__PURE__*/ React.createElement(Box, {
229
+ marginTop: 1,
230
+ paddingLeft: 2
231
+ }, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
232
+ bold: true
233
+ }, "Name:"), " ", name)));
234
+ }
189
235
  return null;
190
236
  };
@@ -1,190 +1,106 @@
1
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
- try {
3
- var info = gen[key](arg);
4
- var value = info.value;
5
- } catch (error) {
6
- reject(error);
7
- return;
8
- }
9
- if (info.done) {
10
- resolve(value);
11
- } else {
12
- Promise.resolve(value).then(_next, _throw);
13
- }
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
14
5
  }
15
- function _async_to_generator(fn) {
16
- return function() {
17
- var self = this, args = arguments;
18
- return new Promise(function(resolve, reject) {
19
- var gen = fn.apply(self, args);
20
- function _next(value) {
21
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
- }
23
- function _throw(err) {
24
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
- }
26
- _next(undefined);
27
- });
28
- };
6
+ function _array_without_holes(arr) {
7
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
29
8
  }
30
- function _ts_generator(thisArg, body) {
31
- var f, y, t, _ = {
32
- label: 0,
33
- sent: function() {
34
- if (t[0] & 1) throw t[1];
35
- return t[1];
36
- },
37
- trys: [],
38
- ops: []
39
- }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
40
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
41
- return this;
42
- }), g;
43
- function verb(n) {
44
- return function(v) {
45
- return step([
46
- n,
47
- v
48
- ]);
49
- };
9
+ function _iterable_to_array(iter) {
10
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
11
+ }
12
+ function _non_iterable_spread() {
13
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
14
+ }
15
+ function _to_consumable_array(arr) {
16
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
17
+ }
18
+ function _unsupported_iterable_to_array(o, minLen) {
19
+ if (!o) return;
20
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
21
+ var n = Object.prototype.toString.call(o).slice(8, -1);
22
+ if (n === "Object" && o.constructor) n = o.constructor.name;
23
+ if (n === "Map" || n === "Set") return Array.from(n);
24
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
25
+ }
26
+ import React from 'react';
27
+ import { Box, Text } from 'ink';
28
+ import { ErrorComponent } from './error.js';
29
+ import { useApiGet } from '../hooks/useApi.js';
30
+ // Helper to truncate text to fit column width
31
+ var truncate = function(text, maxWidth) {
32
+ if (text.length <= maxWidth) return text;
33
+ return text.substring(0, maxWidth - 3) + '...';
34
+ };
35
+ // Helper to pad text to column width
36
+ var padRight = function(text, width) {
37
+ return text + ' '.repeat(Math.max(0, width - text.length));
38
+ };
39
+ // Helper to format dates consistently
40
+ var formatDate = function(dateStr) {
41
+ var date = new Date(dateStr);
42
+ return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
43
+ };
44
+ export var SecretList = function() {
45
+ var _useApiGet = useApiGet('/secrets'), data = _useApiGet.data, loading = _useApiGet.loading, error = _useApiGet.error;
46
+ if (error) {
47
+ return /*#__PURE__*/ React.createElement(ErrorComponent, {
48
+ error: error
49
+ });
50
50
  }
51
- function step(op) {
52
- if (f) throw new TypeError("Generator is already executing.");
53
- while(g && (g = 0, op[0] && (_ = 0)), _)try {
54
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
55
- if (y = 0, t) op = [
56
- op[0] & 2,
57
- t.value
58
- ];
59
- switch(op[0]){
60
- case 0:
61
- case 1:
62
- t = op;
63
- break;
64
- case 4:
65
- _.label++;
66
- return {
67
- value: op[1],
68
- done: false
69
- };
70
- case 5:
71
- _.label++;
72
- y = op[1];
73
- op = [
74
- 0
75
- ];
76
- continue;
77
- case 7:
78
- op = _.ops.pop();
79
- _.trys.pop();
80
- continue;
81
- default:
82
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
83
- _ = 0;
84
- continue;
85
- }
86
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
87
- _.label = op[1];
88
- break;
89
- }
90
- if (op[0] === 6 && _.label < t[1]) {
91
- _.label = t[1];
92
- t = op;
93
- break;
94
- }
95
- if (t && _.label < t[2]) {
96
- _.label = t[2];
97
- _.ops.push(op);
98
- break;
99
- }
100
- if (t[2]) _.ops.pop();
101
- _.trys.pop();
102
- continue;
103
- }
104
- op = body.call(thisArg, _);
105
- } catch (e) {
106
- op = [
107
- 6,
108
- e
109
- ];
110
- y = 0;
111
- } finally{
112
- f = t = 0;
113
- }
114
- if (op[0] & 5) throw op[1];
115
- return {
116
- value: op[0] ? op[1] : void 0,
117
- done: true
118
- };
51
+ if (loading) {
52
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "Loading secrets..."));
119
53
  }
120
- }
121
- import React, { useEffect } from 'react';
122
- import { useApp } from 'ink';
123
- export var SecretList = function(param) {
124
- var server = param.server;
125
- var exit = useApp().exit;
126
- useEffect(function() {
127
- var loadSecrets = function() {
128
- return _async_to_generator(function() {
129
- var err;
130
- return _ts_generator(this, function(_state) {
131
- switch(_state.label){
132
- case 0:
133
- if (!server) {
134
- console.error('No project found. Please run this command from within a Positronic project directory.');
135
- exit();
136
- return [
137
- 2
138
- ];
139
- }
140
- if (!server.listSecrets) {
141
- console.error('Secret management not supported for this backend');
142
- exit();
143
- return [
144
- 2
145
- ];
146
- }
147
- _state.label = 1;
148
- case 1:
149
- _state.trys.push([
150
- 1,
151
- 3,
152
- ,
153
- 4
154
- ]);
155
- // listSecrets will print output directly via stdio: 'inherit'
156
- return [
157
- 4,
158
- server.listSecrets()
159
- ];
160
- case 2:
161
- _state.sent();
162
- exit();
163
- return [
164
- 3,
165
- 4
166
- ];
167
- case 3:
168
- err = _state.sent();
169
- // Error was already printed by backend
170
- exit();
171
- return [
172
- 3,
173
- 4
174
- ];
175
- case 4:
176
- return [
177
- 2
178
- ];
179
- }
180
- });
181
- })();
182
- };
183
- loadSecrets();
184
- }, [
185
- server,
186
- exit
187
- ]);
188
- // This won't be shown because backend output is printed directly
189
- return null;
54
+ if (!data || data.secrets.length === 0) {
55
+ return /*#__PURE__*/ React.createElement(Box, {
56
+ flexDirection: "column"
57
+ }, /*#__PURE__*/ React.createElement(Text, null, "No secrets found."), /*#__PURE__*/ React.createElement(Box, {
58
+ marginTop: 1
59
+ }, /*#__PURE__*/ React.createElement(Text, {
60
+ dimColor: true
61
+ }, 'Tip: Create a secret with "px secret create <name> --value=<value>"')));
62
+ }
63
+ // Define column widths
64
+ var columns = {
65
+ name: {
66
+ header: 'Name',
67
+ width: 30
68
+ },
69
+ updatedAt: {
70
+ header: 'Updated',
71
+ width: 25
72
+ }
73
+ };
74
+ // Calculate total width for separator
75
+ var totalWidth = Object.values(columns).reduce(function(sum, col) {
76
+ return sum + col.width + 2;
77
+ }, 0) - 2;
78
+ // Sort secrets by name
79
+ var sortedSecrets = _to_consumable_array(data.secrets).sort(function(a, b) {
80
+ return a.name.localeCompare(b.name);
81
+ });
82
+ return /*#__PURE__*/ React.createElement(Box, {
83
+ flexDirection: "column",
84
+ paddingTop: 1,
85
+ paddingBottom: 1
86
+ }, /*#__PURE__*/ React.createElement(Text, {
87
+ bold: true
88
+ }, "Found ", data.count, " secret", data.count === 1 ? '' : 's', ":"), /*#__PURE__*/ React.createElement(Box, {
89
+ marginTop: 1,
90
+ flexDirection: "column"
91
+ }, /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
92
+ bold: true,
93
+ color: "cyan"
94
+ }, padRight(columns.name.header, columns.name.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
95
+ bold: true,
96
+ color: "cyan"
97
+ }, padRight(columns.updatedAt.header, columns.updatedAt.width))), /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
98
+ dimColor: true
99
+ }, '─'.repeat(totalWidth))), sortedSecrets.map(function(secret) {
100
+ return /*#__PURE__*/ React.createElement(Box, {
101
+ key: secret.name
102
+ }, /*#__PURE__*/ React.createElement(Text, null, padRight(truncate(secret.name, columns.name.width), columns.name.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
103
+ dimColor: true
104
+ }, padRight(formatDate(secret.updatedAt), columns.updatedAt.width)));
105
+ })));
190
106
  };
@@ -1,6 +1,5 @@
1
1
  import type { ArgumentsCamelCase } from 'yargs';
2
2
  import React from 'react';
3
- import type { PositronicDevServer } from '@positronic/spec';
4
3
  interface SecretCreateArgs {
5
4
  name: string;
6
5
  value?: string;
@@ -12,8 +11,6 @@ interface SecretBulkArgs {
12
11
  file?: string;
13
12
  }
14
13
  export declare class SecretCommand {
15
- private server?;
16
- constructor(server?: PositronicDevServer | undefined);
17
14
  list(): React.ReactElement;
18
15
  create({ name, value, }: ArgumentsCamelCase<SecretCreateArgs>): React.ReactElement;
19
16
  delete({ name }: ArgumentsCamelCase<SecretDeleteArgs>): React.ReactElement;
@@ -1 +1 @@
1
- {"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../../../src/commands/secret.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAM5D,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,MAAM,CAAC;gBAAP,MAAM,CAAC,EAAE,mBAAmB,YAAA;IAEhD,IAAI,IAAI,KAAK,CAAC,YAAY;IAI1B,MAAM,CAAC,EACL,IAAI,EACJ,KAAK,GACN,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC,YAAY;IAQ5D,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC,YAAY;IAI1E,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,kBAAkB,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY;CAMvE"}
1
+ {"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../../../src/commands/secret.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,aAAa;IACxB,IAAI,IAAI,KAAK,CAAC,YAAY;IAI1B,MAAM,CAAC,EACL,IAAI,EACJ,KAAK,GACN,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC,YAAY;IAO5D,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC,YAAY;IAI1E,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,kBAAkB,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY;CAGvE"}
@@ -1,8 +1,7 @@
1
- import type { PositronicDevServer } from '@positronic/spec';
2
1
  interface SecretBulkProps {
3
2
  file?: string;
4
- server?: PositronicDevServer;
3
+ projectDir?: string;
5
4
  }
6
- export declare const SecretBulk: ({ file, server }: SecretBulkProps) => import("react/jsx-runtime").JSX.Element | null;
5
+ export declare const SecretBulk: ({ file, projectDir }: SecretBulkProps) => import("react/jsx-runtime").JSX.Element | null;
7
6
  export {};
8
7
  //# sourceMappingURL=secret-bulk.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"secret-bulk.d.ts","sourceRoot":"","sources":["../../../src/components/secret-bulk.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAI5D,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,eAAO,MAAM,UAAU,GAAI,kBAA2B,eAAe,mDAmEpE,CAAC"}
1
+ {"version":3,"file":"secret-bulk.d.ts","sourceRoot":"","sources":["../../../src/components/secret-bulk.tsx"],"names":[],"mappings":"AAQA,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,eAAO,MAAM,UAAU,GAAI,sBAA+B,eAAe,mDAwGxE,CAAC"}
@@ -1,9 +1,7 @@
1
- import type { PositronicDevServer } from '@positronic/spec';
2
1
  interface SecretCreateProps {
3
2
  name: string;
4
3
  value?: string;
5
- server?: PositronicDevServer;
6
4
  }
7
- export declare const SecretCreate: ({ name, value: providedValue, server }: SecretCreateProps) => null;
5
+ export declare const SecretCreate: ({ name, value }: SecretCreateProps) => import("react/jsx-runtime").JSX.Element | null;
8
6
  export {};
9
7
  //# sourceMappingURL=secret-create.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"secret-create.d.ts","sourceRoot":"","sources":["../../../src/components/secret-create.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,eAAO,MAAM,YAAY,GAAI,wCAAwC,iBAAiB,SAsCrF,CAAC"}
1
+ {"version":3,"file":"secret-create.d.ts","sourceRoot":"","sources":["../../../src/components/secret-create.tsx"],"names":[],"mappings":"AAKA,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,eAAO,MAAM,YAAY,GAAI,iBAAiB,iBAAiB,mDA2E9D,CAAC"}
@@ -1,8 +1,6 @@
1
- import type { PositronicDevServer } from '@positronic/spec';
2
1
  interface SecretDeleteProps {
3
2
  name: string;
4
- server?: PositronicDevServer;
5
3
  }
6
- export declare const SecretDelete: ({ name, server }: SecretDeleteProps) => null;
4
+ export declare const SecretDelete: ({ name }: SecretDeleteProps) => import("react/jsx-runtime").JSX.Element | null;
7
5
  export {};
8
6
  //# sourceMappingURL=secret-delete.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"secret-delete.d.ts","sourceRoot":"","sources":["../../../src/components/secret-delete.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,eAAO,MAAM,YAAY,GAAI,kBAAkB,iBAAiB,SA+B/D,CAAC"}
1
+ {"version":3,"file":"secret-delete.d.ts","sourceRoot":"","sources":["../../../src/components/secret-delete.tsx"],"names":[],"mappings":"AAKA,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,YAAY,GAAI,UAAU,iBAAiB,mDA4CvD,CAAC"}
@@ -1,7 +1,2 @@
1
- import type { PositronicDevServer } from '@positronic/spec';
2
- interface SecretListProps {
3
- server?: PositronicDevServer;
4
- }
5
- export declare const SecretList: ({ server }: SecretListProps) => null;
6
- export {};
1
+ export declare const SecretList: () => import("react/jsx-runtime").JSX.Element;
7
2
  //# sourceMappingURL=secret-list.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"secret-list.d.ts","sourceRoot":"","sources":["../../../src/components/secret-list.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,eAAO,MAAM,UAAU,GAAI,YAAY,eAAe,SAgCrD,CAAC"}
1
+ {"version":3,"file":"secret-list.d.ts","sourceRoot":"","sources":["../../../src/components/secret-list.tsx"],"names":[],"mappings":"AAiCA,eAAO,MAAM,UAAU,+CAsEtB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@positronic/cli",
3
- "version": "0.0.29",
3
+ "version": "0.0.30",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -23,11 +23,12 @@
23
23
  "clean": "rm -rf tsconfig.tsbuildinfo dist node_modules"
24
24
  },
25
25
  "dependencies": {
26
- "@positronic/core": "^0.0.29",
27
- "@positronic/spec": "^0.0.29",
28
- "@positronic/template-new-project": "^0.0.29",
26
+ "@positronic/core": "^0.0.30",
27
+ "@positronic/spec": "^0.0.30",
28
+ "@positronic/template-new-project": "^0.0.30",
29
29
  "caz": "^2.0.0",
30
30
  "chokidar": "^3.6.0",
31
+ "dotenv": "^16.4.7",
31
32
  "eventsource": "^3.0.6",
32
33
  "ink": "^5.2.1",
33
34
  "istextorbinary": "^9.5.0",