@mybase-dev/cli 1.0.4 → 1.0.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.
Files changed (2) hide show
  1. package/dist/mybase.js +60 -22
  2. package/package.json +1 -1
package/dist/mybase.js CHANGED
@@ -139,7 +139,7 @@ function parseDotenv(text) {
139
139
  // package.json
140
140
  var package_default = {
141
141
  name: "@mybase-dev/cli",
142
- version: "1.0.4",
142
+ version: "1.0.5",
143
143
  description: "The mybase CLI: projects, keys, cron, queues, cache, rate limits, analytics, docs, and agent setup for a self-hosted mybase.",
144
144
  type: "module",
145
145
  repository: {
@@ -305,6 +305,31 @@ function parseDelay(value) {
305
305
  return Math.round(Number(m[1]) * UNITS[m[2]]);
306
306
  }
307
307
 
308
+ // src/service-enable.ts
309
+ async function linkedEnvs(project) {
310
+ const overview = await api(`/projects/${encodeURIComponent(project)}/secrets`).catch(() => null);
311
+ return overview?.envs.filter((e) => e.linked).map((e) => e.name) ?? [];
312
+ }
313
+ async function enableService(project, id, flags) {
314
+ const envs = flags.has("no-link") ? [] : await linkedEnvs(project);
315
+ let link = envs.length > 0 && flags.has("link");
316
+ if (envs.length > 0 && !link && !jsonMode && process.stdin.isTTY) {
317
+ const answer = prompt(`Add the ${id} keys to the linked secrets envs (${envs.join(", ")})? [Y/n]`);
318
+ link = !answer?.trim() || /^y/i.test(answer.trim());
319
+ }
320
+ const path = `/projects/${encodeURIComponent(project)}/services/${id}`;
321
+ const result = await api(path, link ? { method: "PUT", body: JSON.stringify({ link: true }) } : { method: "PUT" });
322
+ return { result, linked: link ? envs : [] };
323
+ }
324
+ function printLinked(project, linked, flags) {
325
+ if (linked.length > 0)
326
+ console.log(`
327
+ Keys added to the linked secrets envs: ${linked.join(", ")} (mybase run -p ${project} -e ${linked[0]} -- \u2026)`);
328
+ else if (flags.has("link"))
329
+ console.log(`
330
+ No linked secrets envs yet: mybase secrets link -p ${project} -e prod`);
331
+ }
332
+
308
333
  // src/cron.ts
309
334
  var cronUsage = ` cron enable <project> Turn on cron for a project and print its signing secret
310
335
  cron disable <project> [--yes] Turn it off, deleting every job and its history
@@ -388,12 +413,13 @@ async function cron(sub, args) {
388
413
  switch (sub) {
389
414
  case "enable": {
390
415
  const p = need(project, "project name");
391
- await api(`/projects/${encodeURIComponent(p)}/services/cron`, { method: "PUT" });
416
+ const { linked } = await enableService(p, "cron", flags);
392
417
  const secret = await api(`/projects/${encodeURIComponent(p)}/cron/secret`);
393
- print({ enabled: "cron", project: p, ...secret }, () => {
418
+ print({ enabled: "cron", project: p, linked, ...secret }, () => {
394
419
  console.log(`Cron enabled for "${p}"
395
420
  `);
396
421
  printSecret(secret);
422
+ printLinked(p, linked, flags);
397
423
  });
398
424
  return true;
399
425
  }
@@ -881,12 +907,14 @@ async function analytics(sub, args) {
881
907
  switch (sub) {
882
908
  case "enable": {
883
909
  const p = need2(project, "project name");
884
- await api(`/projects/${encodeURIComponent(p)}/services/analytics`, { method: "PUT" });
910
+ const flags = parseArgs(args).flags;
911
+ const { linked } = await enableService(p, "analytics", flags);
885
912
  const settings = await api(`${base(p)}/settings`);
886
- print({ enabled: "analytics", project: p, ...settings }, () => {
913
+ print({ enabled: "analytics", project: p, linked, ...settings }, () => {
887
914
  console.log(`Analytics enabled for "${p}"
888
915
  `);
889
916
  printSettings(p, settings);
917
+ printLinked(p, linked, flags);
890
918
  });
891
919
  return true;
892
920
  }
@@ -1351,13 +1379,14 @@ async function cache(sub, args) {
1351
1379
  switch (sub) {
1352
1380
  case "enable": {
1353
1381
  const p = need(project, "project name");
1354
- const res = await api(`/projects/${encodeURIComponent(p)}/services/cache`, { method: "PUT" });
1355
- if (res.service !== "cache")
1382
+ const { result: res, linked } = await enableService(p, "cache", flags);
1383
+ if (res?.service !== "cache")
1356
1384
  throw new Error("unexpected answer from the API");
1357
- print({ enabled: "cache", project: p, ...res.credentials }, () => {
1385
+ print({ enabled: "cache", project: p, linked, ...res.credentials }, () => {
1358
1386
  console.log(`Cache enabled for "${p}"
1359
1387
  `);
1360
1388
  printCredentials(p, res.credentials);
1389
+ printLinked(p, linked, flags);
1361
1390
  });
1362
1391
  return true;
1363
1392
  }
@@ -1419,12 +1448,13 @@ async function captcha(sub, args) {
1419
1448
  switch (sub) {
1420
1449
  case "enable": {
1421
1450
  const p = need(project, "project name");
1422
- await api(`/projects/${encodeURIComponent(p)}/services/captcha`, { method: "PUT" });
1451
+ const { linked } = await enableService(p, "captcha", flags);
1423
1452
  const s = await api(base3(p));
1424
- print({ enabled: "captcha", project: p, ...s }, () => {
1453
+ print({ enabled: "captcha", project: p, linked, ...s }, () => {
1425
1454
  console.log(`Captcha enabled for "${p}"
1426
1455
  `);
1427
1456
  printSettings2(p, s);
1457
+ printLinked(p, linked, flags);
1428
1458
  });
1429
1459
  return true;
1430
1460
  }
@@ -1570,12 +1600,13 @@ async function queue(sub, args) {
1570
1600
  switch (sub) {
1571
1601
  case "enable": {
1572
1602
  const p = need(project, "project name");
1573
- await api(`/projects/${encodeURIComponent(p)}/services/queue`, { method: "PUT" });
1603
+ const { linked } = await enableService(p, "queue", flags);
1574
1604
  const settings = await api(base4(p));
1575
- print({ enabled: "queue", project: p, ...settings }, () => {
1605
+ print({ enabled: "queue", project: p, linked, ...settings }, () => {
1576
1606
  console.log(`Queues enabled for "${p}"
1577
1607
  `);
1578
1608
  printUsage(p, settings);
1609
+ printLinked(p, linked, flags);
1579
1610
  });
1580
1611
  return true;
1581
1612
  }
@@ -1770,12 +1801,13 @@ async function vector(sub, args) {
1770
1801
  switch (sub) {
1771
1802
  case "enable": {
1772
1803
  const p = need(project, "project name");
1773
- await api(`/projects/${encodeURIComponent(p)}/services/vector`, { method: "PUT" });
1804
+ const { linked } = await enableService(p, "vector", flags);
1774
1805
  const settings = await api(base5(p));
1775
- print({ enabled: "vector", project: p, ...settings }, () => {
1806
+ print({ enabled: "vector", project: p, linked, ...settings }, () => {
1776
1807
  console.log(`Vector search enabled for "${p}"
1777
1808
  `);
1778
1809
  printUsage2(p, settings);
1810
+ printLinked(p, linked, flags);
1779
1811
  });
1780
1812
  return true;
1781
1813
  }
@@ -1956,12 +1988,13 @@ async function ratelimit(sub, args) {
1956
1988
  switch (sub) {
1957
1989
  case "enable": {
1958
1990
  const p = need(project, "project name");
1959
- await api(`/projects/${encodeURIComponent(p)}/services/ratelimit`, { method: "PUT" });
1991
+ const { linked } = await enableService(p, "ratelimit", flags);
1960
1992
  const settings = await api(base6(p));
1961
- print({ enabled: "ratelimit", project: p, ...settings }, () => {
1993
+ print({ enabled: "ratelimit", project: p, linked, ...settings }, () => {
1962
1994
  console.log(`Rate limits enabled for "${p}"
1963
1995
  `);
1964
1996
  printUsage3(p, settings);
1997
+ printLinked(p, linked, flags);
1965
1998
  });
1966
1999
  return true;
1967
2000
  }
@@ -2063,8 +2096,11 @@ var secretsUsage = ` secrets enable <project> Turn on secrets (dev, stagi
2063
2096
  secrets history [--limit 20] Revisions, newest first
2064
2097
  secrets restore <revision> [--yes] Put values back as they were after <revision>
2065
2098
  secrets link --env <env,\u2026> [--yes] Rotate the project's DB/S3/cache credentials and keep them
2066
- in these envs (DATABASE_URL, S3_*, REDIS_URL, MYBASE_URL)
2099
+ in these envs (DATABASE_URL, S3_*, REDIS_URL, MYBASE_URL), with
2100
+ every service's keys (MYBASE_API_KEY, MYBASE_CRON_SECRET, \u2026)
2067
2101
  secrets unlink [--yes] Remove the credentials from the env (they stay valid)
2102
+ \`<service> enable\` asks to add that service's keys to linked
2103
+ envs (--link / --no-link to skip the question)
2068
2104
  Project/env: -p/--project, -e/--env, else MYBASE_PROJECT/MYBASE_ENV,
2069
2105
  else \`secrets setup\` for this directory`;
2070
2106
  var expandShortFlags = (args) => args.map((a) => a === "-p" ? "--project" : a === "-e" ? "--env" : a);
@@ -2240,7 +2276,7 @@ async function secrets(sub, args) {
2240
2276
  case "link": {
2241
2277
  const { project, env } = await target(flags);
2242
2278
  const envs = env.split(",").map((e) => e.trim()).filter(Boolean);
2243
- confirm(yes, `This rotates the credentials of "${project}" (database password, storage key, and cache password if the cache is on) and stores the new ones in ${envs.join(", ")} plus any env linked before. Apps still using the old credentials will stop working.`, project, "the project name");
2279
+ confirm(yes, `This rotates the credentials of "${project}" (database password, storage key, cache password if the cache is on, and the API key link made before) and stores the new ones, with the other services' keys, in ${envs.join(", ")} plus any env linked before. Apps still using the old credentials will stop working.`, project, "the project name");
2244
2280
  const result = await api(`${base7(project)}/link`, { method: "POST", body: JSON.stringify({ envs }) });
2245
2281
  print(result, () => {
2246
2282
  console.log(`Rotated and stored in ${result.envs.join(", ")}: ${result.keys.join(", ")}`);
@@ -2300,9 +2336,9 @@ async function search(sub, args) {
2300
2336
  switch (sub) {
2301
2337
  case "enable": {
2302
2338
  const p = need(project, "project name");
2303
- await api(servicePath(p), { method: "PUT" });
2339
+ const { linked } = await enableService(p, "search", flags);
2304
2340
  const searchUrl = `${API_URL}/search/${p}`;
2305
- print({ enabled: "search", project: p, searchUrl, fetchUrl: `${searchUrl}/fetch` }, () => {
2341
+ print({ enabled: "search", project: p, linked, searchUrl, fetchUrl: `${searchUrl}/fetch` }, () => {
2306
2342
  console.log(`Web search enabled for "${p}"
2307
2343
  `);
2308
2344
  console.log(` search URL ${searchUrl}?q=\u2026`);
@@ -2313,6 +2349,7 @@ async function search(sub, args) {
2313
2349
  `);
2314
2350
  console.log(` const web = createSearchClient({ apiUrl: "${API_URL}", project: "${p}", apiKey: process.env.MYBASE_API_KEY! })`);
2315
2351
  console.log(` const { results } = await web.search("\u2026") // or searchTools(web) for an LLM agent`);
2352
+ printLinked(p, linked, flags);
2316
2353
  });
2317
2354
  return true;
2318
2355
  }
@@ -5408,15 +5445,16 @@ async function users(sub, args) {
5408
5445
  switch (sub) {
5409
5446
  case "enable": {
5410
5447
  const p = need(project, "project name");
5411
- await api(`/projects/${encodeURIComponent(p)}/services/users`, { method: "PUT" });
5448
+ const { linked } = await enableService(p, "users", flags);
5412
5449
  const o = await api(base8(p));
5413
- print({ enabled: "users", project: p, ...o }, () => {
5450
+ print({ enabled: "users", project: p, linked, ...o }, () => {
5414
5451
  console.log(`Users enabled for "${p}". Better Auth's tables go in the "${o.schema}" schema.
5415
5452
  `);
5416
5453
  console.log("Next:");
5417
5454
  console.log(` 1. An API key for the app: mybase token create ${p}-auth --project ${p} --perm users:write,cache:write`);
5418
5455
  console.log(` 2. The cache, for sessions: mybase cache enable ${p}`);
5419
5456
  console.log(` 3. An auth.ts to start from: mybase users init ${p}`);
5457
+ printLinked(p, linked, flags);
5420
5458
  });
5421
5459
  return true;
5422
5460
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mybase-dev/cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "The mybase CLI: projects, keys, cron, queues, cache, rate limits, analytics, docs, and agent setup for a self-hosted mybase.",
5
5
  "type": "module",
6
6
  "repository": {