@lotics/cli 0.181.1 → 0.183.0

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.
@@ -114,13 +114,75 @@ export interface FileUploadResult {
114
114
  error: string;
115
115
  }>;
116
116
  }
117
- /** One finding from a package publish/release extract. */
117
+ /** One finding from the extract behind a starter publish. */
118
118
  export interface ExtractFinding {
119
119
  severity: "error" | "warning" | "info";
120
120
  area: string;
121
121
  message: string;
122
122
  }
123
- /** Advisory knowledge warnings surfaced by install/upgrade (never block). */
123
+ export interface StarterPublishRequest {
124
+ /** The origin apps that ship, in alias-minting order. */
125
+ app_ids: string[];
126
+ /** Live knowledge doc ids to bundle. Omitted keeps the previous version's set; [] drops them all. */
127
+ knowledge_doc_ids?: string[];
128
+ /** First publish only: alias fixes before v1 freezes them. */
129
+ renames?: Array<{
130
+ from: string;
131
+ to: string;
132
+ }>;
133
+ /** First publish only: the listing name; defaults to the workspace's. */
134
+ name?: string;
135
+ /** First publish only: the listing description; defaults to the first app's. */
136
+ description?: string;
137
+ /** First publish only: the listing icon; defaults to the first app's. */
138
+ icon?: string;
139
+ /** First publish only: the listing accent colour; defaults to the first app's. */
140
+ color?: string;
141
+ }
142
+ export interface StarterPublishPreview {
143
+ /** The starter this would publish into, or null when it would mint one. */
144
+ starter_id: string | null;
145
+ starter_name: string;
146
+ version: number;
147
+ apps: Array<{
148
+ alias: string;
149
+ app_id: string;
150
+ name: string;
151
+ }>;
152
+ /** Empty after v1 — the aliases froze there. */
153
+ renamable_aliases: {
154
+ entities: string[];
155
+ fields: string[];
156
+ options: string[];
157
+ roles: string[];
158
+ templates: string[];
159
+ };
160
+ added_aliases: string[];
161
+ changed_artifacts: string[];
162
+ knowledge: {
163
+ added: string[];
164
+ removed: string[];
165
+ changed: string[];
166
+ };
167
+ findings: ExtractFinding[];
168
+ }
169
+ /** A publish is a job; this is the row the requester polls. */
170
+ export interface StarterPublish {
171
+ id: string;
172
+ status: "pending" | "building" | "completed" | "failed";
173
+ /** Null until a first publish completes. */
174
+ starter_id: string | null;
175
+ version_id: string | null;
176
+ version: number | null;
177
+ app_ids: string[];
178
+ building_app_alias: string | null;
179
+ apps_built: number;
180
+ error: string | null;
181
+ created_at: string;
182
+ started_at: string | null;
183
+ finished_at: string | null;
184
+ }
185
+ /** Advisory knowledge warnings surfaced by a copy (never block). */
124
186
  export interface KnowledgeWarnings {
125
187
  /** `knowledge_expects` doc names with no matching workspace doc. */
126
188
  missing_expected_docs: string[];
@@ -344,13 +406,12 @@ export declare class LoticsClient {
344
406
  current_version_id: string | null;
345
407
  }>;
346
408
  /**
347
- * Retire (or `undo` un-retire) a registry package (backs `lotics app
348
- * unpublish` — the endpoint/audit action keep the `retire` name to avoid API
349
- * churn). Retiring refuses NEW installs and hides the package from non-owning
350
- * orgs; existing installations keep working and may still upgrade. Owner-org
351
- * admin-only.
409
+ * Take a starter off the shelf, or `undo` to put it back (backs `opctl
410
+ * starter unpublish`). It hides from non-owning orgs and can no longer be
411
+ * copied; copies already made are unaffected — they never linked back.
412
+ * Owner-org admin-only.
352
413
  */
353
- retirePackage(package_id: string, body: {
414
+ unpublishStarter(starter_id: string, body: {
354
415
  undo: boolean;
355
416
  }): Promise<{
356
417
  id: string;
@@ -364,7 +425,7 @@ export declare class LoticsClient {
364
425
  * A version is an immutable snapshot; the listing is not. Omit a field to
365
426
  * leave it, pass `description: null` to clear it. Owner-org admin-only.
366
427
  */
367
- editPackageListing(package_id: string, body: {
428
+ editStarterListing(starter_id: string, body: {
368
429
  name?: string;
369
430
  description?: string | null;
370
431
  icon?: string | null;
@@ -375,11 +436,8 @@ export declare class LoticsClient {
375
436
  id: string;
376
437
  name: string;
377
438
  description: string | null;
378
- icon?: string | null;
379
- /** Optional for the same reason as `getPackage`'s: an older server omits it. */
380
- theme?: {
381
- color?: string | null;
382
- } | null;
439
+ icon: string | null;
440
+ theme: Record<string, unknown> | null;
383
441
  }>;
384
442
  /**
385
443
  * The starters this organization can copy — Lotics-reviewed ones plus its own,
@@ -392,51 +450,38 @@ export declare class LoticsClient {
392
450
  description: string | null;
393
451
  latest_version: number;
394
452
  is_official: boolean;
395
- owned_by_caller?: boolean;
453
+ owned_by_caller: boolean;
396
454
  }>>;
397
455
  /**
398
456
  * Copy a starter into the current workspace.
399
457
  *
400
458
  * Server-side this scaffolds the schema, creates the templates, docs and
401
- * sample records, creates a BESPOKE app and materializes onto it — then stops.
402
- * It deploys nothing: a starter ships source only, and the source has to be
403
- * built where codegen can bake THIS workspace's field ids. `bundle_url` is a
404
- * presigned GET of that source, and finishing the job is the caller's half.
459
+ * sample records, creates every app the starter carries and deploys each
460
+ * from its prebuilt dist — no build anywhere. `apps` reports each deploy;
461
+ * one that failed carries its `error` and the copy is complete around it.
405
462
  * Admin-only.
406
463
  */
407
464
  instantiateStarter(starter_id: string, body: {
408
465
  version?: number;
409
466
  no_sample_data?: boolean;
410
467
  adopt?: boolean;
411
- /** Ask the server to build and deploy the copy, so this machine needs no Node. */
412
- build_on_server?: boolean;
413
468
  }): Promise<{
414
- app_id: string | null;
469
+ /** Each app's deploy, in contract order. `error` set and `deployed` null when one did not land. */
470
+ apps: Array<{
471
+ alias: string;
472
+ app_id: string;
473
+ name: string;
474
+ deployed: {
475
+ version_id: string;
476
+ version_number: number;
477
+ } | null;
478
+ error: string | null;
479
+ }>;
415
480
  starter_id: string;
416
481
  version: number;
417
- bundle_url: string | null;
418
- /**
419
- * The version the SERVER deployed, when it did.
420
- *
421
- * Optional in this type on purpose: a server that predates the field omits
422
- * it entirely, and it is absent rather than null. Callers must treat "not
423
- * there" and "null" alike and build locally — assuming the request was
424
- * honoured would report success over an app nobody built.
425
- */
426
- deployed?: {
427
- version_id: string;
428
- version_number: number;
429
- } | null;
430
- /**
431
- * Why the server built nothing, when it was asked to and `deployed` is null.
432
- * Absent from an older server's response for the same reason as `deployed`.
433
- */
434
- build_error?: string | null;
435
482
  binding: Record<string, Record<string, string>>;
436
483
  sample_record_ids: Record<string, string[]>;
437
- knowledge_warnings: {
438
- missing_expected_docs: string[];
439
- };
484
+ knowledge_warnings: KnowledgeWarnings;
440
485
  }>;
441
486
  /**
442
487
  * Which starter this app is the origin of. 404 when it has published none.
@@ -479,34 +524,26 @@ export declare class LoticsClient {
479
524
  * Fetch a registry starter's metadata (`latest_version` and the Lotics-backed
480
525
  * `is_official` trust badge). Admin-only; cross-tenant by id.
481
526
  */
482
- getPackage(package_id: string): Promise<{
527
+ getStarter(starter_id: string): Promise<{
483
528
  id: string;
484
529
  name: string;
485
530
  description: string | null;
486
531
  latest_version: number;
487
532
  is_official: boolean;
488
533
  retired_at: string | null;
489
- /** Absent from a pre-deploy server — treat undefined as not-owned (the badge under-claims, never over-claims). */
490
- owned_by_caller?: boolean;
491
- /**
492
- * The shelf tile, which every copy's app inherits.
493
- *
494
- * Optional for the same reason `owned_by_caller` is: a server that predates
495
- * the field answers without it, and a CLI newer than the deployment it is
496
- * talking to must read that as "not stated" rather than "not set".
497
- */
498
- icon?: string | null;
499
- theme?: Record<string, unknown> | null;
534
+ /** Whether the CALLING org owns it — the copy-time trust badge, without exposing the owner's org id. */
535
+ owned_by_caller: boolean;
536
+ /** The shelf tile. Null = unset; a copy's app tiles come from the contract. */
537
+ icon: string | null;
538
+ theme: Record<string, unknown> | null;
500
539
  created_at: string;
501
540
  updated_at: string;
502
541
  }>;
503
- /** Version history newest-first (no contract payloads) — backs `opctl package show`. Admin-only. */
504
- listPackageVersions(package_id: string): Promise<{
542
+ /** Version history newest-first (no contract payloads) — backs `opctl starter show`. Admin-only. */
543
+ listStarterVersions(starter_id: string): Promise<{
505
544
  versions: Array<{
506
545
  version: number;
507
546
  changelog: string | null;
508
- channel: "release" | "dev";
509
- yanked_at: string | null;
510
547
  created_at: string;
511
548
  }>;
512
549
  }>;
@@ -525,120 +562,28 @@ export declare class LoticsClient {
525
562
  };
526
563
  }>>;
527
564
  /**
528
- * Preview a release — the dry run behind `opctl app release`. Runs the
529
- * binding-aware extract of the origin (aliases stable through the app's current
530
- * binding) and reports the next version number, the new + changed aliases, the
531
- * bundled-knowledge delta, and any extract findings (an `error` blocks the
532
- * apply). An optional `knowledge` declaration (from the pulled app manifest)
533
- * re-declares the bundle set — added/dropped/changed docs surface in the delta;
534
- * omitted, the current corpus is reconstructed from the pin. No writes. Admin,
535
- * owning-org only.
536
- */
537
- previewPackageRelease(app_id: string, opts?: {
538
- /** alias → doc_id re-declaring the bundled-knowledge set (from the manifest). */
539
- knowledge?: Array<{
540
- alias: string;
541
- doc_id: string;
542
- }>;
543
- }): Promise<{
544
- package_id: string;
545
- version: number;
546
- added_aliases: string[];
547
- changed_artifacts: string[];
548
- /** Absent from a pre-declaration server (deploy skew) — treat as empty delta. */
549
- knowledge?: {
550
- added: string[];
551
- removed: string[];
552
- changed: string[];
553
- };
554
- findings: ExtractFinding[];
555
- }>;
556
- /**
557
- * Release — snapshot the origin app into the next registry version. The server
558
- * binding-aware-extracts it, repackages its deployed source + dist as the
559
- * bundle, publishes the next `release`-channel version with the changelog, and
560
- * re-pins the origin. An optional `knowledge` declaration re-declares the
561
- * bundled-knowledge set (added/dropped/re-snapshotted docs; omitted preserves
562
- * the current corpus). Error findings from extract surface as a 409; a
563
- * missing/archived declared doc is a 400, a foreign-package doc a 409. Admin,
564
- * owning-org only. Backs `opctl app release --yes`.
565
- */
566
- releasePackage(app_id: string, body: {
567
- changelog: string;
568
- /** alias → doc_id re-declaring the bundled-knowledge set (from the manifest). */
569
- knowledge?: Array<{
570
- alias: string;
571
- doc_id: string;
572
- }>;
573
- }): Promise<{
574
- package_id: string;
575
- version: number;
576
- added_aliases: string[];
577
- changed_artifacts: string[];
578
- /** Absent from a pre-declaration server (deploy skew) — treat as empty delta. */
579
- knowledge?: {
580
- added: string[];
581
- removed: string[];
582
- changed: string[];
583
- };
584
- }>;
565
+ * Preview publishing a set of this workspace's apps as one starter version —
566
+ * the GET behind `opctl starter publish` (no `--yes`). The server runs the
567
+ * same extraction the publish runs and reports which starter it would
568
+ * release into (null: it would mint one), the next version, the aliases a
569
+ * first publish can still rename, the diff against the current version, the
570
+ * knowledge delta, and the findings (an `error` blocks the publish). No
571
+ * writes. Admin-only.
572
+ */
573
+ previewStarterPublish(opts: StarterPublishRequest): Promise<StarterPublishPreview>;
585
574
  /**
586
- * Dry-run preview of a first-release — the `GET` behind `opctl app publish`
587
- * (no `--yes`), the publish-side analogue of `previewPackageRelease`. The
588
- * server runs the same fresh-alias extract + `src/` scan the apply runs
589
- * (through any `renames`) and returns the package name it would mint, the
590
- * auto-minted RENAMABLE aliases (the exact `--rename` keys), and the extract
591
- * findings (an `error` blocks the apply). No writes. Admin-only.
575
+ * Publish this workspace's apps as a starter version — a JOB, because every
576
+ * app is built once against sentinel field keys and eleven builds outlast a
577
+ * request. Everything a request can refuse is refused here with nothing
578
+ * written: a blocking finding or another publish still running for this
579
+ * org (409), a missing deploy or a bad declaration (400). The response is
580
+ * the job to poll with `getStarterPublish`. Admin-only.
592
581
  */
593
- previewPublishAppPackage(app_id: string, opts?: {
594
- renames?: Array<{
595
- from: string;
596
- to: string;
597
- }>;
598
- /** alias → doc_id for the app's package-managed knowledge (from its manifest). */
599
- knowledge?: Array<{
600
- alias: string;
601
- doc_id: string;
602
- }>;
603
- }): Promise<{
604
- app_id: string;
605
- package_name: string;
606
- renamable_aliases: {
607
- entities: string[];
608
- fields: string[];
609
- options: string[];
610
- roles: string[];
611
- templates: string[];
612
- workflows: string[];
613
- };
614
- findings: ExtractFinding[];
615
- }>;
616
- /**
617
- * First-release apply — mint a package from a BESPOKE app and publish v1 in one
618
- * call (the `POST` behind `opctl app publish --yes`). The server extracts an
619
- * alias-keyed contract from the app (fresh aliases; `renames` fixes them before
620
- * v1 freezes), creates the registry package (name/description from the app),
621
- * publishes v1 from the app's deployed source + dist, and pins the origin as
622
- * installation #1. Error findings from extract surface as a 409. An
623
- * already-linked app must use `releasePackage` instead. Admin-only. Backs
624
- * `opctl app publish <app_id>`.
625
- */
626
- publishAppAsPackage(app_id: string, body: {
627
- renames?: Array<{
628
- from: string;
629
- to: string;
630
- }>;
582
+ requestStarterPublish(body: StarterPublishRequest & {
631
583
  changelog?: string | null;
632
- /** alias → doc_id for the app's package-managed knowledge (from its manifest). */
633
- knowledge?: Array<{
634
- alias: string;
635
- doc_id: string;
636
- }>;
637
- }): Promise<{
638
- package_id: string;
639
- version: number;
640
- app_id: string;
641
- }>;
584
+ }): Promise<StarterPublish>;
585
+ /** The state of a publish: which app is building, and the version once every dist is in. */
586
+ getStarterPublish(publish_id: string): Promise<StarterPublish>;
642
587
  /**
643
588
  * Resolve the display name + fields (incl. select options) of the given tables
644
589
  * — the schema `lotics app codegen` turns into the runtime `.lotics/app_fields.ts`
@@ -324,14 +324,13 @@ export class LoticsClient {
324
324
  return this.request("POST", "/v1/apps", body);
325
325
  }
326
326
  /**
327
- * Retire (or `undo` un-retire) a registry package (backs `lotics app
328
- * unpublish` — the endpoint/audit action keep the `retire` name to avoid API
329
- * churn). Retiring refuses NEW installs and hides the package from non-owning
330
- * orgs; existing installations keep working and may still upgrade. Owner-org
331
- * admin-only.
327
+ * Take a starter off the shelf, or `undo` to put it back (backs `opctl
328
+ * starter unpublish`). It hides from non-owning orgs and can no longer be
329
+ * copied; copies already made are unaffected — they never linked back.
330
+ * Owner-org admin-only.
332
331
  */
333
- async retirePackage(package_id, body) {
334
- return this.request("POST", `/v1/packages/${encodeURIComponent(package_id)}/retire`, body);
332
+ async unpublishStarter(starter_id, body) {
333
+ return this.request("POST", `/v1/starters/${encodeURIComponent(starter_id)}/unpublish`, body);
335
334
  }
336
335
  /**
337
336
  * Edit a starter's registry listing — the name and description a stranger
@@ -340,13 +339,12 @@ export class LoticsClient {
340
339
  * A version is an immutable snapshot; the listing is not. Omit a field to
341
340
  * leave it, pass `description: null` to clear it. Owner-org admin-only.
342
341
  */
343
- async editPackageListing(package_id, body) {
344
- return this.request("POST", `/v1/packages/${encodeURIComponent(package_id)}/listing`, body);
342
+ async editStarterListing(starter_id, body) {
343
+ return this.request("POST", `/v1/starters/${encodeURIComponent(starter_id)}/listing`, body);
345
344
  }
346
- // --- Packages (registry reads + installations) ---
347
- // Authoring is server-side: apps via `POST /v1/apps/{id}/package-publish|release`,
348
- // content packages via the `publish_content`/`release_content` tools. There is no
349
- // client-side create-package / upload-bundle path.
345
+ // --- Starters (registry reads + copies) ---
346
+ // Authoring is server-side, through the publish job (`requestStarterPublish`).
347
+ // There is no client-side create-starter / upload-bundle path.
350
348
  /**
351
349
  * The starters this organization can copy — Lotics-reviewed ones plus its own,
352
350
  * never a catalogue of everything published. The server returns exactly what
@@ -359,10 +357,9 @@ export class LoticsClient {
359
357
  * Copy a starter into the current workspace.
360
358
  *
361
359
  * Server-side this scaffolds the schema, creates the templates, docs and
362
- * sample records, creates a BESPOKE app and materializes onto it — then stops.
363
- * It deploys nothing: a starter ships source only, and the source has to be
364
- * built where codegen can bake THIS workspace's field ids. `bundle_url` is a
365
- * presigned GET of that source, and finishing the job is the caller's half.
360
+ * sample records, creates every app the starter carries and deploys each
361
+ * from its prebuilt dist — no build anywhere. `apps` reports each deploy;
362
+ * one that failed carries its `error` and the copy is complete around it.
366
363
  * Admin-only.
367
364
  */
368
365
  async instantiateStarter(starter_id, body) {
@@ -400,12 +397,12 @@ export class LoticsClient {
400
397
  * Fetch a registry starter's metadata (`latest_version` and the Lotics-backed
401
398
  * `is_official` trust badge). Admin-only; cross-tenant by id.
402
399
  */
403
- async getPackage(package_id) {
404
- return this.request("GET", `/v1/packages/${encodeURIComponent(package_id)}`);
400
+ async getStarter(starter_id) {
401
+ return this.request("GET", `/v1/starters/${encodeURIComponent(starter_id)}`);
405
402
  }
406
- /** Version history newest-first (no contract payloads) — backs `opctl package show`. Admin-only. */
407
- async listPackageVersions(package_id) {
408
- return this.request("GET", `/v1/packages/${encodeURIComponent(package_id)}/versions`);
403
+ /** Version history newest-first (no contract payloads) — backs `opctl starter show`. Admin-only. */
404
+ async listStarterVersions(starter_id) {
405
+ return this.request("GET", `/v1/starters/${encodeURIComponent(starter_id)}/versions`);
409
406
  }
410
407
  /**
411
408
  * Workspace-wide dangling-reference sweep — active app/workflow artifacts
@@ -415,68 +412,51 @@ export class LoticsClient {
415
412
  async getWorkspaceDanglingReferences() {
416
413
  return this.request("GET", "/v1/workspaces/dangling-references");
417
414
  }
415
+ // --- Starter publishing (the authoring verbs; copying is `instantiateStarter`) ---
418
416
  /**
419
- * Preview a release — the dry run behind `opctl app release`. Runs the
420
- * binding-aware extract of the origin (aliases stable through the app's current
421
- * binding) and reports the next version number, the new + changed aliases, the
422
- * bundled-knowledge delta, and any extract findings (an `error` blocks the
423
- * apply). An optional `knowledge` declaration (from the pulled app manifest)
424
- * re-declares the bundle set — added/dropped/changed docs surface in the delta;
425
- * omitted, the current corpus is reconstructed from the pin. No writes. Admin,
426
- * owning-org only.
417
+ * Preview publishing a set of this workspace's apps as one starter version —
418
+ * the GET behind `opctl starter publish` (no `--yes`). The server runs the
419
+ * same extraction the publish runs and reports which starter it would
420
+ * release into (null: it would mint one), the next version, the aliases a
421
+ * first publish can still rename, the diff against the current version, the
422
+ * knowledge delta, and the findings (an `error` blocks the publish). No
423
+ * writes. Admin-only.
427
424
  */
428
- async previewPackageRelease(app_id, opts = {}) {
425
+ async previewStarterPublish(opts) {
429
426
  const params = new URLSearchParams();
430
- if (opts.knowledge !== undefined && opts.knowledge.length > 0) {
431
- params.set("knowledge", JSON.stringify(opts.knowledge));
432
- }
433
- const query = params.toString();
434
- return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/package-release${query ? `?${query}` : ""}`);
435
- }
436
- /**
437
- * Release — snapshot the origin app into the next registry version. The server
438
- * binding-aware-extracts it, repackages its deployed source + dist as the
439
- * bundle, publishes the next `release`-channel version with the changelog, and
440
- * re-pins the origin. An optional `knowledge` declaration re-declares the
441
- * bundled-knowledge set (added/dropped/re-snapshotted docs; omitted preserves
442
- * the current corpus). Error findings from extract surface as a 409; a
443
- * missing/archived declared doc is a 400, a foreign-package doc a 409. Admin,
444
- * owning-org only. Backs `opctl app release --yes`.
445
- */
446
- async releasePackage(app_id, body) {
447
- return this.request("POST", `/v1/apps/${encodeURIComponent(app_id)}/package-release`, body);
448
- }
449
- /**
450
- * Dry-run preview of a first-release — the `GET` behind `opctl app publish`
451
- * (no `--yes`), the publish-side analogue of `previewPackageRelease`. The
452
- * server runs the same fresh-alias extract + `src/` scan the apply runs
453
- * (through any `renames`) and returns the package name it would mint, the
454
- * auto-minted RENAMABLE aliases (the exact `--rename` keys), and the extract
455
- * findings (an `error` blocks the apply). No writes. Admin-only.
456
- */
457
- async previewPublishAppPackage(app_id, opts = {}) {
458
- const params = new URLSearchParams();
459
- if (opts.knowledge !== undefined && opts.knowledge.length > 0) {
460
- params.set("knowledge", JSON.stringify(opts.knowledge));
461
- }
462
- if (opts.renames !== undefined && opts.renames.length > 0) {
427
+ params.set("app_ids", opts.app_ids.join(","));
428
+ if (opts.knowledge_doc_ids !== undefined)
429
+ params.set("knowledge_doc_ids", opts.knowledge_doc_ids.join(","));
430
+ if (opts.renames !== undefined && opts.renames.length > 0)
463
431
  params.set("renames", JSON.stringify(opts.renames));
464
- }
465
- const query = params.toString();
466
- return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/package-publish${query ? `?${query}` : ""}`);
432
+ if (opts.name !== undefined)
433
+ params.set("name", opts.name);
434
+ if (opts.description !== undefined)
435
+ params.set("description", opts.description);
436
+ if (opts.icon !== undefined)
437
+ params.set("icon", opts.icon);
438
+ if (opts.color !== undefined)
439
+ params.set("color", opts.color);
440
+ return this.request("GET", `/v1/starters/publish-preview?${params.toString()}`);
441
+ }
442
+ /**
443
+ * Publish this workspace's apps as a starter version — a JOB, because every
444
+ * app is built once against sentinel field keys and eleven builds outlast a
445
+ * request. Everything a request can refuse is refused here with nothing
446
+ * written: a blocking finding or another publish still running for this
447
+ * org (409), a missing deploy or a bad declaration (400). The response is
448
+ * the job to poll with `getStarterPublish`. Admin-only.
449
+ */
450
+ async requestStarterPublish(body) {
451
+ const { color, ...rest } = body;
452
+ return this.request("POST", "/v1/starters/publishes", {
453
+ ...rest,
454
+ ...(color !== undefined ? { theme: { color } } : {}),
455
+ });
467
456
  }
468
- /**
469
- * First-release apply — mint a package from a BESPOKE app and publish v1 in one
470
- * call (the `POST` behind `opctl app publish --yes`). The server extracts an
471
- * alias-keyed contract from the app (fresh aliases; `renames` fixes them before
472
- * v1 freezes), creates the registry package (name/description from the app),
473
- * publishes v1 from the app's deployed source + dist, and pins the origin as
474
- * installation #1. Error findings from extract surface as a 409. An
475
- * already-linked app must use `releasePackage` instead. Admin-only. Backs
476
- * `opctl app publish <app_id>`.
477
- */
478
- async publishAppAsPackage(app_id, body) {
479
- return this.request("POST", `/v1/apps/${encodeURIComponent(app_id)}/package-publish`, body);
457
+ /** The state of a publish: which app is building, and the version once every dist is in. */
458
+ async getStarterPublish(publish_id) {
459
+ return this.request("GET", `/v1/starters/publishes/${encodeURIComponent(publish_id)}`);
480
460
  }
481
461
  /**
482
462
  * Resolve the display name + fields (incl. select options) of the given tables