@tothalex/nulljs 0.0.59 → 0.0.60

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/cli.js +268 -199
  2. package/package.json +4 -4
package/dist/cli.js CHANGED
@@ -52,113 +52,6 @@ var buildUrl = (path, options) => {
52
52
  // ../../packages/api/actions/deployments.ts
53
53
  var init_deployments = () => {};
54
54
 
55
- // ../../packages/api/actions/deploy.ts
56
- import { mkdtempSync, writeFileSync, rmSync } from "fs";
57
- import { tmpdir } from "os";
58
- import { join } from "path";
59
- var {$ } = globalThis.Bun;
60
- var getMimeType = (fileName) => {
61
- if (fileName.endsWith(".js"))
62
- return "application/javascript";
63
- if (fileName.endsWith(".css"))
64
- return "text/css";
65
- if (fileName.endsWith(".html"))
66
- return "text/html";
67
- if (fileName.endsWith(".json"))
68
- return "application/json";
69
- return "application/octet-stream";
70
- }, createFormDataWithInfo = (assets2) => {
71
- const form = new FormData;
72
- const blobs = [];
73
- for (const asset of assets2) {
74
- const mime = getMimeType(asset.fileName);
75
- const buffer = Buffer.from(asset.code);
76
- const blob = new Blob([buffer], { type: mime });
77
- form.append(asset.fileName, blob);
78
- blobs.push({ fileName: asset.fileName, size: blob.size, type: mime });
79
- }
80
- return { form, blobs };
81
- }, createSignature = async (blobs, privateKey) => {
82
- const sortedBlobs = [...blobs].sort((a, b) => a.fileName.localeCompare(b.fileName));
83
- const dataString = sortedBlobs.map((b) => `${b.fileName}:${b.size}:${b.type}`).join("|");
84
- const sign = await crypto.subtle.sign("Ed25519", privateKey, Buffer.from(dataString));
85
- return btoa(String.fromCharCode(...new Uint8Array(sign)));
86
- }, postWithCurl = async (url, signature, assets2) => {
87
- const tempDir = mkdtempSync(join(tmpdir(), "nulljs-deploy-"));
88
- try {
89
- const formParts = [];
90
- for (const asset of assets2) {
91
- const filePath = join(tempDir, asset.fileName);
92
- writeFileSync(filePath, asset.code);
93
- const mime = getMimeType(asset.fileName);
94
- formParts.push(`-F`);
95
- formParts.push(`${asset.fileName}=@${filePath};type=${mime}`);
96
- }
97
- const result = await $`curl -s -w '\n%{http_code}' -X POST -H "authorization: ${signature}" ${formParts} ${url}`.text();
98
- const lines = result.trim().split(`
99
- `);
100
- const statusCode = parseInt(lines.pop() || "0", 10);
101
- const body = lines.join(`
102
- `);
103
- return { ok: statusCode >= 200 && statusCode < 300, status: statusCode, text: body };
104
- } finally {
105
- rmSync(tempDir, { recursive: true, force: true });
106
- }
107
- }, createFunctionDeployment = async (deployment2, options) => {
108
- const handler = deployment2.assets.find((asset) => asset.fileName === "handler.js");
109
- if (!handler) {
110
- throw new Error(`Handler not found for ${deployment2.name}`);
111
- }
112
- const { blobs } = createFormDataWithInfo([handler]);
113
- const signature = await createSignature(blobs, options.privateKey);
114
- const baseUrl = options.url || "";
115
- const url = `${baseUrl}/api/deployment`;
116
- if (options.useCurl) {
117
- const result = await postWithCurl(url, signature, [handler]);
118
- if (!result.ok) {
119
- throw new Error(`Deployment failed (${result.status}): ${result.text}`);
120
- }
121
- return;
122
- }
123
- const { form } = createFormDataWithInfo([handler]);
124
- const response = await fetch(url, {
125
- method: "POST",
126
- headers: {
127
- authorization: signature
128
- },
129
- body: form
130
- });
131
- if (!response.ok) {
132
- const errorText = await response.text();
133
- throw new Error(`Deployment failed (${response.status}): ${errorText}`);
134
- }
135
- }, createReactDeployment = async (deployment2, options) => {
136
- const { blobs } = createFormDataWithInfo(deployment2.assets);
137
- const signature = await createSignature(blobs, options.privateKey);
138
- const baseUrl = options.url || "";
139
- const url = `${baseUrl}/api/deployment/react`;
140
- if (options.useCurl) {
141
- const result = await postWithCurl(url, signature, deployment2.assets);
142
- if (!result.ok) {
143
- throw new Error(`Deployment failed (${result.status}): ${result.text}`);
144
- }
145
- return;
146
- }
147
- const { form } = createFormDataWithInfo(deployment2.assets);
148
- const response = await fetch(url, {
149
- method: "POST",
150
- headers: {
151
- authorization: signature
152
- },
153
- body: form
154
- });
155
- if (!response.ok) {
156
- const errorText = await response.text();
157
- throw new Error(`Deployment failed (${response.status}): ${errorText}`);
158
- }
159
- };
160
- var init_deploy = () => {};
161
-
162
55
  // ../../packages/api/actions/invocations.ts
163
56
  var init_invocations = () => {};
164
57
 
@@ -178,68 +71,9 @@ var init_assets = () => {};
178
71
  // ../../packages/api/actions/activity.ts
179
72
  var init_activity = () => {};
180
73
 
181
- // ../../packages/api/actions/secrets.ts
182
- var createSignatureHeader = async (privateKey, props) => {
183
- const timestamp = new Date().toISOString();
184
- const raw = `${props.method}-${props.path}-${timestamp}${props.body ? "-" + props.body : ""}`;
185
- const sign = await crypto.subtle.sign("Ed25519", privateKey, Buffer.from(raw));
186
- const signature = btoa(String.fromCharCode(...new Uint8Array(sign)));
187
- const header = {
188
- authorization: signature,
189
- "x-time": timestamp
190
- };
191
- if (props.body) {
192
- header["x-body"] = btoa(props.body);
193
- }
194
- return header;
195
- }, listSecrets = async (options) => {
196
- const baseUrl = options.url || "";
197
- const path = `${baseUrl}/api/secrets`;
198
- const headers = await createSignatureHeader(options.privateKey, {
199
- method: "GET",
200
- path
201
- });
202
- let response;
203
- try {
204
- response = await fetch(path, {
205
- method: "GET",
206
- headers
207
- });
208
- } catch (err) {
209
- throw new Error(`Network error: ${err instanceof Error ? err.message : String(err)}`);
210
- }
211
- if (!response.ok) {
212
- const errorText = await response.text();
213
- throw new Error(`Failed to list secrets (${response.status}): ${errorText}`);
214
- }
215
- return response.json();
216
- }, createSecret = async (secret, options) => {
217
- const baseUrl = options.url || "";
218
- const path = `${baseUrl}/api/secrets`;
219
- const body = JSON.stringify(secret);
220
- const headers = await createSignatureHeader(options.privateKey, {
221
- method: "POST",
222
- path,
223
- body
224
- });
225
- const response = await fetch(path, {
226
- method: "POST",
227
- headers: {
228
- "Content-Type": "application/json",
229
- ...headers
230
- },
231
- body
232
- });
233
- if (!response.ok) {
234
- const errorText = await response.text();
235
- throw new Error(`Failed to create secret (${response.status}): ${errorText}`);
236
- }
237
- };
238
-
239
74
  // ../../packages/api/actions/index.ts
240
75
  var init_actions = __esm(() => {
241
76
  init_deployments();
242
- init_deploy();
243
77
  init_invocations();
244
78
  init_logs();
245
79
  init_assets();
@@ -253,10 +87,10 @@ var init_api = __esm(() => {
253
87
  });
254
88
 
255
89
  // src/config/index.ts
256
- import { readFileSync, writeFileSync as writeFileSync2, existsSync, mkdirSync } from "fs";
257
- import { join as join2 } from "path";
90
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
91
+ import { join } from "path";
258
92
  import chalk from "chalk";
259
- var getLocalConfigDir = () => join2(process.cwd(), ".nulljs"), getLocalConfigFile = () => join2(getLocalConfigDir(), "config.json"), ensureLocalConfigDir = () => {
93
+ var getLocalConfigDir = () => join(process.cwd(), ".nulljs"), getLocalConfigFile = () => join(getLocalConfigDir(), "config.json"), ensureLocalConfigDir = () => {
260
94
  const localDir = getLocalConfigDir();
261
95
  if (!existsSync(localDir)) {
262
96
  mkdirSync(localDir, { recursive: true });
@@ -274,7 +108,7 @@ var getLocalConfigDir = () => join2(process.cwd(), ".nulljs"), getLocalConfigFil
274
108
  }
275
109
  }, writeConfigStore = (store) => {
276
110
  ensureLocalConfigDir();
277
- writeFileSync2(getLocalConfigFile(), JSON.stringify(store, null, 2));
111
+ writeFileSync(getLocalConfigFile(), JSON.stringify(store, null, 2));
278
112
  }, readLocalConfig = () => {
279
113
  const store = readConfigStore();
280
114
  if (!store)
@@ -373,14 +207,14 @@ var init_config = () => {};
373
207
 
374
208
  // src/lib/server.ts
375
209
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, realpathSync } from "fs";
376
- import { join as join3, dirname } from "path";
210
+ import { join as join2, dirname } from "path";
377
211
  import chalk2 from "chalk";
378
212
  var CLI_DIR, PLATFORMS, getPlatformKey = () => {
379
213
  return `${process.platform}-${process.arch}`;
380
214
  }, findProjectRoot = (startPath = process.cwd()) => {
381
215
  let currentPath = startPath;
382
216
  while (currentPath !== dirname(currentPath)) {
383
- if (existsSync2(join3(currentPath, "package.json"))) {
217
+ if (existsSync2(join2(currentPath, "package.json"))) {
384
218
  return currentPath;
385
219
  }
386
220
  currentPath = dirname(currentPath);
@@ -389,7 +223,7 @@ var CLI_DIR, PLATFORMS, getPlatformKey = () => {
389
223
  }, findMonorepoRoot = (startPath = process.cwd()) => {
390
224
  let currentPath = startPath;
391
225
  while (currentPath !== dirname(currentPath)) {
392
- if (existsSync2(join3(currentPath, "Cargo.toml")) && existsSync2(join3(currentPath, "package.json"))) {
226
+ if (existsSync2(join2(currentPath, "Cargo.toml")) && existsSync2(join2(currentPath, "package.json"))) {
393
227
  return currentPath;
394
228
  }
395
229
  currentPath = dirname(currentPath);
@@ -402,11 +236,11 @@ var CLI_DIR, PLATFORMS, getPlatformKey = () => {
402
236
  }
403
237
  const monorepoRoot = findMonorepoRoot() || findMonorepoRoot(CLI_DIR);
404
238
  if (monorepoRoot) {
405
- const debugBinary = join3(monorepoRoot, "target", "debug", "server");
239
+ const debugBinary = join2(monorepoRoot, "target", "debug", "server");
406
240
  if (existsSync2(debugBinary)) {
407
241
  return { path: debugBinary, source: "local-debug" };
408
242
  }
409
- const releaseBinary = join3(monorepoRoot, "target", "release", "server");
243
+ const releaseBinary = join2(monorepoRoot, "target", "release", "server");
410
244
  if (existsSync2(releaseBinary)) {
411
245
  return { path: releaseBinary, source: "local-release" };
412
246
  }
@@ -429,7 +263,7 @@ var CLI_DIR, PLATFORMS, getPlatformKey = () => {
429
263
  args.push("--api-port", "3000");
430
264
  args.push("--gateway-port", "3001");
431
265
  const projectRoot = findProjectRoot();
432
- const cloudPath = join3(projectRoot, ".nulljs");
266
+ const cloudPath = join2(projectRoot, ".nulljs");
433
267
  args.push("--cloud-path", cloudPath);
434
268
  if (!existsSync2(cloudPath)) {
435
269
  mkdirSync2(cloudPath, { recursive: true });
@@ -680,6 +514,183 @@ var init_bundle = __esm(() => {
680
514
  init_function();
681
515
  });
682
516
 
517
+ // ../../packages/api/actions/http.ts
518
+ import { mkdtempSync, writeFileSync as writeFileSync2, rmSync } from "fs";
519
+ import { tmpdir } from "os";
520
+ import { join as join3 } from "path";
521
+ var {$ } = globalThis.Bun;
522
+ var parseCurlResponse = (result) => {
523
+ const lines = result.trim().split(`
524
+ `);
525
+ const status = parseInt(lines.pop() || "0", 10);
526
+ const body = lines.join(`
527
+ `);
528
+ return {
529
+ ok: status >= 200 && status < 300,
530
+ status,
531
+ body
532
+ };
533
+ }, buildHeaderFlags = (headers) => {
534
+ const flags = [];
535
+ for (const [key, value] of Object.entries(headers)) {
536
+ flags.push("-H");
537
+ flags.push(`${key}: ${value}`);
538
+ }
539
+ return flags;
540
+ }, httpGet = async (path, options) => {
541
+ const url = options?.baseUrl ? `${options.baseUrl}${path}` : path;
542
+ const headers = options?.headers || {};
543
+ if (options?.useCurl) {
544
+ const headerFlags = buildHeaderFlags(headers);
545
+ const result = await $`curl -s -w '\n%{http_code}' -X GET ${headerFlags} ${url}`.text();
546
+ return parseCurlResponse(result);
547
+ }
548
+ const response = await fetch(url, {
549
+ method: "GET",
550
+ headers
551
+ });
552
+ return {
553
+ ok: response.ok,
554
+ status: response.status,
555
+ body: await response.text()
556
+ };
557
+ }, httpPost = async (path, body, options) => {
558
+ const url = options?.baseUrl ? `${options.baseUrl}${path}` : path;
559
+ const headers = options?.headers || {};
560
+ if (options?.useCurl) {
561
+ const tempDir = mkdtempSync(join3(tmpdir(), "nulljs-http-"));
562
+ const bodyFile = join3(tempDir, "body.json");
563
+ try {
564
+ writeFileSync2(bodyFile, body);
565
+ const headerFlags = buildHeaderFlags(headers);
566
+ const result = await $`curl -s -w '\n%{http_code}' -X POST ${headerFlags} -d @${bodyFile} ${url}`.text();
567
+ return parseCurlResponse(result);
568
+ } finally {
569
+ rmSync(tempDir, { recursive: true, force: true });
570
+ }
571
+ }
572
+ const response = await fetch(url, {
573
+ method: "POST",
574
+ headers,
575
+ body
576
+ });
577
+ return {
578
+ ok: response.ok,
579
+ status: response.status,
580
+ body: await response.text()
581
+ };
582
+ }, httpPostFormData = async (path, files, options) => {
583
+ const url = options?.baseUrl ? `${options.baseUrl}${path}` : path;
584
+ const headers = options?.headers || {};
585
+ if (options?.useCurl) {
586
+ const tempDir = mkdtempSync(join3(tmpdir(), "nulljs-http-"));
587
+ try {
588
+ const formParts = [];
589
+ for (const file of files) {
590
+ const filePath = join3(tempDir, file.fileName);
591
+ writeFileSync2(filePath, file.content);
592
+ formParts.push("-F");
593
+ formParts.push(`${file.fileName}=@${filePath};type=${file.mimeType}`);
594
+ }
595
+ const headerFlags = buildHeaderFlags(headers);
596
+ const result = await $`curl -s -w '\n%{http_code}' -X POST ${headerFlags} ${formParts} ${url}`.text();
597
+ return parseCurlResponse(result);
598
+ } finally {
599
+ rmSync(tempDir, { recursive: true, force: true });
600
+ }
601
+ }
602
+ const form = new FormData;
603
+ for (const file of files) {
604
+ const buffer = Buffer.from(file.content);
605
+ const blob = new Blob([buffer], { type: file.mimeType });
606
+ form.append(file.fileName, blob);
607
+ }
608
+ const response = await fetch(url, {
609
+ method: "POST",
610
+ headers,
611
+ body: form
612
+ });
613
+ return {
614
+ ok: response.ok,
615
+ status: response.status,
616
+ body: await response.text()
617
+ };
618
+ };
619
+ var init_http = () => {};
620
+
621
+ // ../../packages/api/actions/deploy.ts
622
+ var getMimeType = (fileName) => {
623
+ if (fileName.endsWith(".js"))
624
+ return "application/javascript";
625
+ if (fileName.endsWith(".css"))
626
+ return "text/css";
627
+ if (fileName.endsWith(".html"))
628
+ return "text/html";
629
+ if (fileName.endsWith(".json"))
630
+ return "application/json";
631
+ return "application/octet-stream";
632
+ }, assetsToFileData = (assets3) => {
633
+ const files = [];
634
+ const blobs = [];
635
+ for (const asset of assets3) {
636
+ const mimeType = getMimeType(asset.fileName);
637
+ const buffer = Buffer.from(asset.code);
638
+ files.push({
639
+ fileName: asset.fileName,
640
+ content: asset.code,
641
+ mimeType
642
+ });
643
+ blobs.push({
644
+ fileName: asset.fileName,
645
+ size: buffer.length,
646
+ type: mimeType
647
+ });
648
+ }
649
+ return { files, blobs };
650
+ }, createSignature = async (blobs, privateKey) => {
651
+ const sortedBlobs = [...blobs].sort((a, b) => a.fileName.localeCompare(b.fileName));
652
+ const dataString = sortedBlobs.map((b) => `${b.fileName}:${b.size}:${b.type}`).join("|");
653
+ const sign = await crypto.subtle.sign("Ed25519", privateKey, Buffer.from(dataString));
654
+ return btoa(String.fromCharCode(...new Uint8Array(sign)));
655
+ }, createFunctionDeployment = async (deployment2, options) => {
656
+ const handler = deployment2.assets.find((asset) => asset.fileName === "handler.js");
657
+ if (!handler) {
658
+ throw new Error(`Handler not found for ${deployment2.name}`);
659
+ }
660
+ const { files, blobs } = assetsToFileData([handler]);
661
+ const signature = await createSignature(blobs, options.privateKey);
662
+ const baseUrl = options.url || "";
663
+ const path = "/api/deployment";
664
+ const result = await httpPostFormData(path, files, {
665
+ baseUrl,
666
+ useCurl: options.useCurl,
667
+ headers: {
668
+ authorization: signature
669
+ }
670
+ });
671
+ if (!result.ok) {
672
+ throw new Error(`Deployment failed (${result.status}): ${result.body}`);
673
+ }
674
+ }, createReactDeployment = async (deployment2, options) => {
675
+ const { files, blobs } = assetsToFileData(deployment2.assets);
676
+ const signature = await createSignature(blobs, options.privateKey);
677
+ const baseUrl = options.url || "";
678
+ const path = "/api/deployment/react";
679
+ const result = await httpPostFormData(path, files, {
680
+ baseUrl,
681
+ useCurl: options.useCurl,
682
+ headers: {
683
+ authorization: signature
684
+ }
685
+ });
686
+ if (!result.ok) {
687
+ throw new Error(`Deployment failed (${result.status}): ${result.body}`);
688
+ }
689
+ };
690
+ var init_deploy = __esm(() => {
691
+ init_http();
692
+ });
693
+
683
694
  // src/lib/deploy.ts
684
695
  var exports_deploy = {};
685
696
  __export(exports_deploy, {
@@ -730,7 +741,7 @@ var deployedHashes, clearDeployCache = () => {
730
741
  return { deployed: true, skipped: false };
731
742
  };
732
743
  var init_deploy2 = __esm(() => {
733
- init_api();
744
+ init_deploy();
734
745
  init_bundle();
735
746
  deployedHashes = new Map;
736
747
  });
@@ -912,7 +923,7 @@ var FUNCTION_DIRS, deployedHashes2, hashCode2 = (code) => {
912
923
  var init_watcher = __esm(() => {
913
924
  init_config();
914
925
  init_bundle();
915
- init_api();
926
+ init_deploy();
916
927
  FUNCTION_DIRS = ["api", "cron", "event"];
917
928
  deployedHashes2 = new Map;
918
929
  });
@@ -2031,14 +2042,72 @@ var printAvailableCommands = () => {
2031
2042
  console.log(chalk5.cyan(" nulljs host") + chalk5.gray(" - Set up production hosting with systemd"));
2032
2043
  };
2033
2044
  // src/commands/secret.ts
2034
- init_api();
2035
- init_config();
2036
2045
  import { Command as Command2 } from "commander";
2037
2046
  import chalk6 from "chalk";
2038
2047
  import { resolve as resolve3 } from "path";
2039
2048
  import { readFile, readdir as readdir3 } from "fs/promises";
2040
2049
  import { existsSync as existsSync6 } from "fs";
2041
2050
  import * as p3 from "@clack/prompts";
2051
+
2052
+ // ../../packages/api/actions/secrets.ts
2053
+ init_http();
2054
+ var createSignatureHeader = async (privateKey, props) => {
2055
+ const timestamp = new Date().toISOString();
2056
+ const raw = `${props.method}-${props.path}-${timestamp}${props.body ? "-" + props.body : ""}`;
2057
+ const sign = await crypto.subtle.sign("Ed25519", privateKey, Buffer.from(raw));
2058
+ const signature = btoa(String.fromCharCode(...new Uint8Array(sign)));
2059
+ const header = {
2060
+ authorization: signature,
2061
+ "x-time": timestamp
2062
+ };
2063
+ if (props.body) {
2064
+ header["x-body"] = btoa(props.body);
2065
+ }
2066
+ return header;
2067
+ };
2068
+ var listSecrets = async (options) => {
2069
+ const baseUrl = options.url || "";
2070
+ const path = "/api/secrets";
2071
+ const fullPath = `${baseUrl}${path}`;
2072
+ const headers = await createSignatureHeader(options.privateKey, {
2073
+ method: "GET",
2074
+ path: fullPath
2075
+ });
2076
+ const result = await httpGet(path, {
2077
+ baseUrl,
2078
+ useCurl: options.useCurl,
2079
+ headers
2080
+ });
2081
+ if (!result.ok) {
2082
+ throw new Error(`Failed to list secrets (${result.status}): ${result.body}`);
2083
+ }
2084
+ return JSON.parse(result.body);
2085
+ };
2086
+ var createSecret = async (secret, options) => {
2087
+ const baseUrl = options.url || "";
2088
+ const path = "/api/secrets";
2089
+ const fullPath = `${baseUrl}${path}`;
2090
+ const body = JSON.stringify(secret);
2091
+ const signatureHeaders = await createSignatureHeader(options.privateKey, {
2092
+ method: "POST",
2093
+ path: fullPath,
2094
+ body
2095
+ });
2096
+ const result = await httpPost(path, body, {
2097
+ baseUrl,
2098
+ useCurl: options.useCurl,
2099
+ headers: {
2100
+ "Content-Type": "application/json",
2101
+ ...signatureHeaders
2102
+ }
2103
+ });
2104
+ if (!result.ok) {
2105
+ throw new Error(`Failed to create secret (${result.status}): ${result.body}`);
2106
+ }
2107
+ };
2108
+
2109
+ // src/commands/secret.ts
2110
+ init_config();
2042
2111
  var selectConfig2 = async () => {
2043
2112
  const configList = listConfigs();
2044
2113
  if (!configList || configList.configs.length === 0) {
@@ -2093,7 +2162,7 @@ var parseEnvFile = async (filePath) => {
2093
2162
  const content = await readFile(filePath, "utf-8");
2094
2163
  const lines = content.split(`
2095
2164
  `);
2096
- const secrets2 = [];
2165
+ const secrets = [];
2097
2166
  for (const line of lines) {
2098
2167
  const trimmed = line.trim();
2099
2168
  if (!trimmed || trimmed.startsWith("#")) {
@@ -2109,13 +2178,13 @@ var parseEnvFile = async (filePath) => {
2109
2178
  value = value.slice(1, -1);
2110
2179
  }
2111
2180
  if (key) {
2112
- secrets2.push({ key, value });
2181
+ secrets.push({ key, value });
2113
2182
  }
2114
2183
  }
2115
- return secrets2;
2184
+ return secrets;
2116
2185
  };
2117
2186
  var registerSecretCommand = (program) => {
2118
- program.command("secret").description("Secret management").addCommand(new Command2("list").description("List all secret keys").option("-e, --env <name>", "Use a specific config environment").action(async (options) => {
2187
+ program.command("secret").description("Secret management").addCommand(new Command2("list").description("List all secret keys").option("-e, --env <name>", "Use a specific config environment").option("--curl", "Use curl instead of fetch (workaround for macOS local network issues)").action(async (options) => {
2119
2188
  let config;
2120
2189
  try {
2121
2190
  config = options.env ? getConfig(options.env) : await selectConfig2();
@@ -2132,7 +2201,7 @@ var registerSecretCommand = (program) => {
2132
2201
  try {
2133
2202
  console.log(chalk6.gray(`Fetching secrets from ${config.api}...`));
2134
2203
  const privateKey = await loadPrivateKey(config);
2135
- const keys = await listSecrets({ privateKey, url: config.api });
2204
+ const keys = await listSecrets({ privateKey, url: config.api, useCurl: options.curl });
2136
2205
  if (keys.length === 0) {
2137
2206
  console.log(chalk6.yellow("No secrets found"));
2138
2207
  return;
@@ -2146,7 +2215,7 @@ Secret keys:`));
2146
2215
  console.error(chalk6.red("\u2717 Failed to list secrets:"), error instanceof Error ? error.message : String(error));
2147
2216
  process.exit(1);
2148
2217
  }
2149
- })).addCommand(new Command2("create").description("Create a new secret").argument("[key]", "Secret key").argument("[value]", "Secret value").option("-e, --env <name>", "Use a specific config environment").action(async (key, value, options) => {
2218
+ })).addCommand(new Command2("create").description("Create a new secret").argument("[key]", "Secret key").argument("[value]", "Secret value").option("-e, --env <name>", "Use a specific config environment").option("--curl", "Use curl instead of fetch (workaround for macOS local network issues)").action(async (key, value, options) => {
2150
2219
  const config = options?.env ? getConfig(options.env) : await selectConfig2();
2151
2220
  if (!config) {
2152
2221
  console.error(chalk6.red("\u2717 No configuration found."));
@@ -2192,13 +2261,13 @@ Secret keys:`));
2192
2261
  await new Promise((resolve4) => setImmediate(resolve4));
2193
2262
  try {
2194
2263
  const privateKey = await loadPrivateKey(config);
2195
- await createSecret({ key: secretKey, value: secretValue }, { privateKey, url: config.api });
2264
+ await createSecret({ key: secretKey, value: secretValue }, { privateKey, url: config.api, useCurl: options?.curl });
2196
2265
  console.log(chalk6.green("\u2713 Secret created:") + ` ${chalk6.cyan(secretKey)}`);
2197
2266
  } catch (error) {
2198
2267
  console.error(chalk6.red("\u2717 Failed to create secret:"), error instanceof Error ? error.message : error);
2199
2268
  process.exit(1);
2200
2269
  }
2201
- })).addCommand(new Command2("deploy").description("Deploy secrets from a .secret file").argument("[file]", "Path to .secret file").option("-e, --env <name>", "Use a specific config environment").action(async (file, options) => {
2270
+ })).addCommand(new Command2("deploy").description("Deploy secrets from a .secret file").argument("[file]", "Path to .secret file").option("-e, --env <name>", "Use a specific config environment").option("--curl", "Use curl instead of fetch (workaround for macOS local network issues)").action(async (file, options) => {
2202
2271
  const config = options?.env ? getConfig(options.env) : await selectConfig2();
2203
2272
  if (!config) {
2204
2273
  console.error(chalk6.red("\u2717 No configuration found."));
@@ -2218,19 +2287,19 @@ Secret keys:`));
2218
2287
  }
2219
2288
  await new Promise((resolve4) => setImmediate(resolve4));
2220
2289
  try {
2221
- const secrets2 = await parseEnvFile(filePath);
2222
- if (secrets2.length === 0) {
2290
+ const secrets = await parseEnvFile(filePath);
2291
+ if (secrets.length === 0) {
2223
2292
  console.log(chalk6.yellow("No secrets found in file"));
2224
2293
  return;
2225
2294
  }
2226
2295
  const privateKey = await loadPrivateKey(config);
2227
2296
  let created = 0;
2228
2297
  let failed = 0;
2229
- console.log(chalk6.cyan(`Deploying ${secrets2.length} secret(s) to ${config.name}...
2298
+ console.log(chalk6.cyan(`Deploying ${secrets.length} secret(s) to ${config.name}...
2230
2299
  `));
2231
- for (const secret of secrets2) {
2300
+ for (const secret of secrets) {
2232
2301
  try {
2233
- await createSecret(secret, { privateKey, url: config.api });
2302
+ await createSecret(secret, { privateKey, url: config.api, useCurl: options?.curl });
2234
2303
  console.log(chalk6.green("\u2713") + ` ${secret.key}`);
2235
2304
  created++;
2236
2305
  } catch (error) {
@@ -2248,7 +2317,7 @@ Secret keys:`));
2248
2317
  console.error(chalk6.red("\u2717 Failed to deploy secrets:"), error instanceof Error ? error.message : error);
2249
2318
  process.exit(1);
2250
2319
  }
2251
- })).addCommand(new Command2("import").description("Import secrets from a file (alias for deploy)").argument("[file]", "Path to .secret file").option("-e, --env <name>", "Use a specific config environment").action(async (file, options) => {
2320
+ })).addCommand(new Command2("import").description("Import secrets from a file (alias for deploy)").argument("[file]", "Path to .secret file").option("-e, --env <name>", "Use a specific config environment").option("--curl", "Use curl instead of fetch (workaround for macOS local network issues)").action(async (file, options) => {
2252
2321
  const config = options?.env ? getConfig(options.env) : await selectConfig2();
2253
2322
  if (!config) {
2254
2323
  console.error(chalk6.red("\u2717 No configuration found."));
@@ -2268,19 +2337,19 @@ Secret keys:`));
2268
2337
  }
2269
2338
  await new Promise((resolve4) => setImmediate(resolve4));
2270
2339
  try {
2271
- const secrets2 = await parseEnvFile(filePath);
2272
- if (secrets2.length === 0) {
2340
+ const secrets = await parseEnvFile(filePath);
2341
+ if (secrets.length === 0) {
2273
2342
  console.log(chalk6.yellow("No secrets found in file"));
2274
2343
  return;
2275
2344
  }
2276
2345
  const privateKey = await loadPrivateKey(config);
2277
2346
  let created = 0;
2278
2347
  let failed = 0;
2279
- console.log(chalk6.cyan(`Importing ${secrets2.length} secret(s) to ${config.name}...
2348
+ console.log(chalk6.cyan(`Importing ${secrets.length} secret(s) to ${config.name}...
2280
2349
  `));
2281
- for (const secret of secrets2) {
2350
+ for (const secret of secrets) {
2282
2351
  try {
2283
- await createSecret(secret, { privateKey, url: config.api });
2352
+ await createSecret(secret, { privateKey, url: config.api, useCurl: options?.curl });
2284
2353
  console.log(chalk6.green("\u2713") + ` ${secret.key}`);
2285
2354
  created++;
2286
2355
  } catch (error) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tothalex/nulljs",
3
3
  "module": "dist/index.js",
4
- "version": "0.0.59",
4
+ "version": "0.0.60",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "nulljs": "./dist/cli.js"
@@ -18,9 +18,9 @@
18
18
  "typescript": "^5"
19
19
  },
20
20
  "optionalDependencies": {
21
- "@tothalex/nulljs-darwin-arm64": "^0.0.81",
22
- "@tothalex/nulljs-linux-arm64": "^0.0.81",
23
- "@tothalex/nulljs-linux-x64": "^0.0.81"
21
+ "@tothalex/nulljs-darwin-arm64": "^0.0.86",
22
+ "@tothalex/nulljs-linux-arm64": "^0.0.86",
23
+ "@tothalex/nulljs-linux-x64": "^0.0.86"
24
24
  },
25
25
  "files": [
26
26
  "dist"