@madewithremy/admin 0.1.51 → 0.1.53

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/prod.js CHANGED
@@ -1023,7 +1023,7 @@ async function dashboardLive(ctx) {
1023
1023
  "GET",
1024
1024
  `/_internal/v2/apps/${ctx.appId}/dashboard`
1025
1025
  );
1026
- return dashboard.liveRelease;
1026
+ return dashboard.liveRelease ? { ...dashboard.liveRelease, primaryUrl: dashboard.primaryUrl } : null;
1027
1027
  }
1028
1028
  async function primaryUrl(ctx) {
1029
1029
  const dashboard = await call(
@@ -1041,7 +1041,8 @@ function summarizeRelease(release) {
1041
1041
  status: release.status,
1042
1042
  buildDurationMs: release.buildDurationMs ?? null,
1043
1043
  publishedAt: release.publishedAt ?? null,
1044
- ...release.previewUrl ? { previewUrl: release.previewUrl } : {}
1044
+ ...release.previewUrl ? { previewUrl: release.previewUrl } : {},
1045
+ ...release.primaryUrl ? { primaryUrl: release.primaryUrl } : {}
1045
1046
  };
1046
1047
  const readers = (release.dataSources ?? []).filter((d) => d.reader);
1047
1048
  if (readers.length > 0 && release.status === "live") {
@@ -1285,7 +1286,7 @@ var releasesHelp = `remy-admin releases \u2014 View and monitor releases.
1285
1286
  Subcommands:
1286
1287
  list List releases, newest first (--limit N, default 20, max 100)
1287
1288
  get Get full details of a specific release
1288
- current Get the currently live release
1289
+ current Get the currently live release, with the address it's served on
1289
1290
  status Check a release's status by id (optionally poll until complete)
1290
1291
  wait Wait for the release built from a commit to go live
1291
1292
 
@@ -1298,8 +1299,11 @@ Usage:
1298
1299
 
1299
1300
  'releases wait' is the "publish and wait until live" primitive. After a
1300
1301
  'git push', run it to block until the pushed commit's release is terminal.
1301
- A push to a non-default branch resolves to status 'preview' and the result
1302
- carries 'previewUrl' \u2014 the gated URL that build is reachable at.
1302
+ A push to the default branch that goes live carries 'primaryUrl', the
1303
+ address the app is served on (its custom domain, else its subdomain, else
1304
+ its id's own host), which 'releases current' also returns. A push to a
1305
+ non-default branch resolves to status 'preview' and the result carries
1306
+ 'previewUrl' \u2014 the gated URL that build is reachable at.
1303
1307
  --commit defaults to the workspace HEAD; abbreviated SHAs (7+ hex chars,
1304
1308
  e.g. from push output) are accepted. It prints one JSON object and sets
1305
1309
  the exit code so you can branch on $? without parsing:
@@ -2008,6 +2012,12 @@ Usage:
2008
2012
  remy-admin domains zone add acmebakery.com --type TXT --host @ --answer "google-site-verification=abc"
2009
2013
 
2010
2014
  Notes:
2015
+ - 'check' says why a subdomain isn't available: reason 'reserved' (the
2016
+ platform's own, never any app's: offer a different name), 'taken' (another
2017
+ app has it, freed only from that app) or 'invalid' (not 1 to 63 letters,
2018
+ digits and hyphens, or shaped like an app's ID). 'set' refuses the same
2019
+ names, with subdomain_not_allowed (reserved or invalid) or unavailable
2020
+ (taken), and says which.
2011
2021
  - 'add' with an apex (e.g. acme.com) auto-creates the www.apex pair and
2012
2022
  returns both. 'remove' on an apex also removes its paired www.
2013
2023
  - 'list'/'records'/'status' read a CF-synced cache that can be up to ~5
@@ -3179,7 +3189,7 @@ Notes:
3179
3189
  - '--app <appId>' targets another app in the same workspace. Every app there is reachable
3180
3190
  with this credential, so it is a targeting flag: the issue lands in THAT app's tracker,
3181
3191
  and 'originAppId' on the row records that this app filed it. Cross-reference it in prose
3182
- as 'app#42'.
3192
+ as 'app#42'. 'remy-admin apps list --search <name>' finds another app's id by its name.
3183
3193
  - 'list' shows what was filed IN an app; 'filed' shows what an app sent OUT to others \u2014
3184
3194
  the whole fan-out in one call instead of one call per app.
3185
3195
  - '--label' repeats ('--label a --label b') or takes a comma-separated list ('--label a,b').
@@ -3196,6 +3206,82 @@ Examples:
3196
3206
  remy-admin issues comment 42 "Fixed in the latest release."
3197
3207
  remy-admin issues close 42 --comment "Already fixed in v3 \u2014 no change needed."`;
3198
3208
 
3209
+ // src/ops/apps.ts
3210
+ var PAGE_SIZE = 500;
3211
+ async function list9(ctx, params = {}) {
3212
+ const words = (params.search ?? "").toLowerCase().split(/\s+/).filter(Boolean);
3213
+ const apps = [];
3214
+ let cursor;
3215
+ while (true) {
3216
+ const page = await call(
3217
+ ctx,
3218
+ "GET",
3219
+ `/_internal/v2/apps${qs({ status: params.status, limit: PAGE_SIZE, cursor })}`
3220
+ );
3221
+ for (const app of page.apps) {
3222
+ const text = `${app.name} ${app.customSubdomain ?? ""}`.toLowerCase();
3223
+ if (words.every((word) => text.includes(word))) {
3224
+ apps.push({
3225
+ appId: app.appId,
3226
+ name: app.name,
3227
+ subdomain: app.customSubdomain,
3228
+ isPublished: app.isPublished,
3229
+ lastDeployedAt: app.lastDeployedAt,
3230
+ createdBy: app.createdBy.name
3231
+ });
3232
+ }
3233
+ }
3234
+ if (!page.nextCursor) {
3235
+ return { apps };
3236
+ }
3237
+ cursor = page.nextCursor;
3238
+ }
3239
+ }
3240
+
3241
+ // src/commands/apps.ts
3242
+ var appsSpecs = {
3243
+ "apps list": {
3244
+ usage: "Usage: remy-admin apps list [--search <words>] [--status draft|published]",
3245
+ flags: {
3246
+ search: { type: "string" },
3247
+ status: { type: "string", choices: ["draft", "published"] }
3248
+ }
3249
+ }
3250
+ };
3251
+ async function appsList(ctx, a) {
3252
+ out(
3253
+ await list9(ctx, {
3254
+ search: a.str("search"),
3255
+ status: a.str("status")
3256
+ })
3257
+ );
3258
+ }
3259
+ var appsHandlers = {
3260
+ "apps list": appsList
3261
+ };
3262
+ var appsHelp = `remy-admin apps \u2014 The apps in this app's workspace.
3263
+
3264
+ Subcommands:
3265
+ list List the workspace's apps, last active first, with their ids
3266
+
3267
+ Usage:
3268
+ remy-admin apps list [--search <words>] [--status draft|published]
3269
+
3270
+ Notes:
3271
+ - Lists every published app in the workspace, and your own drafts (another
3272
+ member's draft isn't listed). This app is in it too.
3273
+ - Each app has appId, name, subdomain (null if it has none), isPublished,
3274
+ lastDeployedAt and createdBy. Its appId is what '--app' takes elsewhere,
3275
+ as in 'issues create --app <appId>'.
3276
+ - '--search' keeps the apps whose name or subdomain contains every word, in
3277
+ any case. When the user names an app, search for it rather than asking for
3278
+ its id; when more than one matches, ask which.
3279
+
3280
+ Examples:
3281
+ remy-admin apps list
3282
+ remy-admin apps list --search "marketing site"
3283
+ remy-admin apps list --status published`;
3284
+
3199
3285
  // src/ops/prerender.ts
3200
3286
  function pages(ctx, params = {}) {
3201
3287
  return call(
@@ -3808,7 +3894,7 @@ async function waitForCandidate(ctx, params) {
3808
3894
  const timeoutMs = params.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
3809
3895
  const outcome = await pollUntil(
3810
3896
  async () => {
3811
- const { dataSources } = await list9(ctx);
3897
+ const { dataSources } = await list10(ctx);
3812
3898
  const source = dataSources.find((s) => s.slug === params.slug);
3813
3899
  if (!source) {
3814
3900
  throw new Error(`Data source "${params.slug}" not found.`);
@@ -3890,7 +3976,7 @@ async function allDocuments(ctx, params) {
3890
3976
  }
3891
3977
  return out2;
3892
3978
  }
3893
- function list9(ctx) {
3979
+ function list10(ctx) {
3894
3980
  return call(ctx, "GET", base(ctx.appId));
3895
3981
  }
3896
3982
  function search2(ctx, params) {
@@ -4009,7 +4095,7 @@ async function waitForMove(ctx, params) {
4009
4095
  const timeoutMs = params.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
4010
4096
  const outcome = await pollUntil(
4011
4097
  async () => {
4012
- const { dataSources } = await list9(ctx);
4098
+ const { dataSources } = await list10(ctx);
4013
4099
  const source2 = dataSources.find((s) => s.slug === params.slug);
4014
4100
  if (!source2) {
4015
4101
  throw new Error(`Data source "${params.slug}" not found.`);
@@ -4210,7 +4296,7 @@ async function uploadManifest(ctx, params) {
4210
4296
  await uploadDirect(token.upload, params.content, "manifest.jsonl");
4211
4297
  return { key: token.key };
4212
4298
  }
4213
- function list10(ctx, params) {
4299
+ function list11(ctx, params) {
4214
4300
  return call(
4215
4301
  ctx,
4216
4302
  "GET",
@@ -4649,7 +4735,7 @@ async function waitForHydration(ctx, params) {
4649
4735
  const timeoutMs = params.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS3;
4650
4736
  const outcome = await pollUntil(
4651
4737
  async () => {
4652
- const { dataSources } = await list9(ctx);
4738
+ const { dataSources } = await list10(ctx);
4653
4739
  const source2 = dataSources.find((s) => s.slug === params.slug);
4654
4740
  if (!source2) {
4655
4741
  throw new Error(`Data source "${params.slug}" not found.`);
@@ -5626,7 +5712,7 @@ async function jobsStart(ctx, a) {
5626
5712
  }
5627
5713
  async function jobsList(ctx, a) {
5628
5714
  const slug = a.str("source");
5629
- out(await list10(ctx, slug ? { slug } : void 0));
5715
+ out(await list11(ctx, slug ? { slug } : void 0));
5630
5716
  }
5631
5717
  async function jobsStatus(ctx, a) {
5632
5718
  const id = a.req("id");
@@ -6643,7 +6729,7 @@ async function dataSourcesAdd(ctx, a) {
6643
6729
  });
6644
6730
  }
6645
6731
  async function dataSourcesList(ctx) {
6646
- out(await list9(ctx));
6732
+ out(await list10(ctx));
6647
6733
  }
6648
6734
  async function dataSourcesStatus(ctx, a) {
6649
6735
  const slug = sourceOf(a);
@@ -6662,7 +6748,7 @@ async function dataSourcesStatus(ctx, a) {
6662
6748
  });
6663
6749
  return;
6664
6750
  }
6665
- const { dataSources: sources2 } = await list9(ctx);
6751
+ const { dataSources: sources2 } = await list10(ctx);
6666
6752
  const source = sources2.find((s) => s.slug === slug);
6667
6753
  if (!source) {
6668
6754
  out({ dataSource: slug, exists: false });
@@ -7525,7 +7611,7 @@ Subcommands:
7525
7611
  numbers list The app's dedicated phone number(s) and their status
7526
7612
  numbers search Search available US numbers by area code / locality
7527
7613
  numbers buy Buy + attach a dedicated number ($1/month \u2014 confirm with the user first)
7528
- numbers release Release the number (permanent \u2014 the rental stops, no refund, ~15-day carrier quarantine)
7614
+ numbers release Release a number (permanent \u2014 the rental stops, no refund, ~15-day carrier quarantine)
7529
7615
  numbers set-name Set/clear the outbound caller-ID display name (CNAM)
7530
7616
  sessions list Call log (web, phone-out, phone-in), newest first
7531
7617
  sessions get One session with full transcript and cost breakdown
@@ -7549,9 +7635,11 @@ Examples:
7549
7635
 
7550
7636
  Notes:
7551
7637
  Buying a number starts a recurring $1/month workspace charge \u2014 never run
7552
- 'numbers buy' without the user's explicit confirmation. The dedicated number
7553
- is both the outbound caller ID for voice.call() and the app's inbound line
7554
- (inbound calls answer the LIVE release's voice agent). A 'pending' number
7638
+ 'numbers buy' without the user's explicit confirmation. An app can hold
7639
+ several numbers (one per tenant, say), up to its workspace's limit
7640
+ (phone_number_limit_reached past it; support raises it). Each is an inbound
7641
+ line (answered by the LIVE release's voice agent) and a caller ID for
7642
+ voice.call(), which takes 'from' once there are several. A 'pending' number
7555
7643
  usually activates within seconds \u2014 poll 'numbers list'. The display name
7556
7644
  (CNAM) is 1-15 letters/numbers/spaces and takes 12-72h to propagate.
7557
7645
  'settings set' merges \u2014 settings you don't pass keep their current values.
@@ -7636,7 +7724,7 @@ Notes:
7636
7724
  and error. Client tools run in the browser, so they have no requestId.`;
7637
7725
 
7638
7726
  // src/ops/tasks.ts
7639
- function list11(ctx, params = {}) {
7727
+ function list12(ctx, params = {}) {
7640
7728
  return call(
7641
7729
  ctx,
7642
7730
  "GET",
@@ -7665,9 +7753,9 @@ var tasksSpecs = {
7665
7753
  positionals: [{ name: "traceId", required: true }]
7666
7754
  }
7667
7755
  };
7668
- async function list12(ctx, a) {
7756
+ async function list13(ctx, a) {
7669
7757
  out(
7670
- await list11(ctx, {
7758
+ await list12(ctx, {
7671
7759
  limit: a.num("limit"),
7672
7760
  cursor: a.str("cursor")
7673
7761
  })
@@ -7677,7 +7765,7 @@ async function get10(ctx, a) {
7677
7765
  out(await get9(ctx, a.req("traceId")));
7678
7766
  }
7679
7767
  var tasksHandlers = {
7680
- "tasks list": list12,
7768
+ "tasks list": list13,
7681
7769
  "tasks get": get10
7682
7770
  };
7683
7771
  var tasksHelp = `remy-admin tasks \u2014 Log of the app's task agents (runTask), kept 90 days.
@@ -8663,7 +8751,7 @@ async function resolveDomainId(ctx, direction, domain) {
8663
8751
  }
8664
8752
  return match.id;
8665
8753
  }
8666
- function list13(ctx, params = {}) {
8754
+ function list14(ctx, params = {}) {
8667
8755
  return call(
8668
8756
  ctx,
8669
8757
  "GET",
@@ -8862,7 +8950,7 @@ var emailSpecs = {
8862
8950
  };
8863
8951
  async function emailList(ctx, a) {
8864
8952
  out(
8865
- await list13(ctx, {
8953
+ await list14(ctx, {
8866
8954
  status: a.str("status"),
8867
8955
  kind: a.str("kind"),
8868
8956
  recipient: a.str("recipient"),
@@ -9033,7 +9121,12 @@ Custom domains \u2014 two independent directions:
9033
9121
  bounces.<domain>) \u2014 hand these to the user to create at
9034
9122
  their DNS host, then 'verify <domain>' to re-check now.
9035
9123
  'list' also returns effectiveSender: what the app currently
9036
- sends as, and which tier that address comes from.
9124
+ sends as, which tier that address comes from, and
9125
+ anyRecipient. anyRecipient false is the shared platform
9126
+ address, which only mails the app's verified users and its
9127
+ workspace's members, in dev and live alike (anyone else is
9128
+ refused with unverified_recipients). A subdomain
9129
+ ('domains set') or a verified sending domain lifts it.
9037
9130
  'inbound-domains' receive mail at the user's own domain via one MX record
9038
9131
  ('check' returns it up front \u2014 no registration needed to
9039
9132
  see it). Apps already receive at *@<slug>.madewithremy.com
@@ -9060,7 +9153,7 @@ Examples:
9060
9153
  `;
9061
9154
 
9062
9155
  // src/ops/cron.ts
9063
- function list14(ctx, params = {}) {
9156
+ function list15(ctx, params = {}) {
9064
9157
  return call(
9065
9158
  ctx,
9066
9159
  "GET",
@@ -9089,7 +9182,7 @@ var cronSpecs = {
9089
9182
  }
9090
9183
  };
9091
9184
  async function cronList(ctx, a) {
9092
- out(await list14(ctx, { runs: a.num("runs") }));
9185
+ out(await list15(ctx, { runs: a.num("runs") }));
9093
9186
  }
9094
9187
  async function cronRun(ctx, a) {
9095
9188
  out(await run2(ctx, a.req("route")));
@@ -9190,7 +9283,7 @@ var POLL_MS5 = 3e3;
9190
9283
  function base7(appId) {
9191
9284
  return `/_internal/v2/apps/${appId}/infra`;
9192
9285
  }
9193
- function list15(ctx, params) {
9286
+ function list16(ctx, params) {
9194
9287
  return call(
9195
9288
  ctx,
9196
9289
  "GET",
@@ -9382,7 +9475,7 @@ async function waitAndReport2(ctx, a, id, phases, summary2, until) {
9382
9475
  }
9383
9476
  }
9384
9477
  async function infraList(ctx, a) {
9385
- out(await list15(ctx, { includeDestroyed: a.bool("include-destroyed") }));
9478
+ out(await list16(ctx, { includeDestroyed: a.bool("include-destroyed") }));
9386
9479
  }
9387
9480
  async function infraGet(ctx, a) {
9388
9481
  out(await get12(ctx, { id: a.req("id") }));
@@ -9874,6 +9967,7 @@ var SPECS = {
9874
9967
  ...methodsSpecs,
9875
9968
  ...dataSpecs,
9876
9969
  ...issuesSpecs,
9970
+ ...appsSpecs,
9877
9971
  ...prerenderSpecs,
9878
9972
  ...filesSpecs,
9879
9973
  ...dataSourcesSpecs,
@@ -9909,6 +10003,7 @@ var HANDLERS = {
9909
10003
  ...methodsHandlers,
9910
10004
  ...dataHandlers,
9911
10005
  ...issuesHandlers,
10006
+ ...appsHandlers,
9912
10007
  ...prerenderHandlers,
9913
10008
  ...filesHandlers,
9914
10009
  ...dataSourcesHandlers,
@@ -9944,6 +10039,7 @@ var GROUP_HELP = {
9944
10039
  methods: methodsHelp,
9945
10040
  data: dataHelp,
9946
10041
  issues: issuesHelp,
10042
+ apps: appsHelp,
9947
10043
  prerender: prerenderHelp,
9948
10044
  files: filesHelp,
9949
10045
  datasources: dataSourcesHelp,
@@ -10030,6 +10126,7 @@ Commands:
10030
10126
  methods List and invoke methods
10031
10127
  data Sync databases between dev and live (lift-from-dev / lift-from-live)
10032
10128
  issues File and manage issues, in this app or another app in the workspace
10129
+ apps The workspace's apps by name, with the ids '--app' takes
10033
10130
  prerender Manage + verify prerendered snapshots served to bots/crawlers
10034
10131
  files Store, retrieve, share (signed links) + manage files in the app's stores
10035
10132
  datasources Build and query searchable document corpora (RAG)
@@ -10067,6 +10164,7 @@ var GROUPS = [
10067
10164
  "methods",
10068
10165
  "data",
10069
10166
  "issues",
10167
+ "apps",
10070
10168
  "prerender",
10071
10169
  "files",
10072
10170
  "datasources",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madewithremy/admin",
3
- "version": "0.1.51",
3
+ "version": "0.1.53",
4
4
  "description": "Admin SDK + CLI for managing production Remy apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",