pinme 2.0.0-beta.3 → 2.0.0-beta.5

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/index.js CHANGED
@@ -96,8 +96,8 @@ var require_package = __commonJS({
96
96
  // node_modules/.pnpm/dotenv@16.5.0/node_modules/dotenv/lib/main.js
97
97
  var require_main = __commonJS({
98
98
  "node_modules/.pnpm/dotenv@16.5.0/node_modules/dotenv/lib/main.js"(exports2, module2) {
99
- var fs15 = require("fs");
100
- var path16 = require("path");
99
+ var fs17 = require("fs");
100
+ var path18 = require("path");
101
101
  var os5 = require("os");
102
102
  var crypto3 = require("crypto");
103
103
  var packageJson = require_package();
@@ -200,7 +200,7 @@ var require_main = __commonJS({
200
200
  if (options && options.path && options.path.length > 0) {
201
201
  if (Array.isArray(options.path)) {
202
202
  for (const filepath of options.path) {
203
- if (fs15.existsSync(filepath)) {
203
+ if (fs17.existsSync(filepath)) {
204
204
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
205
205
  }
206
206
  }
@@ -208,15 +208,15 @@ var require_main = __commonJS({
208
208
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
209
209
  }
210
210
  } else {
211
- possibleVaultPath = path16.resolve(process.cwd(), ".env.vault");
211
+ possibleVaultPath = path18.resolve(process.cwd(), ".env.vault");
212
212
  }
213
- if (fs15.existsSync(possibleVaultPath)) {
213
+ if (fs17.existsSync(possibleVaultPath)) {
214
214
  return possibleVaultPath;
215
215
  }
216
216
  return null;
217
217
  }
218
218
  function _resolveHome(envPath) {
219
- return envPath[0] === "~" ? path16.join(os5.homedir(), envPath.slice(1)) : envPath;
219
+ return envPath[0] === "~" ? path18.join(os5.homedir(), envPath.slice(1)) : envPath;
220
220
  }
221
221
  function _configVault(options) {
222
222
  const debug = Boolean(options && options.debug);
@@ -232,7 +232,7 @@ var require_main = __commonJS({
232
232
  return { parsed };
233
233
  }
234
234
  function configDotenv(options) {
235
- const dotenvPath = path16.resolve(process.cwd(), ".env");
235
+ const dotenvPath = path18.resolve(process.cwd(), ".env");
236
236
  let encoding = "utf8";
237
237
  const debug = Boolean(options && options.debug);
238
238
  if (options && options.encoding) {
@@ -255,13 +255,13 @@ var require_main = __commonJS({
255
255
  }
256
256
  let lastError;
257
257
  const parsedAll = {};
258
- for (const path17 of optionPaths) {
258
+ for (const path19 of optionPaths) {
259
259
  try {
260
- const parsed = DotenvModule.parse(fs15.readFileSync(path17, { encoding }));
260
+ const parsed = DotenvModule.parse(fs17.readFileSync(path19, { encoding }));
261
261
  DotenvModule.populate(parsedAll, parsed, options);
262
262
  } catch (e) {
263
263
  if (debug) {
264
- _debug(`Failed to load ${path17} ${e.message}`);
264
+ _debug(`Failed to load ${path19} ${e.message}`);
265
265
  }
266
266
  lastError = e;
267
267
  }
@@ -1519,11 +1519,11 @@ function checkNodeVersion() {
1519
1519
 
1520
1520
  // bin/index.ts
1521
1521
  var import_commander = require("commander");
1522
- var import_chalk21 = __toESM(require("chalk"));
1522
+ var import_chalk23 = __toESM(require("chalk"));
1523
1523
  var import_figlet5 = __toESM(require("figlet"));
1524
1524
 
1525
1525
  // package.json
1526
- var version = "2.0.0-beta.3";
1526
+ var version = "2.0.0-beta.5";
1527
1527
 
1528
1528
  // bin/upload.ts
1529
1529
  var import_path7 = __toESM(require("path"));
@@ -1968,9 +1968,9 @@ function isVisitable(thing) {
1968
1968
  function removeBrackets(key) {
1969
1969
  return utils_default.endsWith(key, "[]") ? key.slice(0, -2) : key;
1970
1970
  }
1971
- function renderKey(path16, key, dots) {
1972
- if (!path16) return key;
1973
- return path16.concat(key).map(function each(token, i) {
1971
+ function renderKey(path18, key, dots) {
1972
+ if (!path18) return key;
1973
+ return path18.concat(key).map(function each(token, i) {
1974
1974
  token = removeBrackets(token);
1975
1975
  return !dots && i ? "[" + token + "]" : token;
1976
1976
  }).join(dots ? "." : "");
@@ -2015,9 +2015,9 @@ function toFormData(obj, formData, options) {
2015
2015
  }
2016
2016
  return value;
2017
2017
  }
2018
- function defaultVisitor(value, key, path16) {
2018
+ function defaultVisitor(value, key, path18) {
2019
2019
  let arr = value;
2020
- if (value && !path16 && typeof value === "object") {
2020
+ if (value && !path18 && typeof value === "object") {
2021
2021
  if (utils_default.endsWith(key, "{}")) {
2022
2022
  key = metaTokens ? key : key.slice(0, -2);
2023
2023
  value = JSON.stringify(value);
@@ -2036,7 +2036,7 @@ function toFormData(obj, formData, options) {
2036
2036
  if (isVisitable(value)) {
2037
2037
  return true;
2038
2038
  }
2039
- formData.append(renderKey(path16, key, dots), convertValue(value));
2039
+ formData.append(renderKey(path18, key, dots), convertValue(value));
2040
2040
  return false;
2041
2041
  }
2042
2042
  const stack = [];
@@ -2045,10 +2045,10 @@ function toFormData(obj, formData, options) {
2045
2045
  convertValue,
2046
2046
  isVisitable
2047
2047
  });
2048
- function build(value, path16) {
2048
+ function build(value, path18) {
2049
2049
  if (utils_default.isUndefined(value)) return;
2050
2050
  if (stack.indexOf(value) !== -1) {
2051
- throw Error("Circular reference detected in " + path16.join("."));
2051
+ throw Error("Circular reference detected in " + path18.join("."));
2052
2052
  }
2053
2053
  stack.push(value);
2054
2054
  utils_default.forEach(value, function each(el, key) {
@@ -2056,11 +2056,11 @@ function toFormData(obj, formData, options) {
2056
2056
  formData,
2057
2057
  el,
2058
2058
  utils_default.isString(key) ? key.trim() : key,
2059
- path16,
2059
+ path18,
2060
2060
  exposedHelpers
2061
2061
  );
2062
2062
  if (result === true) {
2063
- build(el, path16 ? path16.concat(key) : [key]);
2063
+ build(el, path18 ? path18.concat(key) : [key]);
2064
2064
  }
2065
2065
  });
2066
2066
  stack.pop();
@@ -2221,7 +2221,7 @@ var node_default = {
2221
2221
  // node_modules/.pnpm/axios@1.3.2/node_modules/axios/lib/helpers/toURLEncodedForm.js
2222
2222
  function toURLEncodedForm(data, options) {
2223
2223
  return toFormData_default(data, new node_default.classes.URLSearchParams(), Object.assign({
2224
- visitor: function(value, key, path16, helpers) {
2224
+ visitor: function(value, key, path18, helpers) {
2225
2225
  if (node_default.isNode && utils_default.isBuffer(value)) {
2226
2226
  this.append(key, value.toString("base64"));
2227
2227
  return false;
@@ -2250,10 +2250,10 @@ function arrayToObject(arr) {
2250
2250
  return obj;
2251
2251
  }
2252
2252
  function formDataToJSON(formData) {
2253
- function buildPath(path16, value, target, index) {
2254
- let name = path16[index++];
2253
+ function buildPath(path18, value, target, index) {
2254
+ let name = path18[index++];
2255
2255
  const isNumericKey = Number.isFinite(+name);
2256
- const isLast = index >= path16.length;
2256
+ const isLast = index >= path18.length;
2257
2257
  name = !name && utils_default.isArray(target) ? target.length : name;
2258
2258
  if (isLast) {
2259
2259
  if (utils_default.hasOwnProp(target, name)) {
@@ -2266,7 +2266,7 @@ function formDataToJSON(formData) {
2266
2266
  if (!target[name] || !utils_default.isObject(target[name])) {
2267
2267
  target[name] = [];
2268
2268
  }
2269
- const result = buildPath(path16, value, target[name], index);
2269
+ const result = buildPath(path18, value, target[name], index);
2270
2270
  if (result && utils_default.isArray(target[name])) {
2271
2271
  target[name] = arrayToObject(target[name]);
2272
2272
  }
@@ -3328,9 +3328,9 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
3328
3328
  auth = urlUsername + ":" + urlPassword;
3329
3329
  }
3330
3330
  auth && headers.delete("authorization");
3331
- let path16;
3331
+ let path18;
3332
3332
  try {
3333
- path16 = buildURL(
3333
+ path18 = buildURL(
3334
3334
  parsed.pathname + parsed.search,
3335
3335
  config.params,
3336
3336
  config.paramsSerializer
@@ -3348,7 +3348,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
3348
3348
  false
3349
3349
  );
3350
3350
  const options = {
3351
- path: path16,
3351
+ path: path18,
3352
3352
  method,
3353
3353
  headers: headers.toJSON(),
3354
3354
  agents: { http: config.httpAgent, https: config.httpsAgent },
@@ -3567,14 +3567,14 @@ var cookies_default = node_default.isStandardBrowserEnv ? (
3567
3567
  // Standard browser envs support document.cookie
3568
3568
  /* @__PURE__ */ function standardBrowserEnv() {
3569
3569
  return {
3570
- write: function write(name, value, expires, path16, domain, secure) {
3570
+ write: function write(name, value, expires, path18, domain, secure) {
3571
3571
  const cookie = [];
3572
3572
  cookie.push(name + "=" + encodeURIComponent(value));
3573
3573
  if (utils_default.isNumber(expires)) {
3574
3574
  cookie.push("expires=" + new Date(expires).toGMTString());
3575
3575
  }
3576
- if (utils_default.isString(path16)) {
3577
- cookie.push("path=" + path16);
3576
+ if (utils_default.isString(path18)) {
3577
+ cookie.push("path=" + path18);
3578
3578
  }
3579
3579
  if (utils_default.isString(domain)) {
3580
3580
  cookie.push("domain=" + domain);
@@ -7113,6 +7113,7 @@ var import_child_process2 = require("child_process");
7113
7113
  var TEMPLATE_DIR = import_path11.default.join(__dirname, "../template");
7114
7114
  var PROJECT_DIR = process.cwd();
7115
7115
  var API_BASE = "https://pinme.dev/api/v4";
7116
+ var TEMPLATE_REPO = "https://github.com/glitternetwork/pinme-worker-template.git";
7116
7117
  async function createCmd(options) {
7117
7118
  var _a, _b, _c, _d, _e, _f;
7118
7119
  try {
@@ -7188,9 +7189,20 @@ Directory "${projectName}" already exists.`));
7188
7189
  const errorMsg = ((_d = (_c = (_b = error.response) == null ? void 0 : _b.data) == null ? void 0 : _c.data) == null ? void 0 : _d.error) || ((_f = (_e = error.response) == null ? void 0 : _e.data) == null ? void 0 : _f.msg) || error.message || "Failed to create worker";
7189
7190
  throw new Error(errorMsg);
7190
7191
  }
7191
- console.log(import_chalk16.default.blue("\n2. Copying template files..."));
7192
- import_fs_extra6.default.copySync(TEMPLATE_DIR, targetDir);
7193
- console.log(import_chalk16.default.green(` Template copied to: ${targetDir}`));
7192
+ console.log(import_chalk16.default.blue("\n2. Cloning template from repository..."));
7193
+ try {
7194
+ (0, import_child_process2.execSync)(`git clone --depth 1 ${TEMPLATE_REPO} ${targetDir}`, {
7195
+ stdio: "inherit"
7196
+ });
7197
+ console.log(import_chalk16.default.green(` Template cloned to: ${targetDir}`));
7198
+ const gitDir = import_path11.default.join(targetDir, ".git");
7199
+ if (import_fs_extra6.default.existsSync(gitDir)) {
7200
+ import_fs_extra6.default.removeSync(gitDir);
7201
+ console.log(import_chalk16.default.gray(" .git directory removed"));
7202
+ }
7203
+ } catch (error) {
7204
+ throw new Error(`Failed to clone template: ${error.message}`);
7205
+ }
7194
7206
  console.log(import_chalk16.default.blue("\n3. Updating configuration..."));
7195
7207
  const configPath = import_path11.default.join(targetDir, "pinme.toml");
7196
7208
  const config = import_fs_extra6.default.readFileSync(configPath, "utf-8");
@@ -7206,6 +7218,21 @@ Directory "${projectName}" already exists.`));
7206
7218
  /# database_id = ".*"/,
7207
7219
  `database_id = "${workerData.uuid}"`
7208
7220
  );
7221
+ if (workerData.api_key) {
7222
+ console.log(import_chalk16.default.gray(` API Key: ${workerData.api_key.slice(0, 8)}...`));
7223
+ updatedConfig = updatedConfig.replace(
7224
+ /^# api_key = ".*"$/m,
7225
+ `api_key = "${workerData.api_key}"`
7226
+ );
7227
+ if (!updatedConfig.includes(`api_key = "${workerData.api_key}"`)) {
7228
+ updatedConfig = updatedConfig.replace(
7229
+ /^api_key = ".*"$/m,
7230
+ `api_key = "${workerData.api_key}"`
7231
+ );
7232
+ }
7233
+ } else {
7234
+ console.log(import_chalk16.default.yellow(" Warning: No API Key returned from API"));
7235
+ }
7209
7236
  import_fs_extra6.default.writeFileSync(configPath, updatedConfig);
7210
7237
  console.log(import_chalk16.default.green(` Updated pinme.toml`));
7211
7238
  console.log(import_chalk16.default.gray(` metadata: ${workerData.metadata}`));
@@ -7386,7 +7413,7 @@ function getBuiltWorker() {
7386
7413
  return { workerJsPath, modulePaths };
7387
7414
  }
7388
7415
  function getSqlFiles() {
7389
- const sqlDir = import_path12.default.join(PROJECT_DIR2, "backend", "schema");
7416
+ const sqlDir = import_path12.default.join(PROJECT_DIR2, "db");
7390
7417
  if (!import_fs_extra7.default.existsSync(sqlDir)) {
7391
7418
  return [];
7392
7419
  }
@@ -7540,13 +7567,13 @@ function loadConfig2() {
7540
7567
  };
7541
7568
  }
7542
7569
  function getSqlFiles2() {
7543
- const sqlDir = import_path13.default.join(PROJECT_DIR3, "backend", "schema");
7570
+ const sqlDir = import_path13.default.join(PROJECT_DIR3, "db");
7544
7571
  if (!import_fs_extra8.default.existsSync(sqlDir)) {
7545
- throw new Error("SQL directory not found: backend/schema");
7572
+ throw new Error("SQL directory not found: db");
7546
7573
  }
7547
7574
  const files = import_fs_extra8.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
7548
7575
  if (files.length === 0) {
7549
- throw new Error("No SQL files found in backend/schema");
7576
+ throw new Error("No SQL files found in db");
7550
7577
  }
7551
7578
  return files.map((f) => import_path13.default.join(sqlDir, f));
7552
7579
  }
@@ -7627,7 +7654,7 @@ async function updateDbCmd(options) {
7627
7654
  }
7628
7655
  console.log(import_chalk18.default.gray(`Project: ${projectName}`));
7629
7656
  const sqlFiles = getSqlFiles2();
7630
- console.log(import_chalk18.default.gray(`Found ${sqlFiles.length} SQL file(s) in backend/schema`));
7657
+ console.log(import_chalk18.default.gray(`Found ${sqlFiles.length} SQL file(s) in db`));
7631
7658
  await updateDb(sqlFiles, projectName);
7632
7659
  console.log(import_chalk18.default.green("\n\u2705 Database update complete!"));
7633
7660
  process.exit(0);
@@ -7877,14 +7904,221 @@ async function updateWebCmd(options) {
7877
7904
  }
7878
7905
  }
7879
7906
 
7907
+ // bin/delete.ts
7908
+ var import_chalk21 = __toESM(require("chalk"));
7909
+ var import_inquirer9 = __toESM(require("inquirer"));
7910
+ var import_fs_extra11 = __toESM(require("fs-extra"));
7911
+ var import_path16 = __toESM(require("path"));
7912
+ var API_BASE5 = "https://pinme.dev/api/v4";
7913
+ function getProjectName() {
7914
+ const configPath = import_path16.default.join(process.cwd(), "pinme.toml");
7915
+ if (!import_fs_extra11.default.existsSync(configPath)) {
7916
+ return null;
7917
+ }
7918
+ const config = import_fs_extra11.default.readFileSync(configPath, "utf-8");
7919
+ const match = config.match(/project_name\s*=\s*"([^"]+)"/);
7920
+ return (match == null ? void 0 : match[1]) || null;
7921
+ }
7922
+ async function deleteCmd(options) {
7923
+ var _a, _b;
7924
+ try {
7925
+ const headers = getAuthHeaders();
7926
+ if (!headers["authentication-tokens"] || !headers["token-address"]) {
7927
+ console.log(import_chalk21.default.yellow("\n\u26A0\uFE0F You are not logged in."));
7928
+ console.log(import_chalk21.default.gray("Please run: pinme login"));
7929
+ process.exit(1);
7930
+ }
7931
+ console.log(import_chalk21.default.blue("Deleting project...\n"));
7932
+ let projectName = options.name || getProjectName();
7933
+ if (!projectName) {
7934
+ console.log(import_chalk21.default.red("\n\u274C Error: Cannot find project name."));
7935
+ console.log(import_chalk21.default.yellow(" Please make sure you are in the project directory."));
7936
+ console.log(import_chalk21.default.gray(" The project directory should contain a pinme.toml file."));
7937
+ console.log(import_chalk21.default.gray("\n Or specify the project name:"));
7938
+ console.log(import_chalk21.default.gray(" cd /path/to/your-project"));
7939
+ console.log(import_chalk21.default.gray(" pinme delete"));
7940
+ process.exit(1);
7941
+ }
7942
+ console.log(import_chalk21.default.gray(`Project: ${projectName}`));
7943
+ console.log(import_chalk21.default.gray(`Directory: ${process.cwd()}`));
7944
+ if (!options.force) {
7945
+ const answers = await import_inquirer9.default.prompt([
7946
+ {
7947
+ type: "confirm",
7948
+ name: "confirm",
7949
+ message: `Are you sure you want to delete project "${projectName}"? This will remove Worker, domain binding, and D1 database.`,
7950
+ default: false
7951
+ }
7952
+ ]);
7953
+ if (!answers.confirm) {
7954
+ console.log(import_chalk21.default.gray("Cancelled."));
7955
+ process.exit(0);
7956
+ }
7957
+ }
7958
+ console.log(import_chalk21.default.blue("Deleting project on platform..."));
7959
+ const apiUrl = `${API_BASE5}/delete_project`;
7960
+ console.log(import_chalk21.default.gray(`API URL: ${apiUrl}`));
7961
+ console.log(import_chalk21.default.gray(`Project name: ${projectName}`));
7962
+ const response = await axios_default.post(apiUrl, {
7963
+ project_name: projectName
7964
+ }, {
7965
+ headers: {
7966
+ ...headers,
7967
+ "Content-Type": "application/json"
7968
+ }
7969
+ }).catch((error) => {
7970
+ var _a2, _b2;
7971
+ console.log(import_chalk21.default.red(` Response status: ${(_a2 = error.response) == null ? void 0 : _a2.status}`));
7972
+ console.log(import_chalk21.default.red(` Response data: ${JSON.stringify((_b2 = error.response) == null ? void 0 : _b2.data)}`));
7973
+ throw error;
7974
+ });
7975
+ const data = response.data;
7976
+ if (data.code === 200) {
7977
+ console.log(import_chalk21.default.green("\n\u2705 Project deleted successfully!"));
7978
+ console.log(import_chalk21.default.gray(`
7979
+ Project: ${data.data.project_name}`));
7980
+ console.log(import_chalk21.default.gray(` Domain deleted: ${data.data.domain_deleted ? "\u2705" : "\u274C"}`));
7981
+ console.log(import_chalk21.default.gray(` Worker deleted: ${data.data.worker_deleted ? "\u2705" : "\u274C"}`));
7982
+ console.log(import_chalk21.default.gray(` Database deleted: ${data.data.database_deleted ? "\u2705" : "\u274C"}`));
7983
+ const projectDir = process.cwd();
7984
+ if (import_fs_extra11.default.existsSync(projectDir)) {
7985
+ console.log(import_chalk21.default.blue("\nDeleting local project directory..."));
7986
+ const parentDir = import_path16.default.dirname(projectDir);
7987
+ process.chdir(parentDir);
7988
+ await import_fs_extra11.default.remove(projectDir);
7989
+ console.log(import_chalk21.default.green(`\u2705 Local directory deleted: ${projectDir}`));
7990
+ }
7991
+ } else {
7992
+ const errorMsg = (data == null ? void 0 : data.msg) || "Failed to delete project";
7993
+ throw new Error(errorMsg);
7994
+ }
7995
+ process.exit(0);
7996
+ } catch (error) {
7997
+ console.log(import_chalk21.default.red(error));
7998
+ const errorMsg = ((_b = (_a = error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.msg) || error.message || "Failed to delete project";
7999
+ console.error(import_chalk21.default.red(`
8000
+ \u274C Error: ${errorMsg}`));
8001
+ process.exit(1);
8002
+ }
8003
+ }
8004
+
8005
+ // bin/sendEmail.ts
8006
+ var import_chalk22 = __toESM(require("chalk"));
8007
+ var import_inquirer10 = __toESM(require("inquirer"));
8008
+ var import_fs_extra12 = __toESM(require("fs-extra"));
8009
+ var import_path17 = __toESM(require("path"));
8010
+ var PROJECT_DIR6 = process.cwd();
8011
+ var API_BASE6 = "https://pinme.dev/api/v4";
8012
+ async function sendEmailCmd(options) {
8013
+ var _a, _b;
8014
+ try {
8015
+ console.log(import_chalk22.default.blue("Sending email...\n"));
8016
+ let apiKey = options.apiKey;
8017
+ if (!apiKey) {
8018
+ const configPath = import_path17.default.join(PROJECT_DIR6, "pinme.toml");
8019
+ if (import_fs_extra12.default.existsSync(configPath)) {
8020
+ const config = import_fs_extra12.default.readFileSync(configPath, "utf-8");
8021
+ const apiKeyMatch = config.match(/api_key\s*=\s*"([^"]+)"/);
8022
+ if (apiKeyMatch) {
8023
+ apiKey = apiKeyMatch[1];
8024
+ }
8025
+ }
8026
+ }
8027
+ let to = options.to;
8028
+ let subject = options.subject;
8029
+ let html = options.html;
8030
+ if (!to || !subject || !html) {
8031
+ const answers = await import_inquirer10.default.prompt([
8032
+ {
8033
+ type: "input",
8034
+ name: "to",
8035
+ message: "To (email address):",
8036
+ validate: (input) => {
8037
+ if (!input.trim()) return "Email address is required";
8038
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input)) {
8039
+ return "Please enter a valid email address";
8040
+ }
8041
+ return true;
8042
+ }
8043
+ },
8044
+ {
8045
+ type: "input",
8046
+ name: "subject",
8047
+ message: "Subject:",
8048
+ validate: (input) => {
8049
+ if (!input.trim()) return "Subject is required";
8050
+ return true;
8051
+ }
8052
+ },
8053
+ {
8054
+ type: "editor",
8055
+ name: "html",
8056
+ message: "HTML content (will open in editor):",
8057
+ default: "<p>Hello!</p>",
8058
+ validate: (input) => {
8059
+ if (!input.trim()) return "HTML content is required";
8060
+ return true;
8061
+ }
8062
+ }
8063
+ ]);
8064
+ to = answers.to;
8065
+ subject = answers.subject;
8066
+ html = answers.html;
8067
+ }
8068
+ if (!apiKey) {
8069
+ const keyAnswer = await import_inquirer10.default.prompt([
8070
+ {
8071
+ type: "input",
8072
+ name: "apiKey",
8073
+ message: "API Key (from project config or create_worker response):",
8074
+ validate: (input) => {
8075
+ if (!input.trim()) return "API Key is required";
8076
+ return true;
8077
+ }
8078
+ }
8079
+ ]);
8080
+ apiKey = keyAnswer.apiKey;
8081
+ }
8082
+ console.log(import_chalk22.default.blue("Sending email..."));
8083
+ const apiUrl = `${API_BASE6}/send_email`;
8084
+ console.log(import_chalk22.default.gray(`API URL: ${apiUrl}`));
8085
+ const response = await axios_default.post(apiUrl, {
8086
+ to,
8087
+ subject,
8088
+ html
8089
+ }, {
8090
+ headers: {
8091
+ "X-API-Key": apiKey,
8092
+ "Content-Type": "application/json"
8093
+ }
8094
+ });
8095
+ const data = response.data;
8096
+ if (data.code === 200) {
8097
+ console.log(import_chalk22.default.green("\n\u2705 Email sent successfully!"));
8098
+ console.log(import_chalk22.default.gray(`
8099
+ To: ${to}`));
8100
+ console.log(import_chalk22.default.gray(`Subject: ${subject}`));
8101
+ } else {
8102
+ const errorMsg = (data == null ? void 0 : data.msg) || "Failed to send email";
8103
+ throw new Error(errorMsg);
8104
+ }
8105
+ process.exit(0);
8106
+ } catch (error) {
8107
+ const errorMsg = ((_b = (_a = error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.msg) || error.message || "Failed to send email";
8108
+ console.error(import_chalk22.default.red(`
8109
+ \u274C Error: ${errorMsg}`));
8110
+ process.exit(1);
8111
+ }
8112
+ }
8113
+
7880
8114
  // bin/index.ts
7881
8115
  import_dotenv.default.config();
7882
8116
  checkNodeVersion();
7883
8117
  function showBanner() {
7884
8118
  console.log(
7885
- import_chalk21.default.cyan(import_figlet5.default.textSync("Pinme", { horizontalLayout: "full" }))
8119
+ import_chalk23.default.cyan(import_figlet5.default.textSync("Pinme", { horizontalLayout: "full" }))
7886
8120
  );
7887
- console.log(import_chalk21.default.cyan("A command-line tool for uploading files to IPFS\n"));
8121
+ console.log(import_chalk23.default.cyan("A command-line tool for uploading files to IPFS\n"));
7888
8122
  }
7889
8123
  var program = new import_commander.Command();
7890
8124
  program.name("pinme").version(version).option("-v, --version", "output the current version");
@@ -7907,6 +8141,8 @@ program.command("save").description("Deploy the project (frontend + backend)").a
7907
8141
  program.command("update-db").description("Execute database migration").action(() => updateDbCmd());
7908
8142
  program.command("update-worker").description("Execute worker migration").action(() => updateWorkerCmd());
7909
8143
  program.command("update-web").description("Deploy frontend to IPFS").action((options) => updateWebCmd(options));
8144
+ program.command("delete").description("Delete a project (Worker, domain, D1 database)").argument("[name]", "Project name").option("-f, --force", "Skip confirmation").action((name, options) => deleteCmd({ name, force: options == null ? void 0 : options.force }));
8145
+ program.command("send-email").description("Send email via PinMe API").option("-t, --to <email>", "Recipient email address").option("-s, --subject <subject>", "Email subject").option("-h, --html <content>", "HTML content").option("--text <content>", "Plain text content (alternative to --html)").option("-k, --api-key <key>", "API Key (or from pinme.toml)").action((options) => sendEmailCmd(options));
7910
8146
  program.command("domain").description("Alias for 'my-domains' command").action(() => myDomainsCmd());
7911
8147
  program.command("list").description("show upload history").option(
7912
8148
  "-l, --limit <number>",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinme",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0-beta.5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -15,8 +15,7 @@
15
15
  "pinme": "./dist/index.js"
16
16
  },
17
17
  "files": [
18
- "dist",
19
- "template"
18
+ "dist"
20
19
  ],
21
20
  "keywords": [
22
21
  "ipfs",